Skip to content

Commit 5c780b9

Browse files
committed
Auto merge of #96964 - oli-obk:const_trait_mvp, r=compiler-errors
Replace `#[default_method_body_is_const]` with `#[const_trait]` pulled out of #96077 related issues: #67792 and #92158 cc `@fee1-dead` This is groundwork to only allowing `impl const Trait` for traits that are marked with `#[const_trait]`. This is necessary to prevent adding a new default method from becoming a breaking change (as it could be a non-const fn).
2 parents 855fc02 + 2f96fbe commit 5c780b9

32 files changed

+82
-260
lines changed

compiler/rustc_const_eval/src/const_eval/machine.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,8 +277,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
277277
// sensitive check here. But we can at least rule out functions that are not const
278278
// at all.
279279
if !ecx.tcx.is_const_fn_raw(def.did) {
280-
// allow calling functions marked with #[default_method_body_is_const].
281-
if !ecx.tcx.has_attr(def.did, sym::default_method_body_is_const) {
280+
// allow calling functions inside a trait marked with #[const_trait].
281+
if !ecx.tcx.is_const_default_method(def.did) {
282282
// We certainly do *not* want to actually call the fn
283283
// though, so be sure we return here.
284284
throw_unsup_format!("calling non-const function `{}`", instance)

compiler/rustc_const_eval/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Rust MIR: a lowered representation of Rust.
99
#![feature(control_flow_enum)]
1010
#![feature(decl_macro)]
1111
#![feature(exact_size_is_empty)]
12+
#![feature(let_chains)]
1213
#![feature(let_else)]
1314
#![feature(map_try_insert)]
1415
#![feature(min_specialization)]

compiler/rustc_const_eval/src/transform/check_consts/check.rs

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -711,8 +711,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
711711
}
712712
};
713713

714-
let mut nonconst_call_permission = false;
715-
716714
// Attempting to call a trait method?
717715
if let Some(trait_id) = tcx.trait_of_item(callee) {
718716
trace!("attempting to call a trait method");
@@ -774,13 +772,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
774772
}
775773
}
776774
_ if !tcx.is_const_fn_raw(callee) => {
777-
// At this point, it is only legal when the caller is marked with
778-
// #[default_method_body_is_const], and the callee is in the same
779-
// trait.
780-
let callee_trait = tcx.trait_of_item(callee);
781-
if callee_trait.is_some()
782-
&& tcx.has_attr(caller.to_def_id(), sym::default_method_body_is_const)
783-
&& callee_trait == tcx.trait_of_item(caller)
775+
// At this point, it is only legal when the caller is in a trait
776+
// marked with #[const_trait], and the callee is in the same trait.
777+
let mut nonconst_call_permission = false;
778+
if let Some(callee_trait) = tcx.trait_of_item(callee)
779+
&& tcx.has_attr(callee_trait, sym::const_trait)
780+
&& Some(callee_trait) == tcx.trait_of_item(caller)
784781
// Can only call methods when it's `<Self as TheTrait>::f`.
785782
&& tcx.types.self_param == substs.type_at(0)
786783
{
@@ -874,16 +871,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
874871
let is_intrinsic = tcx.is_intrinsic(callee);
875872

876873
if !tcx.is_const_fn_raw(callee) {
877-
if tcx.trait_of_item(callee).is_some() {
878-
if tcx.has_attr(callee, sym::default_method_body_is_const) {
879-
// To get to here we must have already found a const impl for the
880-
// trait, but for it to still be non-const can be that the impl is
881-
// using default method bodies.
882-
nonconst_call_permission = true;
883-
}
884-
}
885-
886-
if !nonconst_call_permission {
874+
if !tcx.is_const_default_method(callee) {
875+
// To get to here we must have already found a const impl for the
876+
// trait, but for it to still be non-const can be that the impl is
877+
// using default method bodies.
887878
self.check_op(ops::FnCallNonConst {
888879
caller,
889880
callee,

compiler/rustc_const_eval/src/transform/check_consts/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_hir as hir;
99
use rustc_hir::def_id::{DefId, LocalDefId};
1010
use rustc_middle::mir;
1111
use rustc_middle::ty::{self, TyCtxt};
12-
use rustc_span::{sym, Symbol};
12+
use rustc_span::Symbol;
1313

1414
pub use self::qualifs::Qualif;
1515

@@ -84,10 +84,10 @@ pub fn rustc_allow_const_fn_unstable(
8484
// functions are subject to more stringent restrictions than "const-unstable" functions: They
8585
// cannot use unstable features and can only call other "const-stable" functions.
8686
pub fn is_const_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
87-
// A default body marked const is not const-stable because const
87+
// A default body in a `#[const_trait]` is not const-stable because const
8888
// trait fns currently cannot be const-stable. We shouldn't
8989
// restrict default bodies to only call const-stable functions.
90-
if tcx.has_attr(def_id, sym::default_method_body_is_const) {
90+
if tcx.is_const_default_method(def_id) {
9191
return false;
9292
}
9393

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -473,9 +473,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
473473
),
474474
// RFC 2632
475475
gated!(
476-
default_method_body_is_const, Normal, template!(Word), WarnFollowing, const_trait_impl,
477-
"`default_method_body_is_const` is a temporary placeholder for declaring default bodies \
478-
as `const`, which may be removed or renamed in the future."
476+
const_trait, Normal, template!(Word), WarnFollowing, const_trait_impl,
477+
"`const` is a temporary placeholder for marking a trait that is suitable for `const` \
478+
`impls` and all default bodies as `const`, which may be removed or renamed in the \
479+
future."
479480
),
480481
// lang-team MCP 147
481482
gated!(

compiler/rustc_hir/src/def.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ pub enum DefKind {
9292
/// [RFC 2593]: https://github.com/rust-lang/rfcs/pull/2593
9393
Ctor(CtorOf, CtorKind),
9494
/// Associated function: `impl MyStruct { fn associated() {} }`
95+
/// or `trait Foo { fn associated() {} }`
9596
AssocFn,
9697
/// Associated constant: `trait MyTrait { const ASSOC: usize; }`
9798
AssocConst,

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -893,9 +893,9 @@ fn should_encode_mir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> (bool, bool) {
893893
let needs_inline = (generics.requires_monomorphization(tcx)
894894
|| tcx.codegen_fn_attrs(def_id).requests_inline())
895895
&& tcx.sess.opts.output_types.should_codegen();
896-
// The function has a `const` modifier or is annotated with `default_method_body_is_const`.
896+
// The function has a `const` modifier or is in a `#[const_trait]`.
897897
let is_const_fn = tcx.is_const_fn_raw(def_id.to_def_id())
898-
|| tcx.has_attr(def_id.to_def_id(), sym::default_method_body_is_const);
898+
|| tcx.is_const_default_method(def_id.to_def_id());
899899
let always_encode_mir = tcx.sess.opts.debugging_opts.always_encode_mir;
900900
(is_const_fn, needs_inline || always_encode_mir)
901901
}

compiler/rustc_middle/src/hir/map/mod.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -494,9 +494,7 @@ impl<'hir> Map<'hir> {
494494
BodyOwnerKind::Fn if self.tcx.is_const_fn_raw(def_id.to_def_id()) => {
495495
ConstContext::ConstFn
496496
}
497-
BodyOwnerKind::Fn
498-
if self.tcx.has_attr(def_id.to_def_id(), sym::default_method_body_is_const) =>
499-
{
497+
BodyOwnerKind::Fn if self.tcx.is_const_default_method(def_id.to_def_id()) => {
500498
ConstContext::ConstFn
501499
}
502500
BodyOwnerKind::Fn | BodyOwnerKind::Closure => return None,

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2303,6 +2303,11 @@ impl<'tcx> TyCtxt<'tcx> {
23032303
matches!(self.def_kind(def_id), DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..))
23042304
&& self.impl_constness(def_id) == hir::Constness::Const
23052305
}
2306+
2307+
#[inline]
2308+
pub fn is_const_default_method(self, def_id: DefId) -> bool {
2309+
matches!(self.trait_of_item(def_id), Some(trait_id) if self.has_attr(trait_id, sym::const_trait))
2310+
}
23062311
}
23072312

23082313
/// Yields the parent function's `LocalDefId` if `def_id` is an `impl Trait` definition.

compiler/rustc_passes/src/check_attr.rs

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,7 @@ impl CheckAttrVisitor<'_> {
122122
| sym::rustc_if_this_changed
123123
| sym::rustc_then_this_would_need => self.check_rustc_dirty_clean(&attr),
124124
sym::cmse_nonsecure_entry => self.check_cmse_nonsecure_entry(attr, span, target),
125-
sym::default_method_body_is_const => {
126-
self.check_default_method_body_is_const(attr, span, target)
127-
}
125+
sym::const_trait => self.check_const_trait(attr, span, target),
128126
sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target),
129127
sym::must_use => self.check_must_use(hir_id, &attr, span, target),
130128
sym::rustc_pass_by_value => self.check_pass_by_value(&attr, span, target),
@@ -2097,23 +2095,14 @@ impl CheckAttrVisitor<'_> {
20972095
}
20982096
}
20992097

2100-
/// default_method_body_is_const should only be applied to trait methods with default bodies.
2101-
fn check_default_method_body_is_const(
2102-
&self,
2103-
attr: &Attribute,
2104-
span: Span,
2105-
target: Target,
2106-
) -> bool {
2098+
/// `#[const_trait]` only applies to traits.
2099+
fn check_const_trait(&self, attr: &Attribute, _span: Span, target: Target) -> bool {
21072100
match target {
2108-
Target::Method(MethodKind::Trait { body: true }) => true,
2101+
Target::Trait => true,
21092102
_ => {
21102103
self.tcx
21112104
.sess
2112-
.struct_span_err(
2113-
attr.span,
2114-
"attribute should be applied to a trait method with body",
2115-
)
2116-
.span_label(span, "not a trait method or missing a body")
2105+
.struct_span_err(attr.span, "attribute should be applied to a trait")
21172106
.emit();
21182107
false
21192108
}
@@ -2207,6 +2196,8 @@ impl CheckAttrVisitor<'_> {
22072196
"attribute `{}` without any lints has no effect",
22082197
attr.name_or_empty()
22092198
)
2199+
} else if attr.name_or_empty() == sym::default_method_body_is_const {
2200+
format!("`default_method_body_is_const` has been replaced with `#[const_trait]` on traits")
22102201
} else {
22112202
return;
22122203
};

0 commit comments

Comments
 (0)