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