@@ -8,6 +8,7 @@ use rustc_middle::ty::{self as mir_ty, TyCtxt};
88use crate :: analyze:: did_cache:: DefIdCache ;
99use crate :: annot:: AnnotFormula ;
1010use crate :: chc;
11+ use crate :: refine:: TypeBuilder ;
1112use crate :: rty;
1213
1314#[ derive( Debug , Clone ) ]
@@ -127,6 +128,7 @@ pub struct AnnotFnTranslator<'tcx> {
127128 generic_args : mir_ty:: GenericArgsRef < ' tcx > ,
128129
129130 def_ids : DefIdCache < ' tcx > ,
131+ type_builder : TypeBuilder < ' tcx > ,
130132 env : HashMap < HirId , chc:: Term < rty:: FunctionParamIdx > > ,
131133}
132134
@@ -138,13 +140,15 @@ impl<'tcx> AnnotFnTranslator<'tcx> {
138140 let generic_args = tcx. mk_args ( & [ ] ) ;
139141 let typeck = tcx. typeck ( local_def_id) ;
140142 let def_ids = DefIdCache :: new ( tcx) ;
143+ let type_builder = TypeBuilder :: new ( tcx, def_ids. clone ( ) , local_def_id. to_def_id ( ) ) ;
141144 let mut translator = Self {
142145 tcx,
143146 local_def_id,
144147 typeck,
145148 body,
146149 generic_args,
147150 def_ids,
151+ type_builder,
148152 env : HashMap :: default ( ) ,
149153 } ;
150154 translator. build_env_from_params ( ) ;
@@ -224,6 +228,28 @@ impl<'tcx> AnnotFnTranslator<'tcx> {
224228 . expect ( "expected a term" )
225229 }
226230
231+ fn variant_ctor_term (
232+ & self ,
233+ ctor_did : rustc_span:: def_id:: DefId ,
234+ result_ty : mir_ty:: Ty < ' tcx > ,
235+ field_terms : Vec < chc:: Term < rty:: FunctionParamIdx > > ,
236+ ) -> chc:: Term < rty:: FunctionParamIdx > {
237+ let variant_did = self . tcx . parent ( ctor_did) ;
238+ let adt_did = self . tcx . parent ( variant_did) ;
239+ let d_sym = crate :: refine:: datatype_symbol ( self . tcx , adt_did) ;
240+ let variant_name = self . tcx . item_name ( variant_did) ;
241+ let v_sym = chc:: DatatypeSymbol :: new ( format ! ( "{}.{}" , d_sym, variant_name) ) ;
242+ let sort_args = if let mir_ty:: TyKind :: Adt ( _, generic_args) = result_ty. kind ( ) {
243+ generic_args
244+ . types ( )
245+ . map ( |ty| self . type_builder . build ( ty) . to_sort ( ) )
246+ . collect ( )
247+ } else {
248+ panic ! ( "expected an ADT type for variant constructor" )
249+ } ;
250+ chc:: Term :: datatype_ctor ( d_sym, sort_args, v_sym, field_terms)
251+ }
252+
227253 fn to_formula_or_term (
228254 & self ,
229255 hir : & ' tcx rustc_hir:: Expr < ' tcx > ,
@@ -319,20 +345,21 @@ impl<'tcx> AnnotFnTranslator<'tcx> {
319345 rustc_ast:: LitKind :: Bool ( b) => FormulaOrTerm :: Literal ( b) ,
320346 _ => unimplemented ! ( "unsupported literal in formula: {:?}" , lit) ,
321347 } ,
322- ExprKind :: Path ( qpath) => {
323- if let rustc_hir:: def:: Res :: Local ( hir_id) =
324- self . typeck . qpath_res ( & qpath , hir . hir_id )
325- {
326- FormulaOrTerm :: Term (
327- self . env
328- . get ( & hir_id )
329- . expect ( "unbound variable in formula" )
330- . clone ( ) ,
331- )
332- } else {
333- unimplemented ! ( "unsupported path in formula: {:?}" , qpath ) ;
348+ ExprKind :: Path ( qpath) => match self . typeck . qpath_res ( & qpath , hir . hir_id ) {
349+ rustc_hir:: def:: Res :: Local ( hir_id) => FormulaOrTerm :: Term (
350+ self . env
351+ . get ( & hir_id )
352+ . expect ( "unbound variable in formula" )
353+ . clone ( ) ,
354+ ) ,
355+ rustc_hir :: def :: Res :: Def (
356+ rustc_hir :: def :: DefKind :: Ctor ( rustc_hir :: def :: CtorOf :: Variant , _ ) ,
357+ ctor_did ,
358+ ) => {
359+ FormulaOrTerm :: Term ( self . variant_ctor_term ( ctor_did , self . expr_ty ( hir ) , vec ! [ ] ) )
334360 }
335- }
361+ _ => unimplemented ! ( "unsupported path in formula: {:?}" , qpath) ,
362+ } ,
336363 ExprKind :: Tup ( exprs) => {
337364 let terms = exprs. iter ( ) . map ( |e| self . to_term ( e) ) . collect ( ) ;
338365 FormulaOrTerm :: Term ( chc:: Term :: tuple ( terms) )
@@ -349,7 +376,7 @@ impl<'tcx> AnnotFnTranslator<'tcx> {
349376 ExprKind :: Call ( func_expr, args) => {
350377 if let ExprKind :: Path ( qpath) = & func_expr. kind {
351378 let res = self . typeck . qpath_res ( qpath, func_expr. hir_id ) ;
352- if let rustc_hir:: def:: Res :: Def ( _ , def_id) = res {
379+ if let rustc_hir:: def:: Res :: Def ( def_kind , def_id) = res {
353380 if Some ( def_id) == self . def_ids . mut_model_new ( ) {
354381 assert_eq ! ( args. len( ) , 2 , "Mut::new takes exactly 2 arguments" ) ;
355382 let t1 = self . to_term ( & args[ 0 ] ) ;
@@ -361,6 +388,17 @@ impl<'tcx> AnnotFnTranslator<'tcx> {
361388 let t = self . to_term ( & args[ 0 ] ) ;
362389 return FormulaOrTerm :: Term ( chc:: Term :: box_ ( t) ) ;
363390 }
391+ if matches ! (
392+ def_kind,
393+ rustc_hir:: def:: DefKind :: Ctor ( rustc_hir:: def:: CtorOf :: Variant , _)
394+ ) {
395+ let field_terms = args. iter ( ) . map ( |arg| self . to_term ( arg) ) . collect ( ) ;
396+ return FormulaOrTerm :: Term ( self . variant_ctor_term (
397+ def_id,
398+ self . expr_ty ( hir) ,
399+ field_terms,
400+ ) ) ;
401+ }
364402 }
365403 }
366404 unimplemented ! ( "unsupported call in formula: {:?}" , func_expr)
0 commit comments