@@ -185,7 +185,7 @@ pub enum MethodMatchedData {
185185/// that we can have both a projection candidate and a where-clause candidate
186186/// for the same obligation. In that case either would do (except that
187187/// different "leaps of logic" would occur if inference variables are
188- /// present), and we just pick the projection . This is, for example,
188+ /// present), and we just pick the where-clause . This is, for example,
189189/// required for associated types to work in default impls, as the bounds
190190/// are visible both as projection bounds and as where-clauses from the
191191/// parameter environment.
@@ -915,6 +915,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
915915 -> Result < SelectionCandidateSet < ' tcx > , SelectionError < ' tcx > >
916916 {
917917 let TraitObligationStack { obligation, .. } = * stack;
918+ let ref obligation = Obligation {
919+ cause : obligation. cause . clone ( ) ,
920+ recursion_depth : obligation. recursion_depth ,
921+ predicate : self . infcx ( ) . resolve_type_vars_if_possible ( & obligation. predicate )
922+ } ;
923+
924+ if obligation. predicate . skip_binder ( ) . self_ty ( ) . is_ty_var ( ) {
925+ // FIXME(#20297): Self is a type variable (e.g. `_: AsRef<str>`).
926+ //
927+ // This is somewhat problematic, as the current scheme can't really
928+ // handle it turning to be a projection. This does end up as truly
929+ // ambiguous in most cases anyway.
930+ //
931+ // Until this is fixed, take the fast path out - this also improves
932+ // performance by preventing assemble_candidates_from_impls from
933+ // matching every impl for this trait.
934+ return Ok ( SelectionCandidateSet { vec : vec ! [ ] , ambiguous : true } ) ;
935+ }
918936
919937 let mut candidates = SelectionCandidateSet {
920938 vec : Vec :: new ( ) ,
@@ -935,13 +953,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
935953
936954 // For other types, we'll use the builtin rules.
937955 try!( self . assemble_builtin_bound_candidates ( ty:: BoundCopy ,
938- stack ,
956+ obligation ,
939957 & mut candidates) ) ;
940958 }
941959 Some ( bound @ ty:: BoundSized ) => {
942960 // Sized is never implementable by end-users, it is
943961 // always automatically computed.
944- try!( self . assemble_builtin_bound_candidates ( bound, stack, & mut candidates) ) ;
962+ try!( self . assemble_builtin_bound_candidates ( bound,
963+ obligation,
964+ & mut candidates) ) ;
945965 }
946966
947967 None if self . tcx ( ) . lang_items . unsize_trait ( ) ==
@@ -974,29 +994,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
974994 obligation : & TraitObligation < ' tcx > ,
975995 candidates : & mut SelectionCandidateSet < ' tcx > )
976996 {
977- let poly_trait_predicate =
978- self . infcx ( ) . resolve_type_vars_if_possible ( & obligation. predicate ) ;
979-
980- debug ! ( "assemble_candidates_for_projected_tys({:?},{:?})" ,
981- obligation,
982- poly_trait_predicate) ;
997+ debug ! ( "assemble_candidates_for_projected_tys({:?})" , obligation) ;
983998
984999 // FIXME(#20297) -- just examining the self-type is very simplistic
9851000
9861001 // before we go into the whole skolemization thing, just
9871002 // quickly check if the self-type is a projection at all.
988- let trait_def_id = match poly_trait_predicate . 0 . trait_ref . self_ty ( ) . sty {
1003+ let trait_def_id = match obligation . predicate . 0 . trait_ref . self_ty ( ) . sty {
9891004 ty:: TyProjection ( ref data) => data. trait_ref . def_id ,
9901005 ty:: TyInfer ( ty:: TyVar ( _) ) => {
991- // If the self-type is an inference variable, then it MAY wind up
992- // being a projected type, so induce an ambiguity.
993- //
994- // FIXME(#20297) -- being strict about this can cause
995- // inference failures with BorrowFrom, which is
996- // unfortunate. Can we do better here?
997- debug ! ( "assemble_candidates_for_projected_tys: ambiguous self-type" ) ;
998- candidates. ambiguous = true ;
999- return ;
1006+ self . tcx ( ) . sess . span_bug ( obligation. cause . span ,
1007+ "Self=_ should have been handled by assemble_candidates" ) ;
10001008 }
10011009 _ => { return ; }
10021010 } ;
@@ -1164,7 +1172,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11641172 // ok to skip binder because the substs on closure types never
11651173 // touch bound regions, they just capture the in-scope
11661174 // type/region parameters
1167- let self_ty = self . infcx . shallow_resolve ( * obligation. self_ty ( ) . skip_binder ( ) ) ;
1175+ let self_ty = * obligation. self_ty ( ) . skip_binder ( ) ;
11681176 let ( closure_def_id, substs) = match self_ty. sty {
11691177 ty:: TyClosure ( id, ref substs) => ( id, substs) ,
11701178 ty:: TyInfer ( ty:: TyVar ( _) ) => {
@@ -1208,7 +1216,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12081216 }
12091217
12101218 // ok to skip binder because what we are inspecting doesn't involve bound regions
1211- let self_ty = self . infcx . shallow_resolve ( * obligation. self_ty ( ) . skip_binder ( ) ) ;
1219+ let self_ty = * obligation. self_ty ( ) . skip_binder ( ) ;
12121220 match self_ty. sty {
12131221 ty:: TyInfer ( ty:: TyVar ( _) ) => {
12141222 debug ! ( "assemble_fn_pointer_candidates: ambiguous self-type" ) ;
@@ -1265,7 +1273,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12651273 -> Result < ( ) , SelectionError < ' tcx > >
12661274 {
12671275 // OK to skip binder here because the tests we do below do not involve bound regions
1268- let self_ty = self . infcx . shallow_resolve ( * obligation. self_ty ( ) . skip_binder ( ) ) ;
1276+ let self_ty = * obligation. self_ty ( ) . skip_binder ( ) ;
12691277 debug ! ( "assemble_candidates_from_default_impls(self_ty={:?})" , self_ty) ;
12701278
12711279 let def_id = obligation. predicate . def_id ( ) ;
@@ -1321,7 +1329,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13211329 candidates : & mut SelectionCandidateSet < ' tcx > )
13221330 {
13231331 debug ! ( "assemble_candidates_from_object_ty(self_ty={:?})" ,
1324- self . infcx . shallow_resolve ( * obligation. self_ty( ) . skip_binder( ) ) ) ;
1332+ obligation. self_ty( ) . skip_binder( ) ) ;
13251333
13261334 // Object-safety candidates are only applicable to object-safe
13271335 // traits. Including this check is useful because it helps
@@ -1336,10 +1344,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13361344 }
13371345
13381346 self . infcx . commit_if_ok ( |snapshot| {
1339- let bound_self_ty =
1340- self . infcx . resolve_type_vars_if_possible ( & obligation. self_ty ( ) ) ;
13411347 let ( self_ty, _) =
1342- self . infcx ( ) . skolemize_late_bound_regions ( & bound_self_ty , snapshot) ;
1348+ self . infcx ( ) . skolemize_late_bound_regions ( & obligation . self_ty ( ) , snapshot) ;
13431349 let poly_trait_ref = match self_ty. sty {
13441350 ty:: TyTrait ( ref data) => {
13451351 match self . tcx ( ) . lang_items . to_builtin_kind ( obligation. predicate . def_id ( ) ) {
@@ -1413,15 +1419,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
14131419 // T: Trait
14141420 // so it seems ok if we (conservatively) fail to accept that `Unsize`
14151421 // obligation above. Should be possible to extend this in the future.
1416- let self_ty = match self . tcx ( ) . no_late_bound_regions ( & obligation. self_ty ( ) ) {
1422+ let source = match self . tcx ( ) . no_late_bound_regions ( & obligation. self_ty ( ) ) {
14171423 Some ( t) => t,
14181424 None => {
14191425 // Don't add any candidates if there are bound regions.
14201426 return ;
14211427 }
14221428 } ;
1423- let source = self . infcx . shallow_resolve ( self_ty) ;
1424- let target = self . infcx . shallow_resolve ( obligation. predicate . 0 . input_types ( ) [ 0 ] ) ;
1429+ let target = obligation. predicate . 0 . input_types ( ) [ 0 ] ;
14251430
14261431 debug ! ( "assemble_candidates_for_unsizing(source={:?}, target={:?})" ,
14271432 source, target) ;
@@ -1576,11 +1581,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15761581
15771582 fn assemble_builtin_bound_candidates < ' o > ( & mut self ,
15781583 bound : ty:: BuiltinBound ,
1579- stack : & TraitObligationStack < ' o , ' tcx > ,
1584+ obligation : & TraitObligation < ' tcx > ,
15801585 candidates : & mut SelectionCandidateSet < ' tcx > )
15811586 -> Result < ( ) , SelectionError < ' tcx > >
15821587 {
1583- match self . builtin_bound ( bound, stack . obligation ) {
1588+ match self . builtin_bound ( bound, obligation) {
15841589 Ok ( If ( ..) ) => {
15851590 debug ! ( "builtin_bound: bound={:?}" ,
15861591 bound) ;
0 commit comments