@@ -695,6 +695,35 @@ impl From<chc::Atom<Var>> for UnboundAssumption {
695695 }
696696}
697697
698+ impl Extend < UnboundAssumption > for UnboundAssumption {
699+ fn extend < T > ( & mut self , iter : T )
700+ where
701+ T : IntoIterator < Item = UnboundAssumption > ,
702+ {
703+ for assumption in iter {
704+ self . conds . extend (
705+ assumption
706+ . conds
707+ . into_iter ( )
708+ . map ( |c| c. map_var ( |v| v. shift_existential ( self . existentials . len ( ) ) ) ) ,
709+ ) ;
710+ self . existentials . extend ( assumption. existentials ) ;
711+ }
712+ self . conds . retain ( |c| !c. is_top ( ) ) ;
713+ }
714+ }
715+
716+ impl FromIterator < UnboundAssumption > for UnboundAssumption {
717+ fn from_iter < T > ( iter : T ) -> Self
718+ where
719+ T : IntoIterator < Item = UnboundAssumption > ,
720+ {
721+ let mut result = UnboundAssumption :: default ( ) ;
722+ result. extend ( iter) ;
723+ result
724+ }
725+ }
726+
698727impl < ' a , ' b , D > Pretty < ' a , D , termcolor:: ColorSpec > for & ' b UnboundAssumption
699728where
700729 D : pretty:: DocAllocator < ' a , termcolor:: ColorSpec > ,
@@ -738,6 +767,10 @@ impl UnboundAssumption {
738767 conds,
739768 }
740769 }
770+
771+ pub fn is_top ( & self ) -> bool {
772+ self . conds . iter ( ) . all ( chc:: Atom :: is_top)
773+ }
741774}
742775
743776#[ derive( Debug , Clone ) ]
@@ -1290,6 +1323,7 @@ impl Env {
12901323
12911324#[ derive( Debug , Clone ) ]
12921325enum Path {
1326+ PlaceTy ( PlaceType ) ,
12931327 Local ( Local ) ,
12941328 Deref ( Box < Path > ) ,
12951329 TupleProj ( Box < Path > , usize ) ,
@@ -1331,6 +1365,7 @@ impl Path {
13311365impl Env {
13321366 fn path_type ( & self , path : & Path ) -> PlaceType {
13331367 match path {
1368+ Path :: PlaceTy ( pty) => pty. clone ( ) ,
13341369 Path :: Local ( local) => self . local_type ( * local) ,
13351370 Path :: Deref ( path) => self . path_type ( path) . deref ( ) ,
13361371 Path :: TupleProj ( path, idx) => self . path_type ( path) . tuple_proj ( * idx) ,
@@ -1345,23 +1380,101 @@ impl Env {
13451380 self . path_type ( & place. into ( ) )
13461381 }
13471382
1348- fn drop_path ( & mut self , path : & Path ) {
1383+ fn dropping_assumption ( & mut self , path : & Path ) -> UnboundAssumption {
13491384 let ty = self . path_type ( path) ;
13501385 if ty. ty . is_mut ( ) {
1351- self . assume ( ty. into_assumption ( |term| {
1386+ ty. into_assumption ( |term| {
13521387 let term = term. map_var ( Into :: into) ;
13531388 term. clone ( ) . mut_final ( ) . equal_to ( term. mut_current ( ) )
1354- } ) ) ;
1389+ } )
13551390 } else if ty. ty . is_own ( ) {
1356- self . drop_path ( & path. clone ( ) . deref ( ) )
1391+ self . dropping_assumption ( & path. clone ( ) . deref ( ) )
13571392 } else if let Some ( tty) = ty. ty . as_tuple ( ) {
1358- for i in 0 ..tty. elems . len ( ) {
1359- self . drop_path ( & path. clone ( ) . tuple_proj ( i) ) ;
1393+ ( 0 ..tty. elems . len ( ) )
1394+ . into_iter ( )
1395+ . map ( |i| self . dropping_assumption ( & path. clone ( ) . tuple_proj ( i) ) )
1396+ . collect ( )
1397+ } else if let Some ( ety) = ty. ty . as_enum ( ) {
1398+ let enum_def = self . enum_defs [ & ety. symbol ] . clone ( ) ;
1399+ let matcher_pred = chc:: MatcherPred :: new ( ety. symbol . clone ( ) , ety. arg_sorts ( ) ) ;
1400+
1401+ let PlaceType {
1402+ ty : _,
1403+ mut existentials,
1404+ term,
1405+ mut conds,
1406+ } = ty;
1407+
1408+ let mut pred_args = vec ! [ ] ;
1409+ for field_ty in enum_def. field_tys ( ) {
1410+ let mut field_rty = rty:: RefinedType :: unrefined ( field_ty. clone ( ) . vacuous ( ) ) ;
1411+ field_rty. instantiate_ty_params ( ety. args . clone ( ) ) ;
1412+
1413+ let ev = existentials. push ( field_rty. ty . to_sort ( ) ) ;
1414+ pred_args. push ( chc:: Term :: var ( ev. into ( ) ) ) ;
1415+
1416+ if let Some ( p) = field_rty. ty . as_pointer ( ) {
1417+ if matches ! ( & p. elem. ty, rty:: Type :: Enum ( e) if e. symbol == ety. symbol) {
1418+ // TODO: we need recursively defined drop_pred for the recursive ADTs!
1419+ tracing:: warn!( "skipping recursive variant" ) ;
1420+ continue ;
1421+ }
1422+ }
1423+
1424+ let field_pty = {
1425+ let rty:: RefinedType {
1426+ ty : field_ty,
1427+ refinement,
1428+ } = field_rty;
1429+ let rty:: Refinement {
1430+ atoms,
1431+ existentials,
1432+ } = refinement;
1433+ PlaceType {
1434+ ty : field_ty,
1435+ existentials,
1436+ term : chc:: Term :: var ( ev. into ( ) ) ,
1437+ conds : atoms
1438+ . into_iter ( )
1439+ . map ( |a| {
1440+ a. map_var ( |v| match v {
1441+ rty:: RefinedTypeVar :: Value => PlaceTypeVar :: Existential ( ev) ,
1442+ rty:: RefinedTypeVar :: Free ( v) => PlaceTypeVar :: Var ( v. into ( ) ) ,
1443+ // TODO: (but otherwise we can't distinguish field existentials from them...)
1444+ rty:: RefinedTypeVar :: Existential ( _) => {
1445+ panic ! ( "cannot handle existentials in field_rty" )
1446+ }
1447+ } )
1448+ } )
1449+ . collect ( ) ,
1450+ }
1451+ } ;
1452+
1453+ let UnboundAssumption {
1454+ existentials : assumption_existentials,
1455+ conds : assumption_conds,
1456+ } = self . dropping_assumption ( & Path :: PlaceTy ( field_pty) ) ;
1457+ // dropping assumption should not generate any existential
1458+ assert ! ( assumption_existentials. is_empty( ) ) ;
1459+ conds. extend ( assumption_conds) ;
13601460 }
1461+
1462+ pred_args. push ( term) ;
1463+ conds. push ( chc:: Atom :: new ( matcher_pred. into ( ) , pred_args) ) ;
1464+
1465+ UnboundAssumption {
1466+ existentials,
1467+ conds,
1468+ }
1469+ } else {
1470+ UnboundAssumption :: default ( )
13611471 }
13621472 }
13631473
13641474 pub fn drop_local ( & mut self , local : Local ) {
1365- self . drop_path ( & Path :: Local ( local) )
1475+ let assumption = self . dropping_assumption ( & Path :: Local ( local) ) ;
1476+ if !assumption. is_top ( ) {
1477+ self . assume ( assumption) ;
1478+ }
13661479 }
13671480}
0 commit comments