Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 23 additions & 6 deletions compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1289,12 +1289,29 @@ where
&mut self,
param_env: I::ParamEnv,
alias_const: ty::AliasConst<I>,
) -> Result<Option<I::Const>, RerunNonErased> {
) -> Result<(Option<I::Const>, 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() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GCE is such a pain lol. It makes sense that this would be necessary though. One of the reasons GCE is a dead feature is because we can't do this change for it and we need to do this change if we're going to stabilize something 😅

Certainty::Yes
} else {
let goal = Goal::new(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we definitely want a nice comment explaining why we do this :3

cx,
param_env,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should prove this in an empty environment so that evaluating something with a where str: Sized where clause doesn't succeed if we're in a function that also has that where clause. that's what makes this fix not just be about "evaluating before checking wf" but also be about avoiding const eval ICEs due to trivial bounds :3

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(
Expand All @@ -1305,11 +1322,11 @@ where
alias_const: ty::AliasConst<I>,
) -> QueryResultOrRerunNonErased<I> {
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
Expand All @@ -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)
}
Expand Down
11 changes: 7 additions & 4 deletions compiler/rustc_next_trait_solver/src/solve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
}

Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_type_ir/src/const_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -84,6 +85,10 @@ impl<I: Interner> AliasConst<I> {
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<I, I::Ty> {
let def_id = match self.kind {
ty::AliasConstKind::Projection { def_id } => def_id.into(),
Expand Down
13 changes: 13 additions & 0 deletions tests/ui/const-generics/gca/impl-block-type-const-type-mismatch.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//! Regression test for <https://github.com/rust-lang/rust/issues/156780>.
//@ 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<const N:usize>: usize = N + 1;
type const A<const N:usize>: usize = ADD1::<N>;
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() {}
Original file line number Diff line number Diff line change
@@ -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`.
11 changes: 11 additions & 0 deletions tests/ui/const-generics/gca/type-const-arg-type-mismatch-1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//! Regression test for <https://github.com/rust-lang/rust/issues/154805>.
//@ compile-flags: -Znext-solver=globally
#![feature(min_generic_const_args)]
#![feature(generic_const_args)]
#![feature(generic_const_items)]

const ADD1<const N: usize>: usize = N + 1;
type const ONE: usize = ADD1::<core::direct_const_arg!(b"")>; //~ 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() {}
27 changes: 27 additions & 0 deletions tests/ui/const-generics/gca/type-const-arg-type-mismatch-1.stderr
Original file line number Diff line number Diff line change
@@ -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::<core::direct_const_arg!(b"")>;
| ^^^^^^^^^^^^^^^^^^^^^ 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::<core::direct_const_arg!(b"")>;
| ^^^^^^^^^^^^^^^^^^^^^ 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<const N: usize>: 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::<core::direct_const_arg!(b"")>;
| ^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found a different `usize`

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0271`.
12 changes: 12 additions & 0 deletions tests/ui/const-generics/gca/type-const-arg-type-mismatch-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//! Regression test for <https://github.com/rust-lang/rust/issues/154805>.
//@ 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<const N: usize>: usize = N + 1;
type const ONE: usize = ADD1::<b"">; //~ 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() {}
27 changes: 27 additions & 0 deletions tests/ui/const-generics/gca/type-const-arg-type-mismatch-2.stderr
Original file line number Diff line number Diff line change
@@ -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::<b"">;
| ^^^^^^^^^^^^^^^^^^^^^ 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::<b"">;
| ^^^^^^^^^^^^^^^^^^^^^ 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<const N: usize>: 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::<b"">;
| ^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found a different `usize`

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0271`.
Loading