diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index c3ccb46069063..b9788d49efed8 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -1289,12 +1289,29 @@ where &mut self, param_env: I::ParamEnv, alias_const: ty::AliasConst, - ) -> Result, RerunNonErased> { + ) -> Result<(Option, Certainty), NoSolutionOrRerunNonErased> { if self.typing_mode().is_erased_not_coherence() { match self.opaque_accesses.rerun_always(RerunReason::EvaluateConst)? {} } + let cx = self.cx(); + let certainty = if cx.features().generic_const_exprs() { + Certainty::Yes + } else { + let goal = Goal::new( + cx, + param_env, + ty::ClauseKind::WellFormed(alias_const.to_const(cx, ty::IsRigid::Yes).into()), + ); + self.add_goal(GoalSource::AliasWellFormed, goal)?; + let certainty = self.try_evaluate_added_goals()?; + + if matches!(certainty, Certainty::Maybe(_)) { + return Ok((None, certainty)); + } + certainty + }; - Ok(self.delegate.evaluate_const(param_env, alias_const)) + Ok((self.delegate.evaluate_const(param_env, alias_const), certainty)) } pub(super) fn evaluate_const_and_instantiate_projection_term( @@ -1305,11 +1322,11 @@ where alias_const: ty::AliasConst, ) -> QueryResultOrRerunNonErased { match self.evaluate_const(param_env, alias_const)? { - Some(evaluated) => { + (Some(evaluated), _) => { self.eq(param_env, expected_term, evaluated.into())?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } - None if self.cx().features().generic_const_args() => { + (None, certainty) if self.cx().features().generic_const_args() => { // HACK(khyperia): calling `resolve_vars_if_possible` here shouldn't be necessary, // `try_evaluate_const` calls `resolve_vars_if_possible` already. However, we want // to check `has_non_region_infer` against the type with vars resolved (i.e. check @@ -1331,10 +1348,10 @@ where projection_term.to_term(self.cx(), ty::IsRigid::Yes), expected_term, )?; - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + self.evaluate_added_goals_and_make_canonical_response(certainty) } } - None => { + (None, _) => { // Legacy behavior: always treat as ambiguous self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) } diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 195f08dfafd59..07c6219203807 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -215,10 +215,13 @@ where // FIXME(generic_const_exprs): Implement handling for generic // const expressions here. - if let Some(_normalized) = self.evaluate_const(param_env, alias_const)? { - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - } else { - self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) + match self.evaluate_const(param_env, alias_const)? { + (None, certainty) => self.evaluate_added_goals_and_make_canonical_response( + certainty.and(Certainty::AMBIGUOUS), + ), + (Some(_normalized), _) => { + self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } } } diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index 29c65974d8b28..a48ad4cfe1ac8 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -9,6 +9,7 @@ use rustc_type_ir_macros::{ GenericTypeVisitable, Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic, }; +use crate::inherent::*; use crate::{self as ty, AliasConst, BoundVarIndexKind, Interner}; /// Represents a constant in Rust. @@ -84,6 +85,10 @@ impl AliasConst { AliasConst { kind, args, _use_alias_new_instead: () } } + pub fn to_const(self, interner: I, is_rigid: ty::IsRigid) -> I::Const { + I::Const::new_alias(interner, is_rigid, self) + } + pub fn type_of(self, interner: I) -> ty::Unnormalized { let def_id = match self.kind { ty::AliasConstKind::Projection { def_id } => def_id.into(), diff --git a/tests/ui/const-generics/gca/impl-block-type-const-type-mismatch.rs b/tests/ui/const-generics/gca/impl-block-type-const-type-mismatch.rs new file mode 100644 index 0000000000000..a0731e8daf277 --- /dev/null +++ b/tests/ui/const-generics/gca/impl-block-type-const-type-mismatch.rs @@ -0,0 +1,13 @@ +//! Regression test for . +//@ compile-flags: -Znext-solver=globally +#![feature(min_generic_const_args)] +#![feature(generic_const_args)] +#![feature(generic_const_items)] +#![feature(macroless_generic_const_args)] + +const ADD1: usize = N + 1; +type const A: usize = ADD1::; +impl [(); A::<1f64>] {} //~ ERROR: type mismatch resolving `A<1f64> == _` [E0271] +//~| ERROR: cannot define inherent `impl` for primitive types [E0390] + //~^^ ERROR: the type `[(); A::<1f64>]` is not well-formed +fn main() {} diff --git a/tests/ui/const-generics/gca/impl-block-type-const-type-mismatch.stderr b/tests/ui/const-generics/gca/impl-block-type-const-type-mismatch.stderr new file mode 100644 index 0000000000000..d274f9e233121 --- /dev/null +++ b/tests/ui/const-generics/gca/impl-block-type-const-type-mismatch.stderr @@ -0,0 +1,24 @@ +error[E0271]: type mismatch resolving `A<1f64> == _` + --> $DIR/impl-block-type-const-type-mismatch.rs:10:1 + | +LL | impl [(); A::<1f64>] {} + | ^^^^^^^^^^^^^^^^^^^^^^^ types differ + +error: the type `[(); A::<1f64>]` is not well-formed + --> $DIR/impl-block-type-const-type-mismatch.rs:10:6 + | +LL | impl [(); A::<1f64>] {} + | ^^^^^^^^^^^^^^^ + +error[E0390]: cannot define inherent `impl` for primitive types + --> $DIR/impl-block-type-const-type-mismatch.rs:10:1 + | +LL | impl [(); A::<1f64>] {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using an extension trait instead + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0271, E0390. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/const-generics/gca/type-const-arg-type-mismatch-1.rs b/tests/ui/const-generics/gca/type-const-arg-type-mismatch-1.rs new file mode 100644 index 0000000000000..42620ca444389 --- /dev/null +++ b/tests/ui/const-generics/gca/type-const-arg-type-mismatch-1.rs @@ -0,0 +1,11 @@ +//! Regression test for . +//@ compile-flags: -Znext-solver=globally +#![feature(min_generic_const_args)] +#![feature(generic_const_args)] +#![feature(generic_const_items)] + +const ADD1: usize = N + 1; +type const ONE: usize = ADD1::; //~ ERROR type mismatch resolving +//~| ERROR the constant `*b""` is not of type `usize` +//~| ERROR the constant `ADD1::<*b"">` is not of type `usize` +fn main() {} diff --git a/tests/ui/const-generics/gca/type-const-arg-type-mismatch-1.stderr b/tests/ui/const-generics/gca/type-const-arg-type-mismatch-1.stderr new file mode 100644 index 0000000000000..3ecedd7a4353b --- /dev/null +++ b/tests/ui/const-generics/gca/type-const-arg-type-mismatch-1.stderr @@ -0,0 +1,27 @@ +error[E0271]: type mismatch resolving `ADD1<*b""> == _` + --> $DIR/type-const-arg-type-mismatch-1.rs:8:1 + | +LL | type const ONE: usize = ADD1::; + | ^^^^^^^^^^^^^^^^^^^^^ types differ + +error: the constant `*b""` is not of type `usize` + --> $DIR/type-const-arg-type-mismatch-1.rs:8:1 + | +LL | type const ONE: usize = ADD1::; + | ^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `[u8; 0]` + | +note: required by a const generic parameter in `ADD1` + --> $DIR/type-const-arg-type-mismatch-1.rs:7:12 + | +LL | const ADD1: usize = N + 1; + | ^^^^^^^^^^^^^^ required by this const generic parameter in `ADD1` + +error: the constant `ADD1::<*b"">` is not of type `usize` + --> $DIR/type-const-arg-type-mismatch-1.rs:8:1 + | +LL | type const ONE: usize = ADD1::; + | ^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found a different `usize` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/const-generics/gca/type-const-arg-type-mismatch-2.rs b/tests/ui/const-generics/gca/type-const-arg-type-mismatch-2.rs new file mode 100644 index 0000000000000..e4d7e20fcfce4 --- /dev/null +++ b/tests/ui/const-generics/gca/type-const-arg-type-mismatch-2.rs @@ -0,0 +1,12 @@ +//! Regression test for . +//@ compile-flags: -Znext-solver=globally +#![feature(min_generic_const_args)] +#![feature(macroless_generic_const_args)] +#![feature(generic_const_args)] +#![feature(generic_const_items)] + +const ADD1: usize = N + 1; +type const ONE: usize = ADD1::; //~ ERROR type mismatch resolving +//~| ERROR the constant `*b""` is not of type `usize` +//~| ERROR the constant `ADD1::<*b"">` is not of type `usize` +fn main() {} diff --git a/tests/ui/const-generics/gca/type-const-arg-type-mismatch-2.stderr b/tests/ui/const-generics/gca/type-const-arg-type-mismatch-2.stderr new file mode 100644 index 0000000000000..0dbab7e09a7ce --- /dev/null +++ b/tests/ui/const-generics/gca/type-const-arg-type-mismatch-2.stderr @@ -0,0 +1,27 @@ +error[E0271]: type mismatch resolving `ADD1<*b""> == _` + --> $DIR/type-const-arg-type-mismatch-2.rs:9:1 + | +LL | type const ONE: usize = ADD1::; + | ^^^^^^^^^^^^^^^^^^^^^ types differ + +error: the constant `*b""` is not of type `usize` + --> $DIR/type-const-arg-type-mismatch-2.rs:9:1 + | +LL | type const ONE: usize = ADD1::; + | ^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `[u8; 0]` + | +note: required by a const generic parameter in `ADD1` + --> $DIR/type-const-arg-type-mismatch-2.rs:8:12 + | +LL | const ADD1: usize = N + 1; + | ^^^^^^^^^^^^^^ required by this const generic parameter in `ADD1` + +error: the constant `ADD1::<*b"">` is not of type `usize` + --> $DIR/type-const-arg-type-mismatch-2.rs:9:1 + | +LL | type const ONE: usize = ADD1::; + | ^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found a different `usize` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0271`.