@@ -186,7 +186,7 @@ pub enum MethodMatchedData {
186186/// that we can have both a projection candidate and a where-clause candidate
187187/// for the same obligation. In that case either would do (except that
188188/// different "leaps of logic" would occur if inference variables are
189- /// present), and we just pick the projection . This is, for example,
189+ /// present), and we just pick the where-clause . This is, for example,
190190/// required for associated types to work in default impls, as the bounds
191191/// are visible both as projection bounds and as where-clauses from the
192192/// parameter environment.
@@ -916,6 +916,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
916916 -> Result < SelectionCandidateSet < ' tcx > , SelectionError < ' tcx > >
917917 {
918918 let TraitObligationStack { obligation, .. } = * stack;
919+ let ref obligation = Obligation {
920+ cause : obligation. cause . clone ( ) ,
921+ recursion_depth : obligation. recursion_depth ,
922+ predicate : self . infcx ( ) . resolve_type_vars_if_possible ( & obligation. predicate )
923+ } ;
924+
925+ if obligation. predicate . skip_binder ( ) . self_ty ( ) . is_ty_var ( ) {
926+ // FIXME(#20297): Self is a type variable (e.g. `_: AsRef<str>`).
927+ //
928+ // This is somewhat problematic, as the current scheme can't really
929+ // handle it turning to be a projection. This does end up as truly
930+ // ambiguous in most cases anyway.
931+ //
932+ // Until this is fixed, take the fast path out - this also improves
933+ // performance by preventing assemble_candidates_from_impls from
934+ // matching every impl for this trait.
935+ return Ok ( SelectionCandidateSet { vec : vec ! [ ] , ambiguous : true } ) ;
936+ }
919937
920938 let mut candidates = SelectionCandidateSet {
921939 vec : Vec :: new ( ) ,
@@ -936,13 +954,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
936954
937955 // For other types, we'll use the builtin rules.
938956 try!( self . assemble_builtin_bound_candidates ( ty:: BoundCopy ,
939- stack ,
957+ obligation ,
940958 & mut candidates) ) ;
941959 }
942960 Some ( bound @ ty:: BoundSized ) => {
943961 // Sized is never implementable by end-users, it is
944962 // always automatically computed.
945- try!( self . assemble_builtin_bound_candidates ( bound, stack, & mut candidates) ) ;
963+ try!( self . assemble_builtin_bound_candidates ( bound,
964+ obligation,
965+ & mut candidates) ) ;
946966 }
947967
948968 None if self . tcx ( ) . lang_items . unsize_trait ( ) ==
@@ -975,29 +995,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
975995 obligation : & TraitObligation < ' tcx > ,
976996 candidates : & mut SelectionCandidateSet < ' tcx > )
977997 {
978- let poly_trait_predicate =
979- self . infcx ( ) . resolve_type_vars_if_possible ( & obligation. predicate ) ;
980-
981- debug ! ( "assemble_candidates_for_projected_tys({:?},{:?})" ,
982- obligation,
983- poly_trait_predicate) ;
998+ debug ! ( "assemble_candidates_for_projected_tys({:?})" , obligation) ;
984999
9851000 // FIXME(#20297) -- just examining the self-type is very simplistic
9861001
9871002 // before we go into the whole skolemization thing, just
9881003 // quickly check if the self-type is a projection at all.
989- let trait_def_id = match poly_trait_predicate . 0 . trait_ref . self_ty ( ) . sty {
1004+ let trait_def_id = match obligation . predicate . 0 . trait_ref . self_ty ( ) . sty {
9901005 ty:: TyProjection ( ref data) => data. trait_ref . def_id ,
9911006 ty:: TyInfer ( ty:: TyVar ( _) ) => {
992- // If the self-type is an inference variable, then it MAY wind up
993- // being a projected type, so induce an ambiguity.
994- //
995- // FIXME(#20297) -- being strict about this can cause
996- // inference failures with BorrowFrom, which is
997- // unfortunate. Can we do better here?
998- debug ! ( "assemble_candidates_for_projected_tys: ambiguous self-type" ) ;
999- candidates. ambiguous = true ;
1000- return ;
1007+ self . tcx ( ) . sess . span_bug ( obligation. cause . span ,
1008+ "Self=_ should have been handled by assemble_candidates" ) ;
10011009 }
10021010 _ => { return ; }
10031011 } ;
@@ -1165,7 +1173,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11651173 // ok to skip binder because the substs on closure types never
11661174 // touch bound regions, they just capture the in-scope
11671175 // type/region parameters
1168- let self_ty = self . infcx . shallow_resolve ( * obligation. self_ty ( ) . skip_binder ( ) ) ;
1176+ let self_ty = * obligation. self_ty ( ) . skip_binder ( ) ;
11691177 let ( closure_def_id, substs) = match self_ty. sty {
11701178 ty:: TyClosure ( id, ref substs) => ( id, substs) ,
11711179 ty:: TyInfer ( ty:: TyVar ( _) ) => {
@@ -1209,7 +1217,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12091217 }
12101218
12111219 // ok to skip binder because what we are inspecting doesn't involve bound regions
1212- let self_ty = self . infcx . shallow_resolve ( * obligation. self_ty ( ) . skip_binder ( ) ) ;
1220+ let self_ty = * obligation. self_ty ( ) . skip_binder ( ) ;
12131221 match self_ty. sty {
12141222 ty:: TyInfer ( ty:: TyVar ( _) ) => {
12151223 debug ! ( "assemble_fn_pointer_candidates: ambiguous self-type" ) ;
@@ -1266,7 +1274,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12661274 -> Result < ( ) , SelectionError < ' tcx > >
12671275 {
12681276 // OK to skip binder here because the tests we do below do not involve bound regions
1269- let self_ty = self . infcx . shallow_resolve ( * obligation. self_ty ( ) . skip_binder ( ) ) ;
1277+ let self_ty = * obligation. self_ty ( ) . skip_binder ( ) ;
12701278 debug ! ( "assemble_candidates_from_default_impls(self_ty={:?})" , self_ty) ;
12711279
12721280 let def_id = obligation. predicate . def_id ( ) ;
@@ -1322,7 +1330,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13221330 candidates : & mut SelectionCandidateSet < ' tcx > )
13231331 {
13241332 debug ! ( "assemble_candidates_from_object_ty(self_ty={:?})" ,
1325- self . infcx . shallow_resolve ( * obligation. self_ty( ) . skip_binder( ) ) ) ;
1333+ obligation. self_ty( ) . skip_binder( ) ) ;
13261334
13271335 // Object-safety candidates are only applicable to object-safe
13281336 // traits. Including this check is useful because it helps
@@ -1337,10 +1345,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13371345 }
13381346
13391347 self . infcx . commit_if_ok ( |snapshot| {
1340- let bound_self_ty =
1341- self . infcx . resolve_type_vars_if_possible ( & obligation. self_ty ( ) ) ;
13421348 let ( self_ty, _) =
1343- self . infcx ( ) . skolemize_late_bound_regions ( & bound_self_ty , snapshot) ;
1349+ self . infcx ( ) . skolemize_late_bound_regions ( & obligation . self_ty ( ) , snapshot) ;
13441350 let poly_trait_ref = match self_ty. sty {
13451351 ty:: TyTrait ( ref data) => {
13461352 match self . tcx ( ) . lang_items . to_builtin_kind ( obligation. predicate . def_id ( ) ) {
@@ -1414,15 +1420,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
14141420 // T: Trait
14151421 // so it seems ok if we (conservatively) fail to accept that `Unsize`
14161422 // obligation above. Should be possible to extend this in the future.
1417- let self_ty = match self . tcx ( ) . no_late_bound_regions ( & obligation. self_ty ( ) ) {
1423+ let source = match self . tcx ( ) . no_late_bound_regions ( & obligation. self_ty ( ) ) {
14181424 Some ( t) => t,
14191425 None => {
14201426 // Don't add any candidates if there are bound regions.
14211427 return ;
14221428 }
14231429 } ;
1424- let source = self . infcx . shallow_resolve ( self_ty) ;
1425- let target = self . infcx . shallow_resolve ( obligation. predicate . 0 . input_types ( ) [ 0 ] ) ;
1430+ let target = obligation. predicate . 0 . input_types ( ) [ 0 ] ;
14261431
14271432 debug ! ( "assemble_candidates_for_unsizing(source={:?}, target={:?})" ,
14281433 source, target) ;
@@ -1577,11 +1582,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15771582
15781583 fn assemble_builtin_bound_candidates < ' o > ( & mut self ,
15791584 bound : ty:: BuiltinBound ,
1580- stack : & TraitObligationStack < ' o , ' tcx > ,
1585+ obligation : & TraitObligation < ' tcx > ,
15811586 candidates : & mut SelectionCandidateSet < ' tcx > )
15821587 -> Result < ( ) , SelectionError < ' tcx > >
15831588 {
1584- match self . builtin_bound ( bound, stack . obligation ) {
1589+ match self . builtin_bound ( bound, obligation) {
15851590 Ok ( If ( ..) ) => {
15861591 debug ! ( "builtin_bound: bound={:?}" ,
15871592 bound) ;
0 commit comments