@@ -117,19 +117,48 @@ pub enum MethodMatchedData {
117117/// candidate is one that might match or might not, depending on how
118118/// type variables wind up being resolved. This only occurs during inference.
119119///
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.
133162#[ derive( PartialEq , Eq , Debug , Clone ) ]
134163enum SelectionCandidate < ' tcx > {
135164 PhantomFnCandidate ,
@@ -1307,54 +1336,50 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13071336 self . evaluate_predicates_recursively ( stack, selection. iter_nested ( ) )
13081337 }
13091338
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
13121341 /// candidates and prefer where-clause candidates.
13131342 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 > )
13161345 -> bool
13171346 {
1318- if candidate_i == candidate_j {
1347+ if victim == other {
13191348 return true ;
13201349 }
13211350
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
13581383 }
13591384 }
13601385
0 commit comments