From 02e10b2d90c8d4f0cb3f0f2b4a6a8a3283efa9c3 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Mon, 26 Jan 2026 13:00:58 -0500 Subject: [PATCH] fix issues and ui tests, address reviews --- .../src/check_consts/check.rs | 4 +-- compiler/rustc_feature/src/builtin_attrs.rs | 2 +- .../src/check/compare_impl_item.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 5 ++- src/doc/rustc-dev-guide/src/SUMMARY.md | 2 +- src/doc/rustc-dev-guide/src/effects.md | 17 +++++++++- .../const-traits/partial/attr-gate.stderr | 2 +- .../const-traits/partial/no-const-callers.rs | 17 ++++++++++ .../partial/no-const-callers.stderr | 32 +++++++++++++++++-- .../typeck_type_placeholder_item.stderr | 14 -------- 10 files changed, 72 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 2abbf75984a4..57396b657a3f 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -774,8 +774,8 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location // Attempting to call a trait method? if let Some(trait_did) = tcx.trait_of_assoc(callee) { - // We can't determine the actual callee here, so we have to do different checks - // than usual. + // We can't determine the actual callee (the underlying impl of the trait) here, so we have + // to do different checks than usual. trace!("attempting to call a trait method"); let is_const = tcx.constness(callee) == hir::Constness::Const; diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 8f447e1477b3..182ef6816337 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -1333,7 +1333,7 @@ pub struct BuiltinAttribute { rustc_non_const_trait_method, AttributeType::Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::No, "`#[rustc_non_const_trait_method]` should only used by the standard library to mark trait methods \ - as non-const to allow large traits to easier transition to const" + as non-const to allow large traits an easier transition to const" ), BuiltinAttribute { diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index dd7b03c9dac3..9e07d5260d20 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -218,7 +218,7 @@ fn compare_method_predicate_entailment<'tcx>( trait_m_predicates.instantiate_own(tcx, trait_to_impl_args).map(|(predicate, _)| predicate), ); - let is_conditionally_const = tcx.is_conditionally_const(impl_def_id); + let is_conditionally_const = tcx.is_conditionally_const(impl_m.def_id); if is_conditionally_const { // Augment the hybrid param-env with the const conditions // of the impl header and the trait method. diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 044c99ffeb21..4e33b8ebb6de 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2087,7 +2087,10 @@ pub fn is_conditionally_const(self, def_id: impl Into) -> bool { self.constness(def_id) == hir::Constness::Const } DefKind::Impl { of_trait: true } => { - self.constness(self.trait_item_of(def_id).unwrap()) == hir::Constness::Const + let Some(trait_method_did) = self.trait_item_of(def_id) else { + return false; + }; + self.constness(trait_method_did) == hir::Constness::Const && self.is_conditionally_const(parent_def_id) } DefKind::Trait => { diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 1f9e0aac9d0b..5342c54607b7 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -199,7 +199,7 @@ - [Inference details](./opaque-types-impl-trait-inference.md) - [Return Position Impl Trait In Trait](./return-position-impl-trait-in-trait.md) - [Region inference restrictions](./borrow-check/opaque-types-region-inference-restrictions.md) -- [Const condition checking](./effects.md) +- [Const traits and const condition checking](./effects.md) - [Pattern and exhaustiveness checking](./pat-exhaustive-checking.md) - [Unsafety checking](./unsafety-checking.md) - [MIR dataflow](./mir/dataflow.md) diff --git a/src/doc/rustc-dev-guide/src/effects.md b/src/doc/rustc-dev-guide/src/effects.md index 87b0103a7bc4..732ba7153116 100644 --- a/src/doc/rustc-dev-guide/src/effects.md +++ b/src/doc/rustc-dev-guide/src/effects.md @@ -1,4 +1,4 @@ -# Effects and const condition checking +# Effects, const traits, and const condition checking ## The `HostEffect` predicate @@ -154,3 +154,18 @@ be dropped at compile time. [old solver]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_trait_selection/traits/effects.rs.html [new trait solver]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_next_trait_solver/solve/effect_goals.rs.html + +## More on const traits + +To be expanded later. + +### The `#[rustc_non_const_trait_method]` attribute + +This is intended for internal (standard library) usage only. With this attribute +applied to a trait method, the compiler will not check the default body of this +method for ability to run in compile time. Users of the trait will also not be +allowed to use this trait method in const contexts. This attribute is primarily +used for constifying large traits such as `Iterator` without having to make all +its methods `const` at the same time. + +This attribute should not be present while stabilizing the trait as `const`. diff --git a/tests/ui/traits/const-traits/partial/attr-gate.stderr b/tests/ui/traits/const-traits/partial/attr-gate.stderr index bc86cbe4edf7..e46e35d036be 100644 --- a/tests/ui/traits/const-traits/partial/attr-gate.stderr +++ b/tests/ui/traits/const-traits/partial/attr-gate.stderr @@ -6,7 +6,7 @@ LL | #[rustc_non_const_trait_method] | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable = note: the `#[rustc_non_const_trait_method]` attribute is an internal implementation detail that will never be stable - = note: `#[rustc_non_const_trait_method]` should only used by the standard library to mark trait methods as non-const to allow large traits to easier transition to const + = note: `#[rustc_non_const_trait_method]` should only used by the standard library to mark trait methods as non-const to allow large traits an easier transition to const error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/partial/no-const-callers.rs b/tests/ui/traits/const-traits/partial/no-const-callers.rs index efcdea36f1ca..7c198f41ce42 100644 --- a/tests/ui/traits/const-traits/partial/no-const-callers.rs +++ b/tests/ui/traits/const-traits/partial/no-const-callers.rs @@ -10,6 +10,17 @@ impl const A for () { fn a() {} } +impl const A for u8 { + fn a() {} + fn b() { println!("hello"); } + //~^ ERROR: cannot call non-const function +} + +impl const A for i8 { + fn a() {} + fn b() {} +} + const fn foo() { T::a(); T::b(); @@ -17,6 +28,12 @@ const fn foo() { <()>::a(); <()>::b(); //~^ ERROR: cannot call non-const associated function + u8::a(); + u8::b(); + //~^ ERROR: cannot call non-const associated function + i8::a(); + i8::b(); + //~^ ERROR: cannot call non-const associated function } fn main() {} diff --git a/tests/ui/traits/const-traits/partial/no-const-callers.stderr b/tests/ui/traits/const-traits/partial/no-const-callers.stderr index 31179161c5cd..bbb4495943ed 100644 --- a/tests/ui/traits/const-traits/partial/no-const-callers.stderr +++ b/tests/ui/traits/const-traits/partial/no-const-callers.stderr @@ -1,5 +1,15 @@ +error[E0015]: cannot call non-const function `std::io::_print` in constant functions + --> $DIR/no-const-callers.rs:15:14 + | +LL | fn b() { println!("hello"); } + | ^^^^^^^^^^^^^^^^^ + | +note: function `_print` is not const + --> $SRC_DIR/std/src/io/stdio.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + error[E0015]: cannot call non-const associated function `::b` in constant functions - --> $DIR/no-const-callers.rs:15:5 + --> $DIR/no-const-callers.rs:26:5 | LL | T::b(); | ^^^^^^ @@ -7,13 +17,29 @@ LL | T::b(); = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants error[E0015]: cannot call non-const associated function `<() as A>::b` in constant functions - --> $DIR/no-const-callers.rs:18:5 + --> $DIR/no-const-callers.rs:29:5 | LL | <()>::b(); | ^^^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to 2 previous errors +error[E0015]: cannot call non-const associated function `::b` in constant functions + --> $DIR/no-const-callers.rs:32:5 + | +LL | u8::b(); + | ^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error[E0015]: cannot call non-const associated function `::b` in constant functions + --> $DIR/no-const-callers.rs:35:5 + | +LL | i8::b(); + | ^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index 0b70ac97fd43..2772d55f953a 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -684,13 +684,6 @@ error[E0015]: cannot call non-const method ` as Iterator>:: LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); | ^^^^^^^^^^^^^^^^^^^^^^ | -note: method `filter` is not const because trait `Iterator` is not const - --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL - | - = note: this trait is not const - ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL - | - = note: this method is not const = note: calls in constants are limited to constant functions, tuple structs and tuple variants error[E0015]: cannot call non-const method `, {closure@$DIR/typeck_type_placeholder_item.rs:240:29: 240:32}> as Iterator>::map::` in constants @@ -699,13 +692,6 @@ error[E0015]: cannot call non-const method `, {closu LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); | ^^^^^^^^^^^^^^ | -note: method `map` is not const because trait `Iterator` is not const - --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL - | - = note: this trait is not const - ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL - | - = note: this method is not const = note: calls in constants are limited to constant functions, tuple structs and tuple variants error: aborting due to 83 previous errors