Skip to content

Commit fa90fea

Browse files
committed
only return nested goals for Certainty::Yes
1 parent cb31a00 commit fa90fea

File tree

3 files changed

+42
-18
lines changed

3 files changed

+42
-18
lines changed

compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,19 +110,19 @@ where
110110
//
111111
// As we return all ambiguous nested goals, we can ignore the certainty returned
112112
// by `try_evaluate_added_goals()`.
113-
let (certainty, normalization_nested_goals) = match self.current_goal_kind {
114-
CurrentGoalKind::NormalizesTo => {
113+
let (certainty, normalization_nested_goals) =
114+
if matches!(self.current_goal_kind, CurrentGoalKind::NormalizesTo)
115+
&& matches!(certainty, Certainty::Yes)
116+
{
115117
let goals = std::mem::take(&mut self.nested_goals);
116118
if goals.is_empty() {
117119
assert!(matches!(goals_certainty, Certainty::Yes));
118120
}
119-
(certainty, NestedNormalizationGoals(goals))
120-
}
121-
CurrentGoalKind::Misc | CurrentGoalKind::CoinductiveTrait => {
121+
(Certainty::Yes, NestedNormalizationGoals(goals))
122+
} else {
122123
let certainty = certainty.unify_with(goals_certainty);
123124
(certainty, NestedNormalizationGoals::empty())
124-
}
125-
};
125+
};
126126

127127
if let Certainty::Maybe(cause @ MaybeCause::Overflow { .. }) = certainty {
128128
// If we have overflow, it's probable that we're substituting a type

compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ mod weak_types;
66
use rustc_type_ir::fast_reject::DeepRejectCtxt;
77
use rustc_type_ir::inherent::*;
88
use 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 _};
1010
use tracing::instrument;
1111

1212
use 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 { .. }

compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
44
use rustc_index::bit_set::GrowableBitSet;
55
use rustc_type_ir::inherent::*;
6+
use rustc_type_ir::solve::GoalSource;
67
use rustc_type_ir::{self as ty, Interner, TypingMode, fold_regions};
78

89
use crate::delegate::SolverDelegate;
@@ -31,7 +32,12 @@ where
3132
goal.param_env,
3233
expected,
3334
);
34-
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
35+
// Trying to normalize an opaque type during coherence is always ambiguous.
36+
// We add a nested ambiguous goal here instead of using `Certainty::AMBIGUOUS`.
37+
// This allows us to return the nested goals to the parent `AliasRelate` goal.
38+
// This can then allow nested goals to fail after we've constrained the `term`.
39+
self.add_goal(GoalSource::Misc, goal.with(cx, ty::PredicateKind::Ambiguous));
40+
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
3541
}
3642
TypingMode::Analysis { defining_opaque_types_and_generators } => {
3743
let Some(def_id) = opaque_ty

0 commit comments

Comments
 (0)