@@ -74,6 +74,12 @@ impl<T: HasInterner<Interner = Interner>> Canonicalized<T> {
7474    } 
7575} 
7676
77+ /// Check if types unify. 
78+ /// 
79+ /// Note that we consider placeholder types to unify with everything. 
80+ /// This means that there may be some unresolved goals that actually set bounds for the placeholder 
81+ /// type for the types to unify. For example `Option<T>` and `Option<U>` unify although there is 
82+ /// unresolved goal `T = U`. 
7783pub  fn  could_unify ( 
7884    db :  & dyn  HirDatabase , 
7985    env :  Arc < TraitEnvironment > , 
@@ -82,30 +88,25 @@ pub fn could_unify(
8288    unify ( db,  env,  tys) . is_some ( ) 
8389} 
8490
91+ /// Check if types unify eagerly making sure there are no unresolved goals. 
92+ /// 
93+ /// This means that placeholder types are not considered to unify if there are any bounds set on 
94+ /// them. For example `Option<T>` and `Option<U>` do not unify as we cannot show that `T = U` 
8595pub  fn  could_unify_deeply ( 
8696    db :  & dyn  HirDatabase , 
8797    env :  Arc < TraitEnvironment > , 
8898    tys :  & Canonical < ( Ty ,  Ty ) > , 
8999)  -> bool  { 
90100    let  mut  table = InferenceTable :: new ( db,  env) ; 
91-     let  vars = Substitution :: from_iter ( 
92-         Interner , 
93-         tys. binders . iter ( Interner ) . map ( |it| match  & it. kind  { 
94-             chalk_ir:: VariableKind :: Ty ( _)  => { 
95-                 GenericArgData :: Ty ( table. new_type_var ( ) ) . intern ( Interner ) 
96-             } 
97-             chalk_ir:: VariableKind :: Lifetime  => { 
98-                 GenericArgData :: Ty ( table. new_type_var ( ) ) . intern ( Interner ) 
99-             }  // FIXME: maybe wrong? 
100-             chalk_ir:: VariableKind :: Const ( ty)  => { 
101-                 GenericArgData :: Const ( table. new_const_var ( ty. clone ( ) ) ) . intern ( Interner ) 
102-             } 
103-         } ) , 
104-     ) ; 
101+     let  vars = make_substitutions ( tys,  & mut  table) ; 
105102    let  ty1_with_vars = vars. apply ( tys. value . 0 . clone ( ) ,  Interner ) ; 
106103    let  ty2_with_vars = vars. apply ( tys. value . 1 . clone ( ) ,  Interner ) ; 
107104    let  ty1_with_vars = table. normalize_associated_types_in ( ty1_with_vars) ; 
108105    let  ty2_with_vars = table. normalize_associated_types_in ( ty2_with_vars) ; 
106+     table. resolve_obligations_as_possible ( ) ; 
107+     table. propagate_diverging_flag ( ) ; 
108+     let  ty1_with_vars = table. resolve_completely ( ty1_with_vars) ; 
109+     let  ty2_with_vars = table. resolve_completely ( ty2_with_vars) ; 
109110    table. unify_deeply ( & ty1_with_vars,  & ty2_with_vars) 
110111} 
111112
@@ -115,15 +116,7 @@ pub(crate) fn unify(
115116    tys :  & Canonical < ( Ty ,  Ty ) > , 
116117)  -> Option < Substitution >  { 
117118    let  mut  table = InferenceTable :: new ( db,  env) ; 
118-     let  vars = Substitution :: from_iter ( 
119-         Interner , 
120-         tys. binders . iter ( Interner ) . map ( |it| match  & it. kind  { 
121-             chalk_ir:: VariableKind :: Ty ( _)  => table. new_type_var ( ) . cast ( Interner ) , 
122-             // FIXME: maybe wrong? 
123-             chalk_ir:: VariableKind :: Lifetime  => table. new_type_var ( ) . cast ( Interner ) , 
124-             chalk_ir:: VariableKind :: Const ( ty)  => table. new_const_var ( ty. clone ( ) ) . cast ( Interner ) , 
125-         } ) , 
126-     ) ; 
119+     let  vars = make_substitutions ( tys,  & mut  table) ; 
127120    let  ty1_with_vars = vars. apply ( tys. value . 0 . clone ( ) ,  Interner ) ; 
128121    let  ty2_with_vars = vars. apply ( tys. value . 1 . clone ( ) ,  Interner ) ; 
129122    if  !table. unify ( & ty1_with_vars,  & ty2_with_vars)  { 
@@ -152,6 +145,21 @@ pub(crate) fn unify(
152145    ) ) 
153146} 
154147
148+ fn  make_substitutions ( 
149+     tys :  & chalk_ir:: Canonical < ( chalk_ir:: Ty < Interner > ,  chalk_ir:: Ty < Interner > ) > , 
150+     table :  & mut  InferenceTable < ' _ > , 
151+ )  -> chalk_ir:: Substitution < Interner >  { 
152+     Substitution :: from_iter ( 
153+         Interner , 
154+         tys. binders . iter ( Interner ) . map ( |it| match  & it. kind  { 
155+             chalk_ir:: VariableKind :: Ty ( _)  => table. new_type_var ( ) . cast ( Interner ) , 
156+             // FIXME: maybe wrong? 
157+             chalk_ir:: VariableKind :: Lifetime  => table. new_type_var ( ) . cast ( Interner ) , 
158+             chalk_ir:: VariableKind :: Const ( ty)  => table. new_const_var ( ty. clone ( ) ) . cast ( Interner ) , 
159+         } ) , 
160+     ) 
161+ } 
162+ 
155163bitflags:: bitflags! { 
156164    #[ derive( Default ,  Clone ,  Copy ) ] 
157165    pub ( crate )  struct  TypeVariableFlags :  u8  { 
@@ -458,15 +466,15 @@ impl<'a> InferenceTable<'a> {
458466        true 
459467    } 
460468
461-     /// Unify two relatable values (e.g. `Ty`) and register new  trait goals that  arise from that.  
469+     /// Unify two relatable values (e.g. `Ty`) and check whether  trait goals which  arise from that could be fulfilled  
462470pub ( crate )  fn  unify_deeply < T :  ?Sized  + Zip < Interner > > ( & mut  self ,  ty1 :  & T ,  ty2 :  & T )  -> bool  { 
463471        let  result = match  self . try_unify ( ty1,  ty2)  { 
464472            Ok ( r)  => r, 
465473            Err ( _)  => return  false , 
466474        } ; 
467475        result. goals . iter ( ) . all ( |goal| { 
468476            let  canonicalized = self . canonicalize ( goal. clone ( ) ) ; 
469-             self . try_fulfill_obligation ( & canonicalized) 
477+             self . try_resolve_obligation ( & canonicalized) . is_some ( ) 
470478        } ) 
471479    } 
472480
@@ -540,7 +548,8 @@ impl<'a> InferenceTable<'a> {
540548
541549    fn  register_obligation_in_env ( & mut  self ,  goal :  InEnvironment < Goal > )  { 
542550        let  canonicalized = self . canonicalize ( goal) ; 
543-         if  !self . try_resolve_obligation ( & canonicalized)  { 
551+         let  solution = self . try_resolve_obligation ( & canonicalized) ; 
552+         if  matches ! ( solution,  Some ( Solution :: Ambig ( _) ) )  { 
544553            self . pending_obligations . push ( canonicalized) ; 
545554        } 
546555    } 
@@ -666,70 +675,35 @@ impl<'a> InferenceTable<'a> {
666675    fn  try_resolve_obligation ( 
667676        & mut  self , 
668677        canonicalized :  & Canonicalized < InEnvironment < Goal > > , 
669-     )  -> bool  { 
678+     )  -> Option < chalk_solve :: Solution < Interner > >  { 
670679        let  solution = self . db . trait_solve ( 
671680            self . trait_env . krate , 
672681            self . trait_env . block , 
673682            canonicalized. value . clone ( ) , 
674683        ) ; 
675684
676-         match  solution { 
685+         match  & solution { 
677686            Some ( Solution :: Unique ( canonical_subst) )  => { 
678687                canonicalized. apply_solution ( 
679688                    self , 
680689                    Canonical  { 
681-                         binders :  canonical_subst. binders , 
690+                         binders :  canonical_subst. binders . clone ( ) , 
682691                        // FIXME: handle constraints 
683-                         value :  canonical_subst. value . subst , 
692+                         value :  canonical_subst. value . subst . clone ( ) , 
684693                    } , 
685694                ) ; 
686-                 true 
687695            } 
688696            Some ( Solution :: Ambig ( Guidance :: Definite ( substs) ) )  => { 
689-                 canonicalized. apply_solution ( self ,  substs) ; 
690-                 false 
697+                 canonicalized. apply_solution ( self ,  substs. clone ( ) ) ; 
691698            } 
692699            Some ( _)  => { 
693700                // FIXME use this when trying to resolve everything at the end 
694-                 false 
695701            } 
696702            None  => { 
697703                // FIXME obligation cannot be fulfilled => diagnostic 
698-                 true 
699-             } 
700-         } 
701-     } 
702- 
703-     fn  try_fulfill_obligation ( 
704-         & mut  self , 
705-         canonicalized :  & Canonicalized < InEnvironment < Goal > > , 
706-     )  -> bool  { 
707-         let  solution = self . db . trait_solve ( 
708-             self . trait_env . krate , 
709-             self . trait_env . block , 
710-             canonicalized. value . clone ( ) , 
711-         ) ; 
712- 
713-         // FIXME: Does just returning `solution.is_some()` work? 
714-         match  solution { 
715-             Some ( Solution :: Unique ( canonical_subst) )  => { 
716-                 canonicalized. apply_solution ( 
717-                     self , 
718-                     Canonical  { 
719-                         binders :  canonical_subst. binders , 
720-                         // FIXME: handle constraints 
721-                         value :  canonical_subst. value . subst , 
722-                     } , 
723-                 ) ; 
724-                 true 
725-             } 
726-             Some ( Solution :: Ambig ( Guidance :: Definite ( substs) ) )  => { 
727-                 canonicalized. apply_solution ( self ,  substs) ; 
728-                 true 
729704            } 
730-             Some ( _)  => true , 
731-             None  => false , 
732705        } 
706+         solution
733707    } 
734708
735709    pub ( crate )  fn  callable_sig ( 
0 commit comments