@@ -117,23 +117,71 @@ pub enum MethodMatchedData {
117117/// obligation is for `int`. In that case, we drop the impl out of the
118118/// list. But the other cases are considered *candidates*.
119119///
120- /// Candidates can either be definitive or ambiguous. An ambiguous
121- /// candidate is one that might match or might not, depending on how
122- /// type variables wind up being resolved. This only occurs during inference.
120+ /// For selection to succeed, there must be exactly one matching
121+ /// candidate. If the obligation is fully known, this is guaranteed
122+ /// by coherence. However, if the obligation contains type parameters
123+ /// or variables, there may be multiple such impls.
123124///
124- /// For selection to succeed, there must be exactly one non-ambiguous
125- /// candidate. Usually, it is not possible to have more than one
126- /// definitive candidate, due to the coherence rules. However, there is
127- /// one case where it could occur: if there is a blanket impl for a
128- /// trait (that is, an impl applied to all T), and a type parameter
129- /// with a where clause. In that case, we can have a candidate from the
130- /// where clause and a second candidate from the impl. This is not a
131- /// problem because coherence guarantees us that the impl which would
132- /// be used to satisfy the where clause is the same one that we see
133- /// now. To resolve this issue, therefore, we ignore impls if we find a
134- /// matching where clause. Part of the reason for this is that where
135- /// clauses can give additional information (like, the types of output
136- /// parameters) that would have to be inferred from the impl.
125+ /// It is not a real problem if multiple matching impls exist because
126+ /// of type variables - it just means the obligation isn't sufficiently
127+ /// elaborated. In that case we report an ambiguity, and the caller can
128+ /// try again after more type information has been gathered or report a
129+ /// "type annotations required" error.
130+ ///
131+ /// However, with type parameters, this can be a real problem - type
132+ /// parameters don't unify with regular types, but they *can* unify
133+ /// with variables from blanket impls, and (unless we know its bounds
134+ /// will always be satisfied) picking the blanket impl will be wrong
135+ /// for at least *some* substitutions. To make this concrete, if we have
136+ ///
137+ /// trait AsDebug { type Out : fmt::Debug; fn debug(self) -> Self::Out; }
138+ /// impl<T: fmt::Debug> AsDebug for T {
139+ /// type Out = T;
140+ /// fn debug(self) -> fmt::Debug { self }
141+ /// }
142+ /// fn foo<T: AsDebug>(t: T) { println!("{:?}", <T as AsDebug>::debug(t)); }
143+ ///
144+ /// we can't just use the impl to resolve the <T as AsDebug> obligation
145+ /// - a type from another crate (that doesn't implement fmt::Debug) could
146+ /// implement AsDebug.
147+ ///
148+ /// Because where-clauses match the type exactly, multiple clauses can
149+ /// only match if there are unresolved variables, and we can mostly just
150+ /// report this ambiguity in that case. This is still a problem - we can't
151+ /// *do anything* with ambiguities that involve only regions. This is issue
152+ /// #21974.
153+ ///
154+ /// If a single where-clause matches and there are no inference
155+ /// variables left, then it definitely matches and we can just select
156+ /// it.
157+ ///
158+ /// In fact, we even select the where-clause when the obligation contains
159+ /// inference variables. The can lead to inference making "leaps of logic",
160+ /// for example in this situation:
161+ ///
162+ /// pub trait Foo<T> { fn foo(&self) -> T; }
163+ /// impl<T> Foo<()> for T { fn foo(&self) { } }
164+ /// impl Foo<bool> for bool { fn foo(&self) -> bool { *self } }
165+ ///
166+ /// pub fn foo<T>(t: T) where T: Foo<bool> {
167+ /// println!("{:?}", <T as Foo<_>>::foo(&t));
168+ /// }
169+ /// fn main() { foo(false); }
170+ ///
171+ /// Here the obligation <T as Foo<$0>> can be matched by both the blanket
172+ /// impl and the where-clause. We select the where-clause and unify $0=bool,
173+ /// so the program prints "false". However, if the where-clause is omitted,
174+ /// the blanket impl is selected, we unify $0=(), and the program prints
175+ /// "()".
176+ ///
177+ /// Exactly the same issues apply to projection and object candidates, except
178+ /// that we can have both a projection candidate and a where-clause candidate
179+ /// for the same obligation. In that case either would do (except that
180+ /// different "leaps of logic" would occur if inference variables are
181+ /// present), and we just pick the projection. This is, for example,
182+ /// required for associated types to work in default impls, as the bounds
183+ /// are visible both as projection bounds and as where-clauses from the
184+ /// parameter environment.
137185#[ derive( PartialEq , Eq , Debug , Clone ) ]
138186enum SelectionCandidate < ' tcx > {
139187 PhantomFnCandidate ,
@@ -1350,63 +1398,51 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13501398 /// Returns true if `candidate_i` should be dropped in favor of
13511399 /// `candidate_j`. Generally speaking we will drop duplicate
13521400 /// candidates and prefer where-clause candidates.
1401+ /// Returns true if `victim` should be dropped in favor of
1402+ /// `other`. Generally speaking we will drop duplicate
1403+ /// candidates and prefer where-clause candidates.
1404+ ///
1405+ /// See the comment for "SelectionCandidate" for more details.
13531406 fn candidate_should_be_dropped_in_favor_of < ' o > ( & mut self ,
1354- candidate_i : & SelectionCandidate < ' tcx > ,
1355- candidate_j : & SelectionCandidate < ' tcx > )
1407+ victim : & SelectionCandidate < ' tcx > ,
1408+ other : & SelectionCandidate < ' tcx > )
13561409 -> bool
13571410 {
1358- if candidate_i == candidate_j {
1411+ if victim == other {
13591412 return true ;
13601413 }
13611414
1362- match ( candidate_i, candidate_j) {
1363- ( & ImplCandidate ( ..) , & ParamCandidate ( ..) ) |
1364- ( & ClosureCandidate ( ..) , & ParamCandidate ( ..) ) |
1365- ( & FnPointerCandidate ( ..) , & ParamCandidate ( ..) ) |
1366- ( & BuiltinObjectCandidate ( ..) , & ParamCandidate ( _) ) |
1367- ( & BuiltinCandidate ( ..) , & ParamCandidate ( ..) ) => {
1368- // We basically prefer always prefer to use a
1369- // where-clause over another option. Where clauses
1370- // impose the burden of finding the exact match onto
1371- // the caller. Using an impl in preference of a where
1372- // clause can also lead us to "overspecialize", as in
1373- // #18453.
1374- true
1375- }
1376- ( & ImplCandidate ( ..) , & ObjectCandidate ( ..) ) => {
1377- // This means that we are matching an object of type
1378- // `Trait` against the trait `Trait`. In that case, we
1379- // always prefer to use the object vtable over the
1380- // impl. Like a where clause, the impl may or may not
1381- // be the one that is used by the object (because the
1382- // impl may have additional where-clauses that the
1383- // object's source might not meet) -- if it is, using
1384- // the vtable is fine. If it is not, using the vtable
1385- // is good. A win win!
1386- true
1387- }
1388- ( & DefaultImplCandidate ( _) , _) => {
1389- // Prefer other candidates over default implementations.
1390- self . tcx ( ) . sess . bug (
1391- "default implementations shouldn't be recorded \
1392- when there are other valid candidates") ;
1393- }
1394- ( & ProjectionCandidate , & ParamCandidate ( _) ) => {
1395- // FIXME(#20297) -- this gives where clauses precedent
1396- // over projections. Really these are just two means
1397- // of deducing information (one based on the where
1398- // clauses on the trait definition; one based on those
1399- // on the enclosing scope), and it'd be better to
1400- // integrate them more intelligently. But for now this
1401- // seems ok. If we DON'T give where clauses
1402- // precedence, we run into trouble in default methods,
1403- // where both the projection bounds for `Self::A` and
1404- // the where clauses are in scope.
1405- true
1406- }
1407- _ => {
1408- false
1409- }
1415+ match other {
1416+ & ObjectCandidate ( ..) |
1417+ & ParamCandidate ( _) | & ProjectionCandidate => match victim {
1418+ & DefaultImplCandidate ( ..) => {
1419+ self . tcx ( ) . sess . bug (
1420+ "default implementations shouldn't be recorded \
1421+ when there are other valid candidates") ;
1422+ }
1423+ & PhantomFnCandidate => {
1424+ self . tcx ( ) . sess . bug ( "PhantomFn didn't short-circuit selection" ) ;
1425+ }
1426+ & ImplCandidate ( ..) |
1427+ & ClosureCandidate ( ..) |
1428+ & FnPointerCandidate ( ..) |
1429+ & BuiltinObjectCandidate ( ..) |
1430+ & DefaultImplObjectCandidate ( ..) |
1431+ & BuiltinCandidate ( ..) => {
1432+ // We have a where-clause so don't go around looking
1433+ // for impls.
1434+ true
1435+ }
1436+ & ObjectCandidate ( ..) |
1437+ & ProjectionCandidate => {
1438+ // Arbitrarily give param candidates priority
1439+ // over projection and object candidates.
1440+ true
1441+ } ,
1442+ & ParamCandidate ( ..) => false ,
1443+ & ErrorCandidate => false // propagate errors
1444+ } ,
1445+ _ => false
14101446 }
14111447 }
14121448
0 commit comments