@@ -185,7 +185,7 @@ pub enum MethodMatchedData {
185
185
/// that we can have both a projection candidate and a where-clause candidate
186
186
/// for the same obligation. In that case either would do (except that
187
187
/// 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,
189
189
/// required for associated types to work in default impls, as the bounds
190
190
/// are visible both as projection bounds and as where-clauses from the
191
191
/// parameter environment.
@@ -915,6 +915,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
915
915
-> Result < SelectionCandidateSet < ' tcx > , SelectionError < ' tcx > >
916
916
{
917
917
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
+ }
918
936
919
937
let mut candidates = SelectionCandidateSet {
920
938
vec : Vec :: new ( ) ,
@@ -935,13 +953,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
935
953
936
954
// For other types, we'll use the builtin rules.
937
955
try!( self . assemble_builtin_bound_candidates ( ty:: BoundCopy ,
938
- stack ,
956
+ obligation ,
939
957
& mut candidates) ) ;
940
958
}
941
959
Some ( bound @ ty:: BoundSized ) => {
942
960
// Sized is never implementable by end-users, it is
943
961
// 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) ) ;
945
965
}
946
966
947
967
None if self . tcx ( ) . lang_items . unsize_trait ( ) ==
@@ -974,29 +994,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
974
994
obligation : & TraitObligation < ' tcx > ,
975
995
candidates : & mut SelectionCandidateSet < ' tcx > )
976
996
{
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) ;
983
998
984
999
// FIXME(#20297) -- just examining the self-type is very simplistic
985
1000
986
1001
// before we go into the whole skolemization thing, just
987
1002
// 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 {
989
1004
ty:: TyProjection ( ref data) => data. trait_ref . def_id ,
990
1005
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" ) ;
1000
1008
}
1001
1009
_ => { return ; }
1002
1010
} ;
@@ -1164,7 +1172,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1164
1172
// ok to skip binder because the substs on closure types never
1165
1173
// touch bound regions, they just capture the in-scope
1166
1174
// 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 ( ) ;
1168
1176
let ( closure_def_id, substs) = match self_ty. sty {
1169
1177
ty:: TyClosure ( id, ref substs) => ( id, substs) ,
1170
1178
ty:: TyInfer ( ty:: TyVar ( _) ) => {
@@ -1208,7 +1216,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1208
1216
}
1209
1217
1210
1218
// 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 ( ) ;
1212
1220
match self_ty. sty {
1213
1221
ty:: TyInfer ( ty:: TyVar ( _) ) => {
1214
1222
debug ! ( "assemble_fn_pointer_candidates: ambiguous self-type" ) ;
@@ -1265,7 +1273,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1265
1273
-> Result < ( ) , SelectionError < ' tcx > >
1266
1274
{
1267
1275
// 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 ( ) ;
1269
1277
debug ! ( "assemble_candidates_from_default_impls(self_ty={:?})" , self_ty) ;
1270
1278
1271
1279
let def_id = obligation. predicate . def_id ( ) ;
@@ -1321,7 +1329,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1321
1329
candidates : & mut SelectionCandidateSet < ' tcx > )
1322
1330
{
1323
1331
debug ! ( "assemble_candidates_from_object_ty(self_ty={:?})" ,
1324
- self . infcx . shallow_resolve ( * obligation. self_ty( ) . skip_binder( ) ) ) ;
1332
+ obligation. self_ty( ) . skip_binder( ) ) ;
1325
1333
1326
1334
// Object-safety candidates are only applicable to object-safe
1327
1335
// traits. Including this check is useful because it helps
@@ -1336,10 +1344,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1336
1344
}
1337
1345
1338
1346
self . infcx . commit_if_ok ( |snapshot| {
1339
- let bound_self_ty =
1340
- self . infcx . resolve_type_vars_if_possible ( & obligation. self_ty ( ) ) ;
1341
1347
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) ;
1343
1349
let poly_trait_ref = match self_ty. sty {
1344
1350
ty:: TyTrait ( ref data) => {
1345
1351
match self . tcx ( ) . lang_items . to_builtin_kind ( obligation. predicate . def_id ( ) ) {
@@ -1413,15 +1419,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1413
1419
// T: Trait
1414
1420
// so it seems ok if we (conservatively) fail to accept that `Unsize`
1415
1421
// 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 ( ) ) {
1417
1423
Some ( t) => t,
1418
1424
None => {
1419
1425
// Don't add any candidates if there are bound regions.
1420
1426
return ;
1421
1427
}
1422
1428
} ;
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 ] ;
1425
1430
1426
1431
debug ! ( "assemble_candidates_for_unsizing(source={:?}, target={:?})" ,
1427
1432
source, target) ;
@@ -1576,11 +1581,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1576
1581
1577
1582
fn assemble_builtin_bound_candidates < ' o > ( & mut self ,
1578
1583
bound : ty:: BuiltinBound ,
1579
- stack : & TraitObligationStack < ' o , ' tcx > ,
1584
+ obligation : & TraitObligation < ' tcx > ,
1580
1585
candidates : & mut SelectionCandidateSet < ' tcx > )
1581
1586
-> Result < ( ) , SelectionError < ' tcx > >
1582
1587
{
1583
- match self . builtin_bound ( bound, stack . obligation ) {
1588
+ match self . builtin_bound ( bound, obligation) {
1584
1589
Ok ( If ( ..) ) => {
1585
1590
debug ! ( "builtin_bound: bound={:?}" ,
1586
1591
bound) ;
0 commit comments