@@ -117,19 +117,48 @@ pub enum MethodMatchedData {
117
117
/// candidate is one that might match or might not, depending on how
118
118
/// type variables wind up being resolved. This only occurs during inference.
119
119
///
120
- /// For selection to succeed, there must be exactly one non-ambiguous
121
- /// candidate. Usually, it is not possible to have more than one
122
- /// definitive candidate, due to the coherence rules. However, there is
123
- /// one case where it could occur: if there is a blanket impl for a
124
- /// trait (that is, an impl applied to all T), and a type parameter
125
- /// with a where clause. In that case, we can have a candidate from the
126
- /// where clause and a second candidate from the impl. This is not a
127
- /// problem because coherence guarantees us that the impl which would
128
- /// be used to satisfy the where clause is the same one that we see
129
- /// now. To resolve this issue, therefore, we ignore impls if we find a
130
- /// matching where clause. Part of the reason for this is that where
131
- /// clauses can give additional information (like, the types of output
132
- /// parameters) that would have to be inferred from the impl.
120
+ /// For selection to succeed, there must be exactly one potential
121
+ /// candidate. Coherence mostly ensures that (disregarding
122
+ /// still-uninferred type variables), but there's a subtlety - coherence
123
+ /// does not consider the parameter environment, so we can have a candidate
124
+ /// from a where-clause (or associated-type bound) along with the
125
+ /// global candidate.
126
+ ///
127
+ /// For example, if we have a blanket impl
128
+ /// impl<T> MyTrait for T
129
+ /// and a where-clause
130
+ /// fn f<T>(t: T) where T: MyTrait
131
+ /// Then there are 2 candidates, but they are actually equivalent, so
132
+ /// it doesn't really matter which one is chosen. Note that the impl
133
+ /// can have bounds - even in this example, we have T: Sized, and the
134
+ /// where-clause could just as well have been
135
+ /// and the where-clause could have been Option<T> : MyTrait).
136
+ ///
137
+ /// This gets subtler. The global candidate can have bounds that
138
+ /// are not already known:
139
+ /// impl<T: Copy> MyTrait for T
140
+ /// If our type is known, we know that this impl will be the one chosen,
141
+ /// so we can just mark a `T: Copy` obligation and move on. This helps
142
+ /// inference in some cases. However, if we have a where-clause for
143
+ /// MyTrait in scope, we can't make this assumption, because another crate
144
+ /// could have a `impl MyTrait for FreshNonCopyType`, which was "passed"
145
+ /// through the where-clause. This had caused several bugs, including #18453.
146
+ ///
147
+ /// From the above, it would seem to be that the best option is to
148
+ /// just pick the where-clause. This is what we do today. However,
149
+ /// it is not a panacea. Assume we have:
150
+ ///
151
+ /// impl<'a> MyTrait<'a> for T
152
+ /// fn f<'s, T>(u: &'s T) where T: MyTrait<'s>
153
+ ///
154
+ /// Then we know that, for all lifetimes 'a, `T: MyTrait<'a>`.
155
+ /// However, because lifetimes are not known at trait-selection time,
156
+ /// we pick the where-clause, and infer that the lifetime must
157
+ /// be 's - the additional clause "poisons" selection. This could
158
+ /// get subtler, as there could have been a `T: Copy` bound on
159
+ /// the blanket impl, or multiple clauses on T:
160
+ /// fn f<'s, T>(u: &'s T) where T: MyTrait<'s>+MyTrait<'tcx>
161
+ /// We don't handle this at this moment.
133
162
#[ derive( PartialEq , Eq , Debug , Clone ) ]
134
163
enum SelectionCandidate < ' tcx > {
135
164
PhantomFnCandidate ,
@@ -1307,54 +1336,50 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1307
1336
self . evaluate_predicates_recursively ( stack, selection. iter_nested ( ) )
1308
1337
}
1309
1338
1310
- /// Returns true if `candidate_i ` should be dropped in favor of
1311
- /// `candidate_j `. Generally speaking we will drop duplicate
1339
+ /// Returns true if `victim ` should be dropped in favor of
1340
+ /// `other `. Generally speaking we will drop duplicate
1312
1341
/// candidates and prefer where-clause candidates.
1313
1342
fn candidate_should_be_dropped_in_favor_of < ' o > ( & mut self ,
1314
- candidate_i : & SelectionCandidate < ' tcx > ,
1315
- candidate_j : & SelectionCandidate < ' tcx > )
1343
+ victim : & SelectionCandidate < ' tcx > ,
1344
+ other : & SelectionCandidate < ' tcx > )
1316
1345
-> bool
1317
1346
{
1318
- if candidate_i == candidate_j {
1347
+ if victim == other {
1319
1348
return true ;
1320
1349
}
1321
1350
1322
- match ( candidate_i, candidate_j) {
1323
- ( & ImplCandidate ( ..) , & ParamCandidate ( ..) ) |
1324
- ( & ClosureCandidate ( ..) , & ParamCandidate ( ..) ) |
1325
- ( & FnPointerCandidate ( ..) , & ParamCandidate ( ..) ) |
1326
- ( & BuiltinObjectCandidate ( ..) , & ParamCandidate ( _) ) |
1327
- ( & BuiltinCandidate ( ..) , & ParamCandidate ( ..) ) => {
1328
- // We basically prefer always prefer to use a
1329
- // where-clause over another option. Where clauses
1330
- // impose the burden of finding the exact match onto
1331
- // the caller. Using an impl in preference of a where
1332
- // clause can also lead us to "overspecialize", as in
1333
- // #18453.
1334
- true
1335
- }
1336
- ( & DefaultImplCandidate ( _) , _) => {
1337
- // Prefer other candidates over default implementations.
1338
- self . tcx ( ) . sess . bug (
1339
- "default implementations shouldn't be recorded \
1340
- when there are other valid candidates") ;
1341
- }
1342
- ( & ProjectionCandidate , & ParamCandidate ( _) ) => {
1343
- // FIXME(#20297) -- this gives where clauses precedent
1344
- // over projections. Really these are just two means
1345
- // of deducing information (one based on the where
1346
- // clauses on the trait definition; one based on those
1347
- // on the enclosing scope), and it'd be better to
1348
- // integrate them more intelligently. But for now this
1349
- // seems ok. If we DON'T give where clauses
1350
- // precedence, we run into trouble in default methods,
1351
- // where both the projection bounds for `Self::A` and
1352
- // the where clauses are in scope.
1353
- true
1354
- }
1355
- _ => {
1356
- false
1357
- }
1351
+ match other {
1352
+ & ParamCandidate ( _) | & ProjectionCandidate => match victim {
1353
+ & DefaultImplCandidate ( ..) => {
1354
+ self . tcx ( ) . sess . bug (
1355
+ "default implementations shouldn't be recorded \
1356
+ when there are other valid candidates") ;
1357
+ }
1358
+ & PhantomFnCandidate => {
1359
+ self . tcx ( ) . sess . bug ( "PhantomFn didn't short-circuit selection" ) ;
1360
+ }
1361
+ & ImplCandidate ( ..) |
1362
+ & ClosureCandidate ( ..) |
1363
+ & FnPointerCandidate ( ..) |
1364
+ & BuiltinObjectCandidate ( ..) |
1365
+ & ObjectCandidate ( ..) |
1366
+ & BuiltinCandidate ( ..) => {
1367
+ // A param/projection candidate is a sure match,
1368
+ // choose it.
1369
+ // FIXME: This isn't exactly correct because of
1370
+ // lifetimes.
1371
+ true
1372
+ }
1373
+ & ProjectionCandidate => {
1374
+ // Arbitrarily give param candidates priority
1375
+ // over projection candidates. Both are "sure"
1376
+ // matches.
1377
+ true
1378
+ } ,
1379
+ & ParamCandidate ( ..) => false ,
1380
+ & ErrorCandidate => false // propagate errors
1381
+ } ,
1382
+ _ => false
1358
1383
}
1359
1384
}
1360
1385
0 commit comments