@@ -101,23 +101,23 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
101101 }
102102 for ( ( param_idx, got_ty) , expected_ty) in got. params . iter_enumerated ( ) . zip ( & expected_args) {
103103 // TODO we can use relate_sub_refined_type here when we implemenented builder-aware relate_*
104- let clause = builder
104+ let cs = builder
105105 . clone ( )
106106 . with_value_var ( & got_ty. ty )
107107 . add_body ( expected_ty. refinement . clone ( ) )
108108 . head ( got_ty. refinement . clone ( ) ) ;
109- clauses. push ( clause ) ;
109+ clauses. extend ( cs ) ;
110110 builder
111111 . with_mapped_value_var ( param_idx)
112112 . add_body ( expected_ty. refinement . clone ( ) ) ;
113113 clauses. extend ( builder. relate_sub_type ( & expected_ty. ty , & got_ty. ty ) ) ;
114114 }
115115
116- let clause = builder
116+ let cs = builder
117117 . with_value_var ( & got. ret . ty )
118118 . add_body ( got. ret . refinement )
119119 . head ( expected_ret. refinement ) ;
120- clauses. push ( clause ) ;
120+ clauses. extend ( cs ) ;
121121 clauses. extend ( builder. relate_sub_type ( & got. ret . ty , & expected_ret. ty ) ) ;
122122 clauses
123123 }
@@ -450,10 +450,8 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
450450 let ret2 = chc:: Term :: var ( param2_var)
451451 . mut_current ( )
452452 . equal_to ( chc:: Term :: var ( param1_var) . mut_final ( ) ) ;
453- let ret_refinement = self
454- . ctx
455- . implied_atom ( vec ! [ ret1, ret2] , |_| param1. ty . to_sort ( ) ) ;
456- let ret = rty:: RefinedType :: new ( rty:: Type :: unit ( ) , ret_refinement. into ( ) ) ;
453+ let ret_formula = chc:: Formula :: Atom ( ret1) . and ( chc:: Formula :: Atom ( ret2) ) ;
454+ let ret = rty:: RefinedType :: new ( rty:: Type :: unit ( ) , ret_formula. into ( ) ) ;
457455 rty:: FunctionType :: new ( [ param1, param2] . into_iter ( ) . collect ( ) , ret) . into ( )
458456 }
459457 Some ( ( def_id, args) ) => {
@@ -758,30 +756,37 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
758756 }
759757}
760758
759+ /// Turns [`rty::RefinedType<Var>`] into [`rty::RefinedType<T>`].
760+ ///
761+ /// We sometimes need to replace [`rty::RefinedTypeVar<Var>`] with [`rty::RefinedTypeVar<T>`].
762+ /// In [`analyze::basic_block`] module, `T` is [`rty::FunctionParamIdx`]. The type we get as
763+ /// a function result is obtained as [`rty::RefinedTypeVar<Var>`], but we need to express it using
764+ /// only function parameters for the subtyping. [`UnbindAtoms`] holds the relation between
765+ /// the function parameters and their representaion under the environment and
766+ /// let the type in environment be expressed only under the function parameters using existentials.
761767#[ derive( Debug , Clone ) ]
762768pub struct UnbindAtoms < T > {
763769 existentials : IndexVec < rty:: ExistentialVarIdx , chc:: Sort > ,
764- atoms : Vec < chc :: Atom < rty:: RefinedTypeVar < Var > > > ,
770+ formula : rty :: FormulaWithAtoms < rty:: RefinedTypeVar < Var > > ,
765771 target_equations : Vec < ( rty:: RefinedTypeVar < T > , chc:: Term < rty:: RefinedTypeVar < Var > > ) > ,
766772}
767773
768774impl < T > Default for UnbindAtoms < T > {
769775 fn default ( ) -> Self {
770776 UnbindAtoms {
771777 existentials : Default :: default ( ) ,
772- atoms : Default :: default ( ) ,
778+ formula : Default :: default ( ) ,
773779 target_equations : Default :: default ( ) ,
774780 }
775781 }
776782}
777783
778784impl < T > UnbindAtoms < T > {
779785 pub fn push ( & mut self , target : rty:: RefinedTypeVar < T > , var_ty : PlaceType ) {
780- self . atoms . extend (
786+ self . formula . push_conj (
781787 var_ty
782- . conds
783- . into_iter ( )
784- . map ( |a| a. map_var ( |v| v. shift_existential ( self . existentials . len ( ) ) . into ( ) ) ) ,
788+ . formula
789+ . map_var ( |v| v. shift_existential ( self . existentials . len ( ) ) . into ( ) ) ,
785790 ) ;
786791 self . target_equations . push ( (
787792 target,
@@ -799,14 +804,11 @@ impl<T> UnbindAtoms<T> {
799804 } = ty;
800805 let rty:: Refinement {
801806 existentials,
802- atoms ,
807+ formula ,
803808 } = refinement;
804809
805- self . atoms . extend (
806- atoms
807- . into_iter ( )
808- . map ( |a| a. map_var ( |v| v. shift_existential ( self . existentials . len ( ) ) ) ) ,
809- ) ;
810+ self . formula
811+ . push_conj ( formula. map_var ( |v| v. shift_existential ( self . existentials . len ( ) ) ) ) ;
810812 self . existentials . extend ( existentials) ;
811813
812814 let mut substs = HashMap :: new ( ) ;
@@ -815,25 +817,29 @@ impl<T> UnbindAtoms<T> {
815817 substs. insert ( v, ev) ;
816818 }
817819
818- let atoms = self
819- . atoms
820- . into_iter ( )
821- . map ( |a| {
822- a. map_var ( |v| match v {
823- rty:: RefinedTypeVar :: Value => rty:: RefinedTypeVar :: Value ,
824- rty:: RefinedTypeVar :: Free ( v) => rty:: RefinedTypeVar :: Existential ( substs[ & v] ) ,
825- rty:: RefinedTypeVar :: Existential ( ev) => rty:: RefinedTypeVar :: Existential ( ev) ,
820+ let mut formula = self . formula . map_var ( |v| match v {
821+ rty:: RefinedTypeVar :: Value => rty:: RefinedTypeVar :: Value ,
822+ rty:: RefinedTypeVar :: Free ( v) => rty:: RefinedTypeVar :: Existential ( substs[ & v] ) ,
823+ rty:: RefinedTypeVar :: Existential ( ev) => rty:: RefinedTypeVar :: Existential ( ev) ,
824+ } ) ;
825+ formula. push_conj (
826+ self . target_equations
827+ . into_iter ( )
828+ . map ( |( t, term) | {
829+ chc:: Term :: var ( t) . equal_to ( term. map_var ( |v| match v {
830+ rty:: RefinedTypeVar :: Value => rty:: RefinedTypeVar :: Value ,
831+ rty:: RefinedTypeVar :: Free ( v) => {
832+ rty:: RefinedTypeVar :: Existential ( substs[ & v] )
833+ }
834+ rty:: RefinedTypeVar :: Existential ( ev) => {
835+ rty:: RefinedTypeVar :: Existential ( ev)
836+ }
837+ } ) )
826838 } )
827- } )
828- . chain ( self . target_equations . into_iter ( ) . map ( |( t, term) | {
829- chc:: Term :: var ( t) . equal_to ( term. map_var ( |v| match v {
830- rty:: RefinedTypeVar :: Value => rty:: RefinedTypeVar :: Value ,
831- rty:: RefinedTypeVar :: Free ( v) => rty:: RefinedTypeVar :: Existential ( substs[ & v] ) ,
832- rty:: RefinedTypeVar :: Existential ( ev) => rty:: RefinedTypeVar :: Existential ( ev) ,
833- } ) )
834- } ) )
835- . collect ( ) ;
836- let refinement = rty:: Refinement :: new ( self . existentials , atoms) ;
839+ . collect :: < Vec < _ > > ( ) ,
840+ ) ;
841+
842+ let refinement = rty:: Refinement :: with_formula ( self . existentials , formula) ;
837843 // TODO: polymorphic datatypes: template needed?
838844 rty:: RefinedType :: new ( src_ty. assert_closed ( ) . vacuous ( ) , refinement)
839845 }
@@ -872,11 +878,10 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
872878 }
873879
874880 let local_ty = self . env . local_type ( local) ;
875- assumption. conds . extend (
881+ assumption. formula . push_conj (
876882 local_ty
877- . conds
878- . into_iter ( )
879- . map ( |a| a. map_var ( |v| v. shift_existential ( assumption. existentials . len ( ) ) ) ) ,
883+ . formula
884+ . map_var ( |v| v. shift_existential ( assumption. existentials . len ( ) ) ) ,
880885 ) ;
881886 let term = local_ty
882887 . term
@@ -889,16 +894,14 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
889894 for ( idx, param) in expected_params. iter_enumerated ( ) {
890895 let rty:: Refinement {
891896 existentials,
892- atoms ,
897+ formula ,
893898 } = param. refinement . clone ( ) ;
894- assumption. conds . extend ( atoms. into_iter ( ) . map ( |a| {
895- a. subst_var ( |v| match v {
896- rty:: RefinedTypeVar :: Value => param_terms[ & idx] . clone ( ) ,
897- rty:: RefinedTypeVar :: Free ( v) => param_terms[ & v] . clone ( ) ,
898- rty:: RefinedTypeVar :: Existential ( ev) => chc:: Term :: var (
899- PlaceTypeVar :: Existential ( ev + assumption. existentials . len ( ) ) ,
900- ) ,
901- } )
899+ assumption. formula . push_conj ( formula. subst_var ( |v| match v {
900+ rty:: RefinedTypeVar :: Value => param_terms[ & idx] . clone ( ) ,
901+ rty:: RefinedTypeVar :: Free ( v) => param_terms[ & v] . clone ( ) ,
902+ rty:: RefinedTypeVar :: Existential ( ev) => chc:: Term :: var ( PlaceTypeVar :: Existential (
903+ ev + assumption. existentials . len ( ) ,
904+ ) ) ,
902905 } ) ) ;
903906 assumption. existentials . extend ( existentials) ;
904907 }
0 commit comments