Skip to content

Commit

Permalink
Rollup merge of rust-lang#132169 - fee1-dead-contrib:consttraitsck, r…
Browse files Browse the repository at this point in the history
…=compiler-errors

Deny calls to non-`#[const_trait]` methods in MIR constck

This is a (potentially temporary) fix that closes off the mismatch in assumptions between MIR constck and typeck which does the const traits checking. Before this PR, MIR constck assumed that typeck correctly handled all calls to trait methods in const contexts if effects is enabled. That is not true because typeck only correctly handles callees that are const. For non-const callees (such as methods in a non-const_trait), typeck had never created an error.

https://github.com/rust-lang/rust/blob/45089ec19ebebec88bace6ec237244ff0eaa7ad3/compiler/rustc_hir_typeck/src/callee.rs#L876-L877

I called this potentially temporary because the const checks could be moved to HIR entirely. Alongside the recent refactor in const stability checks where that component could be placed would need more discussion. (cc `@compiler-errors` `@RalfJung)`

Tests are updated, mainly due to traits not being const in core, so tests that call them correctly error.

This fixes rust-lang/project-const-traits#12.
  • Loading branch information
Zalathar authored Oct 26, 2024
2 parents a72b321 + f2f6723 commit 18aa883
Show file tree
Hide file tree
Showing 75 changed files with 438 additions and 324 deletions.
29 changes: 19 additions & 10 deletions compiler/rustc_const_eval/src/check_consts/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -616,14 +616,16 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {

let mut is_trait = false;
// Attempting to call a trait method?
if tcx.trait_of_item(callee).is_some() {
if let Some(trait_did) = tcx.trait_of_item(callee) {
trace!("attempting to call a trait method");

let trait_is_const = tcx.is_const_trait(trait_did);
// trait method calls are only permitted when `effects` is enabled.
// we don't error, since that is handled by typeck. We try to resolve
// the trait into the concrete method, and uses that for const stability
// checks.
// typeck ensures the conditions for calling a const trait method are met,
// so we only error if the trait isn't const. We try to resolve the trait
// into the concrete method, and uses that for const stability checks.
// FIXME(effects) we might consider moving const stability checks to typeck as well.
if tcx.features().effects() {
if tcx.features().effects() && trait_is_const {
// This skips the check below that ensures we only call `const fn`.
is_trait = true;

Expand All @@ -638,17 +640,24 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
callee = def;
}
} else {
// if the trait is const but the user has not enabled the feature(s),
// suggest them.
let feature = if trait_is_const {
Some(if tcx.features().const_trait_impl() {
sym::effects
} else {
sym::const_trait_impl
})
} else {
None
};
self.check_op(ops::FnCallNonConst {
caller,
callee,
args: fn_args,
span: *fn_span,
call_source,
feature: Some(if tcx.features().const_trait_impl() {
sym::effects
} else {
sym::const_trait_impl
}),
feature,
});
// If we allowed this, we're in miri-unleashed mode, so we might
// as well skip the remaining checks.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@ LL + #[derive(ConstParamTy)]
LL | struct Foo(u8);
|

error[E0284]: type annotations needed: cannot normalize `foo<N>::{constant#0}`
--> $DIR/unify-op-with-fn-call.rs:20:25
error[E0015]: cannot call non-const operator in constants
--> $DIR/unify-op-with-fn-call.rs:20:39
|
LL | fn foo<const N: Foo>(a: Evaluatable<{ N + N }>) {
| ^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `foo<N>::{constant#0}`
| ^^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants

error[E0741]: `Foo` must implement `ConstParamTy` to be used as the type of a const generic parameter
--> $DIR/unify-op-with-fn-call.rs:20:17
Expand Down Expand Up @@ -63,19 +65,29 @@ error[E0284]: type annotations needed: cannot normalize `foo2<N>::{constant#0}`
LL | fn foo2<const N: usize>(a: Evaluatable2<{ N + N }>) {
| ^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `foo2<N>::{constant#0}`

error[E0284]: type annotations needed: cannot normalize `foo<N>::{constant#0}`
--> $DIR/unify-op-with-fn-call.rs:21:11
error[E0015]: cannot call non-const fn `<Foo as Add>::add` in constants
--> $DIR/unify-op-with-fn-call.rs:21:13
|
LL | bar::<{ std::ops::Add::add(N, N) }>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `foo<N>::{constant#0}`
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants

error[E0015]: cannot call non-const fn `<usize as Add>::add` in constants
--> $DIR/unify-op-with-fn-call.rs:30:14
|
LL | bar2::<{ std::ops::Add::add(N, N) }>();
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants

error[E0284]: type annotations needed: cannot normalize `foo2<N>::{constant#0}`
--> $DIR/unify-op-with-fn-call.rs:30:12
|
LL | bar2::<{ std::ops::Add::add(N, N) }>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `foo2<N>::{constant#0}`

error: aborting due to 9 previous errors
error: aborting due to 10 previous errors

Some errors have detailed explanations: E0284, E0741.
For more information about an error, try `rustc --explain E0284`.
Some errors have detailed explanations: E0015, E0284, E0741.
For more information about an error, try `rustc --explain E0015`.
4 changes: 0 additions & 4 deletions tests/ui/const-generics/issue-93647.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ LL | (||1usize)()
|
= note: closures need an RFC before allowed to be called in constants
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|

error: aborting due to 1 previous error

Expand Down
8 changes: 0 additions & 8 deletions tests/ui/const-generics/issues/issue-90318.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/any.rs:LL:COL
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|

error[E0015]: cannot call non-const operator in constants
--> $DIR/issue-90318.rs:22:10
Expand All @@ -43,10 +39,6 @@ LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/any.rs:LL:COL
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|

error: aborting due to 4 previous errors

Expand Down
6 changes: 3 additions & 3 deletions tests/ui/consts/closure-in-foreign-crate.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//@ aux-build:closure-in-foreign-crate.rs
// FIXME(effects) aux-build:closure-in-foreign-crate.rs
//@ build-pass

extern crate closure_in_foreign_crate;
// FIXME(effects) extern crate closure_in_foreign_crate;

const _: () = closure_in_foreign_crate::test();
// FIXME(effects) const _: () = closure_in_foreign_crate::test();

fn main() {}
8 changes: 0 additions & 8 deletions tests/ui/consts/const-fn-error.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ LL | for i in 0..x {
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|

error[E0015]: cannot call non-const fn `<std::ops::Range<usize> as Iterator>::next` in constant functions
--> $DIR/const-fn-error.rs:5:14
Expand All @@ -34,10 +30,6 @@ LL | for i in 0..x {
| ^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|

error: aborting due to 3 previous errors

Expand Down
8 changes: 0 additions & 8 deletions tests/ui/consts/const-for-feature-gate.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ LL | for _ in 0..5 {}
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|

error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants
--> $DIR/const-for-feature-gate.rs:4:14
Expand All @@ -29,10 +25,6 @@ LL | for _ in 0..5 {}
| ^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|

error: aborting due to 3 previous errors

Expand Down
8 changes: 0 additions & 8 deletions tests/ui/consts/const-for.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ LL | for _ in 0..5 {}
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|

error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants
--> $DIR/const-for.rs:4:14
Expand All @@ -19,10 +15,6 @@ LL | for _ in 0..5 {}
| ^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|

error: aborting due to 2 previous errors

Expand Down
8 changes: 0 additions & 8 deletions tests/ui/consts/const-try-feature-gate.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ LL | Some(())?;
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/option.rs:LL:COL
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|

error[E0015]: `?` cannot convert from residual of `Option<()>` in constant functions
--> $DIR/const-try-feature-gate.rs:4:5
Expand All @@ -31,10 +27,6 @@ LL | Some(())?;
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/option.rs:LL:COL
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|

error: aborting due to 3 previous errors

Expand Down
2 changes: 2 additions & 0 deletions tests/ui/consts/const-try.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ impl const Try for TryMe {

const fn t() -> TryMe {
TryMe?;
//~^ ERROR `?` cannot determine the branch of `TryMe` in constant functions
//~| ERROR `?` cannot convert from residual of `TryMe` in constant functions
TryMe
}

Expand Down
19 changes: 18 additions & 1 deletion tests/ui/consts/const-try.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,22 @@ LL | impl const Try for TryMe {
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
= note: adding a non-const method body in the future would be a breaking change

error: aborting due to 2 previous errors
error[E0015]: `?` cannot determine the branch of `TryMe` in constant functions
--> $DIR/const-try.rs:36:5
|
LL | TryMe?;
| ^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants

error[E0015]: `?` cannot convert from residual of `TryMe` in constant functions
--> $DIR/const-try.rs:36:5
|
LL | TryMe?;
| ^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0015`.
7 changes: 4 additions & 3 deletions tests/ui/consts/const_cmp_type_id.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
//@ check-pass
//@ compile-flags: -Znext-solver
#![feature(const_type_id, const_trait_impl, effects)]
#![allow(incomplete_features)]
Expand All @@ -7,11 +6,13 @@ use std::any::TypeId;

fn main() {
const {
// FIXME(effects) this isn't supposed to pass (right now) but it did.
// revisit binops typeck please.
assert!(TypeId::of::<u8>() == TypeId::of::<u8>());
//~^ ERROR cannot call non-const operator in constants
assert!(TypeId::of::<()>() != TypeId::of::<u8>());
//~^ ERROR cannot call non-const operator in constants
let _a = TypeId::of::<u8>() < TypeId::of::<u16>();
//~^ ERROR cannot call non-const operator in constants
// can't assert `_a` because it is not deterministic
// FIXME(effects) make it pass
}
}
34 changes: 34 additions & 0 deletions tests/ui/consts/const_cmp_type_id.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
error[E0015]: cannot call non-const operator in constants
--> $DIR/const_cmp_type_id.rs:9:17
|
LL | assert!(TypeId::of::<u8>() == TypeId::of::<u8>());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/any.rs:LL:COL
= note: calls in constants are limited to constant functions, tuple structs and tuple variants

error[E0015]: cannot call non-const operator in constants
--> $DIR/const_cmp_type_id.rs:11:17
|
LL | assert!(TypeId::of::<()>() != TypeId::of::<u8>());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/any.rs:LL:COL
= note: calls in constants are limited to constant functions, tuple structs and tuple variants

error[E0015]: cannot call non-const operator in constants
--> $DIR/const_cmp_type_id.rs:13:18
|
LL | let _a = TypeId::of::<u8>() < TypeId::of::<u16>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/any.rs:LL:COL
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
= note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0015`.
16 changes: 0 additions & 16 deletions tests/ui/consts/control-flow/loop.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,6 @@ LL | for i in 0..4 {
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|

error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants
--> $DIR/loop.rs:53:14
Expand All @@ -47,10 +43,6 @@ LL | for i in 0..4 {
| ^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|

error[E0015]: cannot convert `std::ops::Range<i32>` into an iterator in constants
--> $DIR/loop.rs:59:14
Expand All @@ -61,10 +53,6 @@ LL | for i in 0..4 {
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|

error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants
--> $DIR/loop.rs:59:14
Expand All @@ -73,10 +61,6 @@ LL | for i in 0..4 {
| ^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|

error: aborting due to 6 previous errors

Expand Down
8 changes: 0 additions & 8 deletions tests/ui/consts/control-flow/try.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ LL | x?;
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/option.rs:LL:COL
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|

error[E0015]: `?` cannot convert from residual of `Option<i32>` in constant functions
--> $DIR/try.rs:6:5
Expand All @@ -31,10 +27,6 @@ LL | x?;
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/option.rs:LL:COL
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|

error: aborting due to 3 previous errors

Expand Down
Loading

0 comments on commit 18aa883

Please sign in to comment.