@@ -6,7 +6,7 @@ mod weak_types;
66use rustc_type_ir:: fast_reject:: DeepRejectCtxt ;
77use rustc_type_ir:: inherent:: * ;
88use rustc_type_ir:: lang_items:: TraitSolverLangItem ;
9- use rustc_type_ir:: { self as ty, Interner , NormalizesTo , Upcast as _} ;
9+ use rustc_type_ir:: { self as ty, Interner , NormalizesTo , PredicateKind , Upcast as _} ;
1010use tracing:: instrument;
1111
1212use crate :: delegate:: SolverDelegate ;
@@ -221,13 +221,21 @@ where
221221 Ok ( Some ( target_item_def_id) ) => target_item_def_id,
222222 Ok ( None ) => {
223223 match ecx. typing_mode ( ) {
224- // In case the associated item is hidden due to specialization, we have to
225- // return ambiguity this would otherwise be incomplete, resulting in
226- // unsoundness during coherence (#105782).
224+ // In case the associated item is hidden due to specialization,
225+ // normalizing this associated item is always ambiguous. Treating
226+ // the associated item as rigid would be incomplete and allow for
227+ // overlapping impls, see #105782.
228+ //
229+ // As this ambiguity is unavoidable we emit a nested ambiguous
230+ // goal instead of using `Certainty::AMBIGUOUS`. This allows us to
231+ // return the nested goals to the parent `AliasRelate` goal. This
232+ // would be relevant if any of the nested goals refer to the `term`.
233+ // This is not the case here and we only prefer adding an ambiguous
234+ // nested goal for consistency.
227235 ty:: TypingMode :: Coherence => {
228- return ecx. evaluate_added_goals_and_make_canonical_response (
229- Certainty :: AMBIGUOUS ,
230- ) ;
236+ ecx. add_goal ( GoalSource :: Misc , goal . with ( cx , PredicateKind :: Ambiguous ) ) ;
237+ return ecx
238+ . evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes ) ;
231239 }
232240 // Outside of coherence, we treat the associated item as rigid instead.
233241 ty:: TypingMode :: Analysis { .. }
@@ -254,10 +262,20 @@ where
254262 // treat it as rigid.
255263 if cx. impl_self_is_guaranteed_unsized ( impl_def_id) {
256264 match ecx. typing_mode ( ) {
265+ // Trying to normalize such associated items is always ambiguous
266+ // during coherence to avoid cyclic reasoning. See the example in
267+ // tests/ui/traits/trivial-unsized-projection-in-coherence.rs.
268+ //
269+ // As this ambiguity is unavoidable we emit a nested ambiguous
270+ // goal instead of using `Certainty::AMBIGUOUS`. This allows us to
271+ // return the nested goals to the parent `AliasRelate` goal. This
272+ // would be relevant if any of the nested goals refer to the `term`.
273+ // This is not the case here and we only prefer adding an ambiguous
274+ // nested goal for consistency.
257275 ty:: TypingMode :: Coherence => {
258- return ecx. evaluate_added_goals_and_make_canonical_response (
259- Certainty :: AMBIGUOUS ,
260- ) ;
276+ ecx. add_goal ( GoalSource :: Misc , goal . with ( cx , PredicateKind :: Ambiguous ) ) ;
277+ return ecx
278+ . evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes ) ;
261279 }
262280 ty:: TypingMode :: Analysis { .. }
263281 | ty:: TypingMode :: Borrowck { .. }
0 commit comments