diff options
| author | Michael Goulet <michael@errs.io> | 2025-06-06 17:00:06 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2025-06-06 17:13:53 +0000 |
| commit | 7efd90a1a56f5f4cf5a73f40b1b84032407873a1 (patch) | |
| tree | 8aa22c1e1ef708b90df62fead5d6a2f23f60a9d7 | |
| parent | 0b20963d6b892651937fb3600e15ca285bdcfefd (diff) | |
Treat normalizing consts like normalizing types in deeply normalize
| -rw-r--r-- | compiler/rustc_trait_selection/src/solve/normalize.rs | 47 | ||||
| -rw-r--r-- | tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs (renamed from tests/crashes/140571.rs) | 11 | ||||
| -rw-r--r-- | tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.stderr | 21 |
3 files changed, 54 insertions, 25 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index d903f94b489..a8d32221204 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -16,7 +16,6 @@ use tracing::instrument; use super::{FulfillmentCtxt, NextSolverError}; use crate::error_reporting::InferCtxtErrorExt; use crate::error_reporting::traits::OverflowCause; -use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::{BoundVarReplacer, PlaceholderReplacer, ScrubbedTraitError}; /// Deeply normalize all aliases in `value`. This does not handle inference and expects @@ -143,12 +142,18 @@ where fn normalize_unevaluated_const( &mut self, - uv: ty::UnevaluatedConst<'tcx>, + alias_ct: ty::Const<'tcx>, ) -> Result<ty::Const<'tcx>, Vec<E>> { + assert_matches!(alias_ct.kind(), ty::ConstKind::Unevaluated(..)); + let infcx = self.at.infcx; let tcx = infcx.tcx; let recursion_limit = tcx.recursion_limit(); if !recursion_limit.value_within_limit(self.depth) { + let ty::ConstKind::Unevaluated(uv) = alias_ct.kind() else { + unreachable!(); + }; + self.at.infcx.err_ctxt().report_overflow_error( OverflowCause::DeeplyNormalize(uv.into()), self.at.cause.span, @@ -164,21 +169,20 @@ where tcx, self.at.cause.clone(), self.at.param_env, - ty::NormalizesTo { alias: uv.into(), term: new_infer_ct.into() }, + ty::PredicateKind::AliasRelate( + alias_ct.into(), + new_infer_ct.into(), + ty::AliasRelationDirection::Equate, + ), ); - let result = if infcx.predicate_may_hold(&obligation) { - self.fulfill_cx.register_predicate_obligation(infcx, obligation); - let errors = self.fulfill_cx.select_where_possible(infcx); - if !errors.is_empty() { - return Err(errors); - } - let ct = infcx.resolve_vars_if_possible(new_infer_ct); - ct.try_fold_with(self)? - } else { - ty::Const::new_unevaluated(tcx, uv).try_super_fold_with(self)? - }; + self.fulfill_cx.register_predicate_obligation(infcx, obligation); + self.select_all_and_stall_coroutine_predicates()?; + // Alias is guaranteed to be fully structurally resolved, + // so we can super fold here. + let ct = infcx.resolve_vars_if_possible(new_infer_ct); + let result = ct.try_super_fold_with(self)?; self.depth -= 1; Ok(result) } @@ -260,15 +264,12 @@ where return Ok(ct); } - let uv = match ct.kind() { - ty::ConstKind::Unevaluated(ct) => ct, - _ => return ct.try_super_fold_with(self), - }; + let ty::ConstKind::Unevaluated(..) = ct.kind() else { return ct.try_super_fold_with(self) }; - if uv.has_escaping_bound_vars() { - let (uv, mapped_regions, mapped_types, mapped_consts) = - BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, uv); - let result = ensure_sufficient_stack(|| self.normalize_unevaluated_const(uv))?; + if ct.has_escaping_bound_vars() { + let (ct, mapped_regions, mapped_types, mapped_consts) = + BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, ct); + let result = ensure_sufficient_stack(|| self.normalize_unevaluated_const(ct))?; Ok(PlaceholderReplacer::replace_placeholders( infcx, mapped_regions, @@ -278,7 +279,7 @@ where result, )) } else { - ensure_sufficient_stack(|| self.normalize_unevaluated_const(uv)) + ensure_sufficient_stack(|| self.normalize_unevaluated_const(ct)) } } } diff --git a/tests/crashes/140571.rs b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs index 97fa1d8432d..f4cde1d62b2 100644 --- a/tests/crashes/140571.rs +++ b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs @@ -1,14 +1,21 @@ -//@ known-bug: #140571 +// Regression test for #140571. The compiler used to ICE + +#![feature(associated_const_equality, specialization)] +//~^ WARN the feature `specialization` is incomplete + pub trait IsVoid { const IS_VOID: bool; } impl<T> IsVoid for T { default const IS_VOID: bool = false; } -impl<T> Maybe<T> for () where T: NotVoid + ?Sized {} pub trait NotVoid {} impl<T> NotVoid for T where T: IsVoid<IS_VOID = false> + ?Sized {} pub trait Maybe<T> {} impl<T> Maybe<T> for T {} +impl<T> Maybe<T> for () where T: NotVoid + ?Sized {} +//~^ ERROR conflicting implementations of trait `Maybe<()>` for type `()` + +fn main() {} diff --git a/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.stderr b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.stderr new file mode 100644 index 00000000000..a26b30fbb63 --- /dev/null +++ b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.stderr @@ -0,0 +1,21 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/overlap-due-to-unsatisfied-const-bound.rs:3:39 + | +LL | #![feature(associated_const_equality, specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0119]: conflicting implementations of trait `Maybe<()>` for type `()` + --> $DIR/overlap-due-to-unsatisfied-const-bound.rs:18:1 + | +LL | impl<T> Maybe<T> for T {} + | ---------------------- first implementation here +LL | impl<T> Maybe<T> for () where T: NotVoid + ?Sized {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0119`. |
