File tree Expand file tree Collapse file tree 4 files changed +45
-6
lines changed Expand file tree Collapse file tree 4 files changed +45
-6
lines changed Original file line number Diff line number Diff line change @@ -142,12 +142,21 @@ impl<T> Canonicalized<T> {
142142
143143pub fn unify ( ty1 : & Canonical < Ty > , ty2 : & Canonical < Ty > ) -> Option < Substs > {
144144 let mut table = InferenceTable :: new ( ) ;
145+ let num_vars = ty1. num_vars . max ( ty2. num_vars ) ;
145146 let vars =
146- Substs :: builder ( ty1. num_vars ) . fill ( std:: iter:: repeat_with ( || table. new_type_var ( ) ) ) . build ( ) ;
147- let ty_with_vars = ty1. value . clone ( ) . subst_bound_vars ( & vars) ;
148- if !table. unify ( & ty_with_vars, & ty2. value ) {
147+ Substs :: builder ( num_vars) . fill ( std:: iter:: repeat_with ( || table. new_type_var ( ) ) ) . build ( ) ;
148+ let ty1_with_vars = ty1. value . clone ( ) . subst_bound_vars ( & vars) ;
149+ let ty2_with_vars = ty2. value . clone ( ) . subst_bound_vars ( & vars) ;
150+ if !table. unify ( & ty1_with_vars, & ty2_with_vars) {
149151 return None ;
150152 }
153+ // default any type vars that weren't unified back to their original bound vars
154+ // (kind of hacky)
155+ for ( i, var) in vars. iter ( ) . enumerate ( ) {
156+ if & * table. resolve_ty_shallow ( var) == var {
157+ table. unify ( var, & Ty :: Bound ( i as u32 ) ) ;
158+ }
159+ }
151160 Some (
152161 Substs :: builder ( ty1. num_vars )
153162 . fill ( vars. iter ( ) . map ( |v| table. resolve_ty_completely ( v. clone ( ) ) ) )
Original file line number Diff line number Diff line change @@ -355,6 +355,10 @@ impl Substs {
355355 Substs ( self . 0 [ ..std:: cmp:: min ( self . 0 . len ( ) , n) ] . into ( ) )
356356 }
357357
358+ pub fn suffix ( & self , n : usize ) -> Substs {
359+ Substs ( self . 0 [ self . 0 . len ( ) - std:: cmp:: min ( self . 0 . len ( ) , n) ..] . into ( ) )
360+ }
361+
358362 pub fn as_single ( & self ) -> & Ty {
359363 if self . 0 . len ( ) != 1 {
360364 panic ! ( "expected substs of len 1, got {:?}" , self ) ;
Original file line number Diff line number Diff line change @@ -508,10 +508,17 @@ pub(crate) fn inherent_impl_substs(
508508 impl_id : ImplId ,
509509 self_ty : & Canonical < Ty > ,
510510) -> Option < Substs > {
511- let vars = Substs :: build_for_def ( db, impl_id) . fill_with_bound_vars ( 0 ) . build ( ) ;
511+ // we create a var for each type parameter of the impl; we need to keep in
512+ // mind here that `self_ty` might have vars of its own
513+ let vars =
514+ Substs :: build_for_def ( db, impl_id) . fill_with_bound_vars ( self_ty. num_vars as u32 ) . build ( ) ;
512515 let self_ty_with_vars = db. impl_self_ty ( impl_id) . subst ( & vars) ;
513- let self_ty_with_vars = Canonical { num_vars : vars. len ( ) , value : self_ty_with_vars } ;
514- super :: infer:: unify ( & self_ty_with_vars, self_ty)
516+ let self_ty_with_vars =
517+ Canonical { num_vars : vars. len ( ) + self_ty. num_vars , value : self_ty_with_vars } ;
518+ let substs = super :: infer:: unify ( & self_ty_with_vars, self_ty) ;
519+ // we only want the substs for the vars we added, not the ones from self_ty
520+ let result = substs. map ( |s| s. suffix ( vars. len ( ) ) ) ;
521+ result
515522}
516523
517524fn transform_receiver_ty (
Original file line number Diff line number Diff line change @@ -1048,6 +1048,25 @@ where
10481048 assert_eq ! ( t, "{unknown}" ) ;
10491049}
10501050
1051+ #[ test]
1052+ fn method_resolution_3373 ( ) {
1053+ let t = type_at (
1054+ r#"
1055+ //- /main.rs
1056+ struct A<T>(T);
1057+
1058+ impl A<i32> {
1059+ fn from(v: i32) -> A<i32> { A(v) }
1060+ }
1061+
1062+ fn main() {
1063+ A::from(3)<|>;
1064+ }
1065+ "# ,
1066+ ) ;
1067+ assert_eq ! ( t, "A<i32>" ) ;
1068+ }
1069+
10511070#[ test]
10521071fn method_resolution_slow ( ) {
10531072 // this can get quite slow if we set the solver size limit too high
You can’t perform that action at this time.
0 commit comments