Skip to content

Commit 7efd90a

Browse files
Treat normalizing consts like normalizing types in deeply normalize
1 parent 0b20963 commit 7efd90a

File tree

3 files changed

+54
-25
lines changed

3 files changed

+54
-25
lines changed

compiler/rustc_trait_selection/src/solve/normalize.rs

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ use tracing::instrument;
1616
use super::{FulfillmentCtxt, NextSolverError};
1717
use crate::error_reporting::InferCtxtErrorExt;
1818
use crate::error_reporting::traits::OverflowCause;
19-
use crate::traits::query::evaluate_obligation::InferCtxtExt;
2019
use crate::traits::{BoundVarReplacer, PlaceholderReplacer, ScrubbedTraitError};
2120

2221
/// Deeply normalize all aliases in `value`. This does not handle inference and expects
@@ -143,12 +142,18 @@ where
143142

144143
fn normalize_unevaluated_const(
145144
&mut self,
146-
uv: ty::UnevaluatedConst<'tcx>,
145+
alias_ct: ty::Const<'tcx>,
147146
) -> Result<ty::Const<'tcx>, Vec<E>> {
147+
assert_matches!(alias_ct.kind(), ty::ConstKind::Unevaluated(..));
148+
148149
let infcx = self.at.infcx;
149150
let tcx = infcx.tcx;
150151
let recursion_limit = tcx.recursion_limit();
151152
if !recursion_limit.value_within_limit(self.depth) {
153+
let ty::ConstKind::Unevaluated(uv) = alias_ct.kind() else {
154+
unreachable!();
155+
};
156+
152157
self.at.infcx.err_ctxt().report_overflow_error(
153158
OverflowCause::DeeplyNormalize(uv.into()),
154159
self.at.cause.span,
@@ -164,21 +169,20 @@ where
164169
tcx,
165170
self.at.cause.clone(),
166171
self.at.param_env,
167-
ty::NormalizesTo { alias: uv.into(), term: new_infer_ct.into() },
172+
ty::PredicateKind::AliasRelate(
173+
alias_ct.into(),
174+
new_infer_ct.into(),
175+
ty::AliasRelationDirection::Equate,
176+
),
168177
);
169178

170-
let result = if infcx.predicate_may_hold(&obligation) {
171-
self.fulfill_cx.register_predicate_obligation(infcx, obligation);
172-
let errors = self.fulfill_cx.select_where_possible(infcx);
173-
if !errors.is_empty() {
174-
return Err(errors);
175-
}
176-
let ct = infcx.resolve_vars_if_possible(new_infer_ct);
177-
ct.try_fold_with(self)?
178-
} else {
179-
ty::Const::new_unevaluated(tcx, uv).try_super_fold_with(self)?
180-
};
179+
self.fulfill_cx.register_predicate_obligation(infcx, obligation);
180+
self.select_all_and_stall_coroutine_predicates()?;
181181

182+
// Alias is guaranteed to be fully structurally resolved,
183+
// so we can super fold here.
184+
let ct = infcx.resolve_vars_if_possible(new_infer_ct);
185+
let result = ct.try_super_fold_with(self)?;
182186
self.depth -= 1;
183187
Ok(result)
184188
}
@@ -260,15 +264,12 @@ where
260264
return Ok(ct);
261265
}
262266

263-
let uv = match ct.kind() {
264-
ty::ConstKind::Unevaluated(ct) => ct,
265-
_ => return ct.try_super_fold_with(self),
266-
};
267+
let ty::ConstKind::Unevaluated(..) = ct.kind() else { return ct.try_super_fold_with(self) };
267268

268-
if uv.has_escaping_bound_vars() {
269-
let (uv, mapped_regions, mapped_types, mapped_consts) =
270-
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, uv);
271-
let result = ensure_sufficient_stack(|| self.normalize_unevaluated_const(uv))?;
269+
if ct.has_escaping_bound_vars() {
270+
let (ct, mapped_regions, mapped_types, mapped_consts) =
271+
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, ct);
272+
let result = ensure_sufficient_stack(|| self.normalize_unevaluated_const(ct))?;
272273
Ok(PlaceholderReplacer::replace_placeholders(
273274
infcx,
274275
mapped_regions,
@@ -278,7 +279,7 @@ where
278279
result,
279280
))
280281
} else {
281-
ensure_sufficient_stack(|| self.normalize_unevaluated_const(uv))
282+
ensure_sufficient_stack(|| self.normalize_unevaluated_const(ct))
282283
}
283284
}
284285
}
Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
1-
//@ known-bug: #140571
1+
// Regression test for #140571. The compiler used to ICE
2+
3+
#![feature(associated_const_equality, specialization)]
4+
//~^ WARN the feature `specialization` is incomplete
5+
26
pub trait IsVoid {
37
const IS_VOID: bool;
48
}
59
impl<T> IsVoid for T {
610
default const IS_VOID: bool = false;
711
}
8-
impl<T> Maybe<T> for () where T: NotVoid + ?Sized {}
912

1013
pub trait NotVoid {}
1114
impl<T> NotVoid for T where T: IsVoid<IS_VOID = false> + ?Sized {}
1215

1316
pub trait Maybe<T> {}
1417
impl<T> Maybe<T> for T {}
18+
impl<T> Maybe<T> for () where T: NotVoid + ?Sized {}
19+
//~^ ERROR conflicting implementations of trait `Maybe<()>` for type `()`
20+
21+
fn main() {}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/overlap-due-to-unsatisfied-const-bound.rs:3:39
3+
|
4+
LL | #![feature(associated_const_equality, specialization)]
5+
| ^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
8+
= help: consider using `min_specialization` instead, which is more stable and complete
9+
= note: `#[warn(incomplete_features)]` on by default
10+
11+
error[E0119]: conflicting implementations of trait `Maybe<()>` for type `()`
12+
--> $DIR/overlap-due-to-unsatisfied-const-bound.rs:18:1
13+
|
14+
LL | impl<T> Maybe<T> for T {}
15+
| ---------------------- first implementation here
16+
LL | impl<T> Maybe<T> for () where T: NotVoid + ?Sized {}
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
18+
19+
error: aborting due to 1 previous error; 1 warning emitted
20+
21+
For more information about this error, try `rustc --explain E0119`.

0 commit comments

Comments
 (0)