From 4598ecf82611511a00c43bdd6eaebbf2a0f917d2 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 16 Jun 2026 21:53:46 +0200 Subject: [PATCH 1/5] Use `DefKind::is_fn_like` instead of hand-rolling it --- compiler/rustc_hir/src/def.rs | 6 +++++- compiler/rustc_metadata/src/rmeta/decoder.rs | 1 - .../src/rmeta/decoder/cstore_impl.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_metadata/src/rmeta/mod.rs | 2 +- compiler/rustc_middle/src/hir/mod.rs | 10 +++++++++- compiler/rustc_middle/src/mir/pretty.rs | 7 +------ compiler/rustc_symbol_mangling/src/lib.rs | 17 +++++------------ .../issue-109768.stderr | 4 ++-- .../cast/ice-cast-type-with-error-124848.stderr | 4 ++-- .../ui/try-block/try-block-bad-lifetime.stderr | 5 +++++ 11 files changed, 32 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 1481cb0726082..c1b24af9fe7f5 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -366,7 +366,11 @@ impl DefKind { pub fn is_fn_like(self) -> bool { matches!( self, - DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::SyntheticCoroutineBody + DefKind::Fn + | DefKind::AssocFn + | DefKind::Closure + | DefKind::SyntheticCoroutineBody + | DefKind::Ctor(..) ) } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 560d39403d4e0..93a93373c1664 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1366,7 +1366,6 @@ impl CrateMetadata { .tables .fn_arg_idents .get(self, id) - .expect("argument names not encoded for a function") .decode((self, tcx)) .nth(0) .is_some_and(|ident| matches!(ident, Some(Ident { name: kw::SelfLower, .. }))) diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 9acebc1a4822f..5c2bba6ed9901 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -277,7 +277,7 @@ provide! { tcx, def_id, other, cdata, rendered_const => { table } rendered_precise_capturing_args => { table } asyncness => { table_direct } - fn_arg_idents => { table } + fn_arg_idents => { table_defaulted_array } coroutine_kind => { table_direct } coroutine_for_closure => { table } coroutine_by_move_body_def_id => { table } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 602c5ee0201dd..61bb6f2a77b1b 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1505,7 +1505,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if let DefKind::Fn | DefKind::AssocFn = def_kind { let asyncness = tcx.asyncness(def_id); self.tables.asyncness.set(def_id.index, asyncness); - record_array!(self.tables.fn_arg_idents[def_id] <- tcx.fn_arg_idents(def_id)); + record_defaulted_array!(self.tables.fn_arg_idents[def_id] <- tcx.fn_arg_idents(def_id)); } if let Some(name) = tcx.intrinsic(def_id) { record!(self.tables.intrinsic[def_id] <- name); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 237672878bb4c..7b87be6099e91 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -413,6 +413,7 @@ define_tables! { constness: Table, safety: Table, defaultness: Table, + fn_arg_idents: Table>>, impl_is_fully_generic_for_reflection: Table, - optional: @@ -452,7 +453,6 @@ define_tables! { mir_const_qualif: Table>, rendered_const: Table>, rendered_precise_capturing_args: Table>>, - fn_arg_idents: Table>>, coroutine_kind: Table, coroutine_for_closure: Table, adt_destructor: Table>, diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 13bda2991fa92..2c535cad131b6 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -16,7 +16,7 @@ use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap, LocalModId}; use rustc_hir::lints::DelayedLints; use rustc_hir::*; use rustc_macros::{Decodable, Encodable, StableHash}; -use rustc_span::{ErrorGuaranteed, ExpnId, Span}; +use rustc_span::{ErrorGuaranteed, ExpnId, Ident, Span}; use crate::query::Providers; use crate::ty::TyCtxt; @@ -483,6 +483,14 @@ pub fn provide(providers: &mut Providers) { }) = node { idents + } else if let Node::Ctor(VariantData::Tuple(fields, _, _)) = node { + tcx.arena.alloc_from_iter(fields.iter().map(|field| { + Some(if field.ident.is_numeric() { + Ident::from_str_and_span(&format!("arg{}", field.ident), field.ident.span) + } else { + field.ident + }) + })) } else { span_bug!( tcx.hir_span(tcx.local_def_id_to_hir_id(def_id)), diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 021c1c176d788..4649427caaf43 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -677,12 +677,7 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn io::Write) -> io: trace!("write_mir_sig: {:?}", body.source.instance); let def_id = body.source.def_id(); let kind = tcx.def_kind(def_id); - let is_function = match kind { - DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) | DefKind::SyntheticCoroutineBody => { - true - } - _ => tcx.is_closure_like(def_id), - }; + let is_function = kind.is_fn_like(); match (kind, body.source.promoted) { (_, Some(_)) => write!(w, "const ")?, // promoteds are the closest to consts (DefKind::Const { .. } | DefKind::AssocConst { .. }, _) => write!(w, "const ")?, diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 482848578a81b..505193352488f 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -88,7 +88,6 @@ //! DefPaths which are much more robust in the face of changes to the code base. use rustc_hir as hir; -use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mono::{InstantiationMode, MonoItem}; @@ -258,17 +257,11 @@ fn compute_symbol_name<'tcx>( // codegen units) then this symbol may become an exported (but hidden // visibility) symbol. This means that multiple crates may do the same // and we want to be sure to avoid any symbol conflicts here. - let is_globally_shared_function = matches!( - def_kind, - DefKind::Fn - | DefKind::AssocFn - | DefKind::Closure - | DefKind::SyntheticCoroutineBody - | DefKind::Ctor(..) - ) && matches!( - MonoItem::Fn(instance).instantiation_mode(tcx), - InstantiationMode::GloballyShared { may_conflict: true } - ); + let is_globally_shared_function = def_kind.is_fn_like() + && matches!( + MonoItem::Fn(instance).instantiation_mode(tcx), + InstantiationMode::GloballyShared { may_conflict: true } + ); // If this is an instance of a generic function, we also hash in // the ID of the instantiating crate. This avoids symbol conflicts diff --git a/tests/ui/associated-inherent-types/issue-109768.stderr b/tests/ui/associated-inherent-types/issue-109768.stderr index 59f8526a73e59..bf8ce8e1dab16 100644 --- a/tests/ui/associated-inherent-types/issue-109768.stderr +++ b/tests/ui/associated-inherent-types/issue-109768.stderr @@ -43,8 +43,8 @@ LL | struct Wrapper(T); | ^^^^^^^ help: provide the argument | -LL | const WRAPPED_ASSOC_3: Wrapper = Wrapper(/* value */); - | +++++++++++ +LL | const WRAPPED_ASSOC_3: Wrapper = Wrapper(/* arg0 */); + | ++++++++++ error: aborting due to 4 previous errors diff --git a/tests/ui/cast/ice-cast-type-with-error-124848.stderr b/tests/ui/cast/ice-cast-type-with-error-124848.stderr index 665b0e0a0dd49..bf3b7845ba802 100644 --- a/tests/ui/cast/ice-cast-type-with-error-124848.stderr +++ b/tests/ui/cast/ice-cast-type-with-error-124848.stderr @@ -55,8 +55,8 @@ LL | struct MyType<'a>(Cell>>, Pin); | ^^^^^^ help: provide the argument | -LL | let mut unpinned = MyType(Cell::new(None), /* value */); - | +++++++++++++ +LL | let mut unpinned = MyType(Cell::new(None), /* arg1 */); + | ++++++++++++ error: aborting due to 5 previous errors diff --git a/tests/ui/try-block/try-block-bad-lifetime.stderr b/tests/ui/try-block/try-block-bad-lifetime.stderr index 28941cb0a9e40..ab733b327a523 100644 --- a/tests/ui/try-block/try-block-bad-lifetime.stderr +++ b/tests/ui/try-block/try-block-bad-lifetime.stderr @@ -34,6 +34,11 @@ LL | Err(k) ?; ... LL | ::std::mem::drop(k); | ^ value used here after move + | +help: consider creating a fresh reborrow of `k` here + | +LL | Err(&mut *k) ?; + | ++++++ error[E0506]: cannot assign to `i` because it is borrowed --> $DIR/try-block-bad-lifetime.rs:32:9 From 318e89dfd6c1e731cc2e54d3d5e890ae4178a22c Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 17 Jun 2026 13:20:18 +0200 Subject: [PATCH 2/5] Add an `ast::Const` variant for encoding comptime at the ast level --- compiler/rustc_ast/src/ast.rs | 1 + compiler/rustc_ast_lowering/src/item.rs | 1 + compiler/rustc_ast_passes/src/ast_validation.rs | 1 + compiler/rustc_ast_pretty/src/pprust/state.rs | 2 ++ compiler/rustc_parse/src/parser/item.rs | 3 +++ src/tools/rustfmt/src/utils.rs | 2 ++ 6 files changed, 10 insertions(+) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 71777e0117ab8..b4de44585da82 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3154,6 +3154,7 @@ impl CoroutineKind { #[derive(Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable, Debug)] #[derive(StableHash, Walkable)] pub enum Const { + Always(Span), Yes(Span), No, } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 34c7137b8676d..1a62b1d2af077 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1770,6 +1770,7 @@ impl<'hir> LoweringContext<'_, 'hir> { /// Whether `comptime` is allowed here is checked by the `comptime` attribute parser. pub(super) fn lower_constness(&mut self, attrs: &[hir::Attribute], c: Const) -> hir::Constness { let mut constness = match c { + Const::Always(_) => hir::Constness::Const { always: true }, Const::Yes(_) => hir::Constness::Const { always: false }, Const::No => hir::Constness::NotConst, }; diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 0e47424ba1aa4..9f10598c57d9a 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -874,6 +874,7 @@ impl<'a> AstValidator<'a> { None => (), } match constness { + Const::Always(span) => report_err(span, "rustc_comptime"), Const::Yes(span) => report_err(span, "const"), Const::No => (), } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 3b0c90264e32d..220732948c029 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -2319,6 +2319,8 @@ impl<'a> State<'a> { match s { ast::Const::No => {} ast::Const::Yes(_) => self.word_nbsp("const"), + // Can only be set via an attribute, which we'll also print + ast::Const::Always(_) => {} } } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 1b06c80f83687..2ed79bc33b563 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -3169,6 +3169,9 @@ impl<'a> Parser<'a> { // that the keyword is already present and the second instance should be removed. let wrong_kw = if self.check_keyword(exp!(Const)) { match constness { + Const::Always(_) => { + unreachable!("can only be set from the rustc_comptime builtin attr") + } Const::Yes(sp) => Some(WrongKw::Duplicated(sp)), Const::No => { recover_constness = Const::Yes(self.token.span); diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs index 131455fc0ff12..a14984d30254d 100644 --- a/src/tools/rustfmt/src/utils.rs +++ b/src/tools/rustfmt/src/utils.rs @@ -130,6 +130,8 @@ pub(crate) fn format_constness(constness: ast::Const) -> &'static str { match constness { ast::Const::Yes(..) => "const ", ast::Const::No => "", + // FIXME(comptime): need actual syntax + ast::Const::Always(_) => "", } } From 8f40a88ef5138b94ffe0088d937d8f9e35897b26 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 17 Jun 2026 13:18:15 +0200 Subject: [PATCH 3/5] Make `rustc_comptime` a bultin attribute and handle it during parsing instead of ast lowering --- compiler/rustc_ast/src/ast.rs | 10 ++ .../rustc_ast_lowering/src/diagnostics.rs | 11 -- .../rustc_ast_lowering/src/expr/closure.rs | 6 +- compiler/rustc_ast_lowering/src/item.rs | 29 +---- .../rustc_ast_passes/src/ast_validation.rs | 5 +- compiler/rustc_ast_passes/src/diagnostics.rs | 17 +-- .../src/attributes/semantics.rs | 13 --- compiler/rustc_attr_parsing/src/context.rs | 3 +- compiler/rustc_builtin_macros/src/comptime.rs | 48 ++++++++ compiler/rustc_builtin_macros/src/lib.rs | 2 + compiler/rustc_feature/src/builtin_attrs.rs | 1 - .../rustc_hir/src/attrs/data_structures.rs | 3 - .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 - compiler/rustc_hir_analysis/src/collect.rs | 1 + .../rustc_hir_analysis/src/diagnostics.rs | 3 +- compiler/rustc_parse/src/parser/item.rs | 2 +- compiler/rustc_passes/src/check_attr.rs | 1 - compiler/rustc_span/src/symbol.rs | 2 +- compiler/rustc_symbol_mangling/src/lib.rs | 1 + library/core/src/any.rs | 4 +- library/core/src/intrinsics/mod.rs | 38 ++++--- library/core/src/lib.rs | 1 + library/core/src/macros/mod.rs | 13 +++ library/core/src/mem/type_info.rs | 12 +- library/core/src/prelude/v1.rs | 7 ++ library/std/src/prelude/v1.rs | 7 ++ tests/ui/comptime/comptime_closure.rs | 6 +- tests/ui/comptime/comptime_closure.stderr | 10 +- tests/ui/comptime/comptime_impl.rs | 9 +- tests/ui/comptime/comptime_impl.stderr | 14 +-- tests/ui/comptime/comptime_method.rs | 4 +- tests/ui/comptime/comptime_method_bounds.rs | 4 +- tests/ui/comptime/comptime_trait.rs | 23 ++-- tests/ui/comptime/comptime_trait.stderr | 105 +++++++++++++++--- tests/ui/comptime/const_comptime.rs | 4 +- tests/ui/comptime/const_comptime.stderr | 8 -- tests/ui/comptime/feature-gate-test.rs | 4 +- tests/ui/comptime/feature-gate-test.stderr | 11 +- tests/ui/comptime/link-dead-code.rs | 4 +- tests/ui/comptime/not_callable.rs | 6 +- tests/ui/comptime/trait_bounds.rs | 8 +- tests/ui/comptime/trait_comptime.rs | 16 +-- tests/ui/comptime/trait_comptime.stderr | 46 +++++--- 43 files changed, 319 insertions(+), 204 deletions(-) create mode 100644 compiler/rustc_builtin_macros/src/comptime.rs diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index b4de44585da82..38cac98d244a4 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3159,6 +3159,16 @@ pub enum Const { No, } +impl Const { + pub fn descr(&self) -> &'static str { + match self { + Const::Always(_) => "#[comptime]", + Const::Yes(_) => "const", + Const::No => "", + } + } +} + /// Item defaultness. /// For details see the [RFC #2532](https://github.com/rust-lang/rfcs/pull/2532). #[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, StableHash, Walkable)] diff --git a/compiler/rustc_ast_lowering/src/diagnostics.rs b/compiler/rustc_ast_lowering/src/diagnostics.rs index 2fbf8fac4c64e..d4b61b489a17d 100644 --- a/compiler/rustc_ast_lowering/src/diagnostics.rs +++ b/compiler/rustc_ast_lowering/src/diagnostics.rs @@ -122,17 +122,6 @@ pub(crate) struct AwaitOnlyInAsyncFnAndBlocks { pub item_span: Option, } -#[derive(Diagnostic)] -#[diag("a function cannot be both `comptime` and `const`")] -pub(crate) struct ConstComptimeFn { - #[primary_span] - #[suggestion("remove the `const`", applicability = "machine-applicable", code = "")] - #[note("`const` implies the function can be called at runtime, too")] - pub span: Span, - #[label("`comptime` because of this")] - pub attr_span: Span, -} - #[derive(Diagnostic)] #[diag("too many parameters for a coroutine (expected 0 or 1 parameters)", code = E0628)] pub(crate) struct CoroutineTooManyParameters { diff --git a/compiler/rustc_ast_lowering/src/expr/closure.rs b/compiler/rustc_ast_lowering/src/expr/closure.rs index 32e2e5d40d132..cc2c6ae2879c1 100644 --- a/compiler/rustc_ast_lowering/src/expr/closure.rs +++ b/compiler/rustc_ast_lowering/src/expr/closure.rs @@ -38,7 +38,6 @@ impl<'hir> LoweringContext<'_, 'hir> { &closure.body, closure.fn_decl_span, closure.fn_arg_span, - attrs, ), span: self.lower_span(e.span), }, @@ -241,7 +240,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn_decl_span: self.lower_span(fn_decl_span), fn_arg_span: Some(self.lower_span(fn_arg_span)), kind: closure_kind, - constness: self.lower_constness(attrs, constness), + constness: self.lower_constness(constness), explicit_captures, }); @@ -309,7 +308,6 @@ impl<'hir> LoweringContext<'_, 'hir> { body: &Expr, fn_decl_span: Span, fn_arg_span: Span, - attrs: &[hir::Attribute], ) -> hir::ExprKind<'hir> { let closure_def_id = self.local_def_id(closure_id); let (binder_clause, generic_params) = self.lower_closure_binder(binder); @@ -371,7 +369,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // knows that a `FnDecl` output type like `-> &str` actually means // "coroutine that returns &str", rather than directly returning a `&str`. kind: hir::ClosureKind::CoroutineClosure(coroutine_desugaring), - constness: self.lower_constness(attrs, constness), + constness: self.lower_constness(constness), explicit_captures: &[], }); hir::ExprKind::Closure(c) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 1a62b1d2af077..c30fca168bffe 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -26,7 +26,6 @@ use super::{ FnDeclKind, GenericArgsMode, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode, RelaxedBoundForbiddenReason, RelaxedBoundPolicy, }; -use crate::diagnostics::ConstComptimeFn; pub(super) struct ItemLowerer<'a, 'hir> { pub(super) tcx: TyCtxt<'hir>, @@ -479,7 +478,7 @@ impl<'hir> LoweringContext<'_, 'hir> { .arena .alloc_from_iter(impl_items.iter().map(|item| self.lower_impl_item_ref(item))); - let constness = self.lower_constness(attrs, *constness); + let constness = self.lower_constness(*constness); hir::ItemKind::Impl(hir::Impl { generics, @@ -499,7 +498,7 @@ impl<'hir> LoweringContext<'_, 'hir> { bounds, items, }) => { - let constness = self.lower_constness(attrs, *constness); + let constness = self.lower_constness(*constness); let impl_restriction = self.lower_impl_restriction(impl_restriction); let ident = self.lower_ident(*ident); let (generics, (safety, items, bounds)) = self.lower_generics( @@ -530,7 +529,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } } ItemKind::TraitAlias(TraitAlias { constness, ident, generics, bounds }) => { - let constness = self.lower_constness(attrs, *constness); + let constness = self.lower_constness(*constness); let ident = self.lower_ident(*ident); let (generics, bounds) = self.lower_generics( generics, @@ -1703,7 +1702,7 @@ impl<'hir> LoweringContext<'_, 'hir> { safety.into() }; - let constness = self.lower_constness(attrs, h.constness); + let constness = self.lower_constness(h.constness); hir::FnHeader { safety, asyncness, constness, abi: self.lower_extern(h.ext) } } @@ -1768,28 +1767,12 @@ impl<'hir> LoweringContext<'_, 'hir> { /// Lowers constness or comptime attribute. /// Whether `const` is allowed here is checked by ast validation. /// Whether `comptime` is allowed here is checked by the `comptime` attribute parser. - pub(super) fn lower_constness(&mut self, attrs: &[hir::Attribute], c: Const) -> hir::Constness { - let mut constness = match c { + pub(super) fn lower_constness(&mut self, c: Const) -> hir::Constness { + match c { Const::Always(_) => hir::Constness::Const { always: true }, Const::Yes(_) => hir::Constness::Const { always: false }, Const::No => hir::Constness::NotConst, - }; - - if let Some(&attr_span) = find_attr!(attrs, RustcComptime(span) => span) { - match std::mem::replace(&mut constness, hir::Constness::Const { always: true }) { - hir::Constness::Const { always: true } => { - unreachable!("lower_constness cannot produce comptime") - } - // A function can't be `const` and `comptime` at the same time - hir::Constness::Const { always: false } => { - let Const::Yes(span) = c else { unreachable!() }; - self.dcx().emit_err(ConstComptimeFn { span, attr_span }); - } - // Good - hir::Constness::NotConst => {} - } } - constness } pub(super) fn lower_safety(&self, s: Safety, default: hir::Safety) -> hir::Safety { diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 9f10598c57d9a..524bd9a0bc548 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -318,7 +318,7 @@ impl<'a> AstValidator<'a> { } fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrImpl) { - let Const::Yes(span) = constness else { + let (Const::Yes(span) | Const::Always(span)) = constness else { return; }; @@ -362,6 +362,7 @@ impl<'a> AstValidator<'a> { || make_trait_const_sugg.is_some(), make_impl_const_sugg, make_trait_const_sugg, + constness: constness.descr(), }); } @@ -874,7 +875,7 @@ impl<'a> AstValidator<'a> { None => (), } match constness { - Const::Always(span) => report_err(span, "rustc_comptime"), + Const::Always(span) => report_err(span, "comptime"), Const::Yes(span) => report_err(span, "const"), Const::No => (), } diff --git a/compiler/rustc_ast_passes/src/diagnostics.rs b/compiler/rustc_ast_passes/src/diagnostics.rs index af22ead1332d1..8a3544cc76452 100644 --- a/compiler/rustc_ast_passes/src/diagnostics.rs +++ b/compiler/rustc_ast_passes/src/diagnostics.rs @@ -42,21 +42,21 @@ pub(crate) struct ImplFnConst { #[diag("functions in {$in_impl -> [true] trait impls *[false] traits - } cannot be declared const", code = E0379)] + } cannot be declared {$constness}", code = E0379)] pub(crate) struct TraitFnConst { #[primary_span] #[label( "functions in {$in_impl -> [true] trait impls *[false] traits - } cannot be const" + } cannot be {$constness}" )] pub span: Span, pub in_impl: bool, - #[label("this declares all associated functions implicitly const")] + #[label("this declares all associated functions implicitly {$constness}")] pub const_context_label: Option, #[suggestion( - "remove the `const`{$requires_multiple_changes -> + "remove the `{$constness}`{$requires_multiple_changes -> [true] {\" ...\"} *[false] {\"\"} }", @@ -65,17 +65,18 @@ pub(crate) struct TraitFnConst { pub remove_const_sugg: (Span, Applicability), pub requires_multiple_changes: bool, #[suggestion( - "... and declare the impl to be const instead", - code = "const ", + "... and declare the impl to be {$constness} instead", + code = "{constness} ", applicability = "maybe-incorrect" )] pub make_impl_const_sugg: Option, #[suggestion( - "... and declare the trait to be const instead", - code = "const ", + "... and declare the trait to be {$constness} instead", + code = "{constness} ", applicability = "maybe-incorrect" )] pub make_trait_const_sugg: Option, + pub constness: &'static str, } #[derive(Diagnostic)] diff --git a/compiler/rustc_attr_parsing/src/attributes/semantics.rs b/compiler/rustc_attr_parsing/src/attributes/semantics.rs index fa19d51c397eb..717ecba65c915 100644 --- a/compiler/rustc_attr_parsing/src/attributes/semantics.rs +++ b/compiler/rustc_attr_parsing/src/attributes/semantics.rs @@ -15,16 +15,3 @@ impl NoArgsAttributeParser for MayDangleParser { const STABILITY: AttributeStability = unstable!(dropck_eyepatch); const CREATE: fn(span: Span) -> AttributeKind = AttributeKind::MayDangle; } - -pub(crate) struct ComptimeParser; -impl NoArgsAttributeParser for ComptimeParser { - const PATH: &[Symbol] = &[sym::rustc_comptime]; - const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; - const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ - Allow(Target::Method(MethodKind::Inherent)), - Allow(Target::Fn), - Allow(Target::Impl { of_trait: false }), - ]); - const STABILITY: AttributeStability = unstable!(rustc_attrs); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcComptime; -} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 81911c1b2f335..1567c85be5b0a 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -58,7 +58,7 @@ use crate::attributes::repr::*; use crate::attributes::rustc_allocator::*; use crate::attributes::rustc_dump::*; use crate::attributes::rustc_internal::*; -use crate::attributes::semantics::{ComptimeParser, *}; +use crate::attributes::semantics::*; use crate::attributes::splat::*; use crate::attributes::stability::*; use crate::attributes::test_attrs::*; @@ -263,7 +263,6 @@ attribute_parsers!( Single>, Single>, Single>, - Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_builtin_macros/src/comptime.rs b/compiler/rustc_builtin_macros/src/comptime.rs new file mode 100644 index 0000000000000..243984e846e62 --- /dev/null +++ b/compiler/rustc_builtin_macros/src/comptime.rs @@ -0,0 +1,48 @@ +use rustc_ast::ast; +use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_span::Span; + +pub(crate) fn expand( + ecx: &mut ExtCtxt<'_>, + _expand_span: Span, + meta_item: &ast::MetaItem, + mut item: Annotatable, +) -> Vec { + let constness = match &mut item { + Annotatable::Item(p) => match &mut p.kind { + ast::ItemKind::Fn(f) => Some(&mut f.sig.header.constness), + ast::ItemKind::Impl(i) => Some(&mut i.constness), + _ => None, + }, + Annotatable::AssocItem(i, _assoc_ctxt) => match &mut i.kind { + ast::AssocItemKind::Fn(func) => Some(&mut func.sig.header.constness), + _ => None, + }, + Annotatable::Stmt(s) => match &mut s.kind { + ast::StmtKind::Item(p) => match &mut p.kind { + ast::ItemKind::Fn(f) => Some(&mut f.sig.header.constness), + ast::ItemKind::Impl(i) => Some(&mut i.constness), + _ => None, + }, + _ => None, + }, + _ => None, + }; + + let ast::MetaItemKind::Word = meta_item.kind else { + ecx.dcx().span_err(meta_item.span, "comptime does not take any arguments"); + return vec![item]; + }; + + if let Some(constness) = constness { + if let ast::Const::Yes(span) = *constness { + ecx.dcx().span_err(span, "a function cannot be both `comptime` and `const`"); + } + *constness = ast::Const::Always(meta_item.span); + } else { + ecx.dcx() + .span_err(meta_item.span, "only functions, trait impls, and methods may be comptime"); + } + + vec![item] +} diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 78bf7d97bd7b8..ff848a4d2c50c 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -28,6 +28,7 @@ mod cfg_accessible; mod cfg_eval; mod cfg_select; mod compile_error; +mod comptime; mod concat; mod concat_bytes; mod define_opaque; @@ -114,6 +115,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { bench: test::expand_bench, cfg_accessible: cfg_accessible::Expander, cfg_eval: cfg_eval::expand, + comptime: comptime::expand, define_opaque: define_opaque::expand, derive: derive::Expander { is_const: false }, derive_const: derive::Expander { is_const: true }, diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index c7e9a939f2ba1..a2c993319ea26 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -346,7 +346,6 @@ pub static BUILTIN_ATTRIBUTES: &[Symbol] = &[ sym::rustc_no_implicit_autorefs, sym::rustc_coherence_is_core, sym::rustc_coinductive, - sym::rustc_comptime, sym::rustc_allow_incoherent_impl, sym::rustc_preserve_ub_checks, sym::rustc_deny_explicit_impl, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index bb0d7227bd171..f034cf75319f7 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1379,9 +1379,6 @@ pub enum AttributeKind { /// Represents `#[rustc_coinductive]`. RustcCoinductive, - /// Represents `#[rustc_comptime]` - RustcComptime(Span), - /// Represents `#[rustc_confusables]`. RustcConfusables { confusables: ThinVec, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 1e634513fdce2..c2456dae1f8fb 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -116,7 +116,6 @@ impl AttributeKind { RustcClean { .. } => No, RustcCoherenceIsCore => No, RustcCoinductive => No, - RustcComptime(..) => No, // Encoded directly in signature RustcConfusables { .. } => Yes, RustcConstStability { .. } => Yes, RustcConstStableIndirect => No, diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 6c393ed3dfc6b..cdf84be5eac46 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1459,6 +1459,7 @@ fn check_impl_constness( suggestion_pre, marking: (), adding: (), + constness: constness.to_string(), }); } diff --git a/compiler/rustc_hir_analysis/src/diagnostics.rs b/compiler/rustc_hir_analysis/src/diagnostics.rs index 0ea353cf14cee..6392963119652 100644 --- a/compiler/rustc_hir_analysis/src/diagnostics.rs +++ b/compiler/rustc_hir_analysis/src/diagnostics.rs @@ -596,12 +596,13 @@ pub(crate) struct GenericArgsOnOverriddenImpl { } #[derive(Diagnostic)] -#[diag("const `impl` for trait `{$trait_name}` which is not `const`")] +#[diag("{$constness} `impl` for trait `{$trait_name}` which is not `const`")] pub(crate) struct ConstImplForNonConstTrait { #[primary_span] #[label("this trait is not `const`")] pub trait_ref_span: Span, pub trait_name: String, + pub constness: String, #[suggestion( "{$suggestion_pre}mark `{$trait_name}` as `const` to allow it to have `const` implementations", applicability = "machine-applicable", diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 2ed79bc33b563..a9220dacafe1e 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -3170,7 +3170,7 @@ impl<'a> Parser<'a> { let wrong_kw = if self.check_keyword(exp!(Const)) { match constness { Const::Always(_) => { - unreachable!("can only be set from the rustc_comptime builtin attr") + unreachable!("can only be set from the comptime builtin attr") } Const::Yes(sp) => Some(WrongKw::Duplicated(sp)), Const::No => { diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 6115811b18af6..a87674f2b1e3d 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -319,7 +319,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { AttributeKind::RustcClean(..) => (), AttributeKind::RustcCoherenceIsCore => (), AttributeKind::RustcCoinductive => (), - AttributeKind::RustcComptime(_) => (), AttributeKind::RustcConfusables { .. } => (), AttributeKind::RustcConstStability { .. } => (), AttributeKind::RustcConstStableIndirect => (), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index c874c1af265f8..3df7d7cf83c5f 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -652,6 +652,7 @@ symbols! { compiler_copy, compiler_fence, compiler_move, + comptime, concat, concat_bytes, conservative_impl_trait, @@ -1768,7 +1769,6 @@ symbols! { rustc_clean, rustc_coherence_is_core, rustc_coinductive, - rustc_comptime, rustc_confusables, rustc_const_stable, rustc_const_stable_indirect, diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 505193352488f..0c2d185688540 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -88,6 +88,7 @@ //! DefPaths which are much more robust in the face of changes to the code base. use rustc_hir as hir; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mono::{InstantiationMode, MonoItem}; diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 85ff2fe1dd6ee..e70468d80b127 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -785,7 +785,7 @@ impl TypeId { /// ``` #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] - #[rustc_comptime] + #[comptime] pub fn trait_info_of<'a, T: TryAsDynCompatible<'a> + ?Sized>(self) -> Option> { // SAFETY: The vtable was obtained for `T`, so it is guaranteed to be `DynMetadata`. // The intrinsic can't infer this because it is designed to work with arbitrary TypeIds. @@ -809,7 +809,7 @@ impl TypeId { /// ``` #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] - #[rustc_comptime] + #[comptime] pub fn trait_info_of_trait_type_id( self, trait_represented_by_type_id: TypeId, diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 7210d850c864a..148ab500a563f 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -873,7 +873,7 @@ pub const unsafe fn transmute_unchecked(src: Src) -> Dst; #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] -#[rustc_comptime] +#[comptime] pub fn needs_drop() -> bool; /// Calculates the offset from a pointer. @@ -2946,7 +2946,7 @@ pub unsafe fn vtable_align(ptr: *const ()) -> usize; #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] -#[rustc_comptime] +#[comptime] pub fn size_of() -> usize; /// The minimum alignment of a type. @@ -2966,7 +2966,7 @@ pub fn size_of() -> usize; #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] -#[rustc_comptime] +#[comptime] pub fn align_of() -> usize; /// The offset of a field inside a type. @@ -2987,7 +2987,7 @@ pub fn align_of() -> usize; #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[lang = "offset_of"] -#[rustc_comptime] +#[comptime] pub fn offset_of(variant: u32, field: u32) -> usize; /// The offset of a field queried by its field representing type. @@ -3002,7 +3002,7 @@ pub fn offset_of(variant: u32, field: u32) -> usize; #[rustc_intrinsic] #[unstable(feature = "field_projections", issue = "145383")] #[rustc_const_unstable(feature = "field_projections", issue = "145383")] -#[rustc_comptime] +#[comptime] pub fn field_offset() -> usize; /// Returns the number of variants of the type `T` cast to a `usize`; @@ -3017,7 +3017,7 @@ pub fn field_offset() -> usize; #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] -#[rustc_comptime] +#[comptime] pub fn variant_count() -> usize; /// The size of the referenced value in bytes. @@ -3047,7 +3047,7 @@ pub const unsafe fn size_of_val(ptr: *const T) -> usize; pub const unsafe fn align_of_val(ptr: *const T) -> usize; #[rustc_intrinsic] -#[rustc_comptime] +#[comptime] #[unstable(feature = "core_intrinsics", issue = "none")] /// Check if a type represented by a `TypeId` implements a trait represented by a `TypeId`. /// It can only be called at compile time, the backends do @@ -3062,7 +3062,7 @@ pub fn type_id_vtable( /// not implement it. #[rustc_intrinsic] #[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_comptime] +#[comptime] pub fn type_of(_id: crate::any::TypeId) -> crate::mem::type_info::Type; /// Gets a static string slice containing the name of a type. @@ -3076,7 +3076,7 @@ pub fn type_of(_id: crate::any::TypeId) -> crate::mem::type_info::Type; #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] -#[rustc_comptime] +#[comptime] pub fn type_name() -> &'static str; /// Gets an identifier which is globally unique to the specified type. This @@ -3092,7 +3092,7 @@ pub fn type_name() -> &'static str; #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] -#[rustc_comptime] +#[comptime] pub fn type_id() -> crate::any::TypeId; /// Tests (at compile-time) if two [`crate::any::TypeId`] instances identify the @@ -3115,7 +3115,7 @@ pub const fn type_id_eq(a: crate::any::TypeId, b: crate::any::TypeId) -> bool { /// The more user-friendly version of this intrinsic is [`core::any::TypeId::size`]. #[rustc_intrinsic] #[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_comptime] +#[comptime] pub fn size_of_type_id(_id: crate::any::TypeId) -> Option; /// Gets the number of variants of the type represented by this `TypeId`. @@ -3123,16 +3123,20 @@ pub fn size_of_type_id(_id: crate::any::TypeId) -> Option; /// The more user-friendly version of this intrinsic is [`core::any::TypeId::variants`]. #[rustc_intrinsic] #[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_comptime] -pub fn type_id_variants(_id: crate::any::TypeId) -> usize; +#[comptime] +pub fn type_id_variants(_id: crate::any::TypeId) -> usize { + panic!("`TypeId::variants` can only be called at compile-time") +} /// Gets the number of fields at the given `variant_index` represented by this `TypeId`. /// /// The more user-friendly version of this intrinsic is [`core::any::TypeId::fields`]. #[rustc_intrinsic] #[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_comptime] -pub fn type_id_fields(_id: crate::any::TypeId, _variant_index: usize) -> usize; +#[comptime] +pub fn type_id_fields(_id: crate::any::TypeId, _variant_index: usize) -> usize { + panic!("`TypeId::fields` can only be called at compile-time") +} /// Gets the [`FieldRepresentingType`]'s `TypeId` at the given index of the type represented by this `TypeId`. /// @@ -3141,7 +3145,7 @@ pub fn type_id_fields(_id: crate::any::TypeId, _variant_index: usize) -> usize; /// [`FieldRepresentingType`]: crate::field::FieldRepresentingType #[rustc_intrinsic] #[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_comptime] +#[comptime] pub fn type_id_field_representing_type( _id: crate::any::TypeId, _variant_index: usize, @@ -3155,7 +3159,7 @@ pub fn type_id_field_representing_type( /// [`FieldRepresentingType`]: crate::field::FieldRepresentingType #[rustc_intrinsic] #[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_comptime] +#[comptime] pub fn field_representing_type_actual_type_id( _frt_type_id: crate::any::TypeId, ) -> crate::any::TypeId; diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 6e670375fcc5e..0787ae726bbe5 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -88,6 +88,7 @@ #![feature(asm_experimental_arch)] #![feature(bstr_internals)] #![feature(cfg_target_has_reliable_f16_f128)] +#![feature(comptime)] #![feature(const_carrying_mul_add)] #![feature(const_cmp)] #![feature(const_destruct)] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index b58d3b7f1f539..180fa70965c60 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1906,6 +1906,19 @@ pub(crate) mod builtin { /* compiler built-in */ } + /// Mark a function as only being evaluable at compile time. + /// Calling the function at runtime will cause an error. + /// Can only be applied to functions and methods + #[unstable( + feature = "comptime", + issue = "146922", + reason = "`comptime` has open design concerns" + )] + #[rustc_builtin_macro] + pub macro comptime($item:item) { + /* compiler built-in */ + } + /// Unstable placeholder for type ascription. #[allow_internal_unstable(builtin_syntax)] #[unstable( diff --git a/library/core/src/mem/type_info.rs b/library/core/src/mem/type_info.rs index 75270b2d5b14b..4fcdab15b16f2 100644 --- a/library/core/src/mem/type_info.rs +++ b/library/core/src/mem/type_info.rs @@ -37,7 +37,7 @@ impl TypeId { /// It can only be called at compile time. #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] - #[rustc_comptime] + #[comptime] pub fn info(self) -> Type { type_of(self) } @@ -391,7 +391,7 @@ impl TypeId { /// ``` #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] - #[rustc_comptime] + #[comptime] pub fn size(self) -> Option { intrinsics::size_of_type_id(self) } @@ -417,7 +417,7 @@ impl TypeId { /// ``` #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] - #[rustc_comptime] + #[comptime] pub fn variants(self) -> usize { intrinsics::type_id_variants(self) } @@ -480,7 +480,7 @@ impl TypeId { /// ``` #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] - #[rustc_comptime] + #[comptime] pub fn fields(self, variant_index: usize) -> usize { intrinsics::type_id_fields(self, variant_index) } @@ -547,7 +547,7 @@ impl TypeId { /// ``` #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] - #[rustc_comptime] + #[comptime] pub fn field(self, variant_index: usize, field_index: usize) -> FieldId { FieldId { frt_type_id: intrinsics::type_id_field_representing_type( @@ -592,7 +592,7 @@ impl FieldId { /// ``` #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] - #[rustc_comptime] + #[comptime] pub fn type_id(self) -> TypeId { intrinsics::field_representing_type_actual_type_id(self.frt_type_id) } diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs index 6122ab12ec351..0dbfb39b30cdf 100644 --- a/library/core/src/prelude/v1.rs +++ b/library/core/src/prelude/v1.rs @@ -165,6 +165,13 @@ pub use crate::macros::builtin::deref; )] pub use crate::macros::builtin::define_opaque; +#[unstable( + feature = "comptime", + issue = "146922", + reason = "`comptime` has open design concerns" +)] +pub use crate::macros::builtin::comptime; + #[unstable(feature = "extern_item_impls", issue = "125418")] pub use crate::macros::builtin::{eii, unsafe_eii}; diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs index aeefec8b9e084..902795f8fd356 100644 --- a/library/std/src/prelude/v1.rs +++ b/library/std/src/prelude/v1.rs @@ -165,6 +165,13 @@ pub use core::prelude::v1::deref; )] pub use core::prelude::v1::define_opaque; +#[unstable( + feature = "comptime", + issue = "146922", + reason = "`comptime` has open design concerns" +)] +pub use core::prelude::v1::comptime; + #[unstable(feature = "extern_item_impls", issue = "125418")] pub use core::prelude::v1::{eii, unsafe_eii}; diff --git a/tests/ui/comptime/comptime_closure.rs b/tests/ui/comptime/comptime_closure.rs index 64b29997bcda5..e5cba607bf877 100644 --- a/tests/ui/comptime/comptime_closure.rs +++ b/tests/ui/comptime/comptime_closure.rs @@ -1,8 +1,8 @@ -#![feature(rustc_attrs, stmt_expr_attributes)] +#![feature(stmt_expr_attributes, comptime)] const _: () = { - let f = #[rustc_comptime] - //~^ ERROR: the `rustc_comptime` attribute cannot be used on closures + let f = #[comptime] + //~^ ERROR: only functions, trait impls, and methods may be comptime || (); // FIXME(comptime): closures should work, too. diff --git a/tests/ui/comptime/comptime_closure.stderr b/tests/ui/comptime/comptime_closure.stderr index 71445e033ff1e..e5d0343a73683 100644 --- a/tests/ui/comptime/comptime_closure.stderr +++ b/tests/ui/comptime/comptime_closure.stderr @@ -1,10 +1,8 @@ -error: the `rustc_comptime` attribute cannot be used on closures - --> $DIR/comptime_closure.rs:4:15 +error: only functions, trait impls, and methods may be comptime + --> $DIR/comptime_closure.rs:4:13 | -LL | let f = #[rustc_comptime] - | ^^^^^^^^^^^^^^ - | - = help: the `rustc_comptime` attribute can be applied to functions, inherent impl blocks, and inherent methods +LL | let f = #[comptime] + | ^^^^^^^^^^^ error[E0015]: cannot call non-const closure in constants --> $DIR/comptime_closure.rs:9:5 diff --git a/tests/ui/comptime/comptime_impl.rs b/tests/ui/comptime/comptime_impl.rs index 6e8768aaed109..e697da61b6aaf 100644 --- a/tests/ui/comptime/comptime_impl.rs +++ b/tests/ui/comptime/comptime_impl.rs @@ -1,4 +1,4 @@ -#![feature(rustc_attrs, const_trait_impl)] +#![feature(const_trait_impl, comptime)] const trait Foo { fn foo(&self); @@ -8,20 +8,19 @@ const trait Foo { struct Bar; -#[rustc_comptime] +#[comptime] impl Bar { fn boo(&self) {} } -#[rustc_comptime] -//~^ ERROR: cannot be used on trait impl +#[comptime] impl Foo for Bar { fn foo(&self) { comptime_fn(); } } -#[rustc_comptime] +#[comptime] fn comptime_fn() {} const _: () = { diff --git a/tests/ui/comptime/comptime_impl.stderr b/tests/ui/comptime/comptime_impl.stderr index 4c55736c0bb63..bb97123712d12 100644 --- a/tests/ui/comptime/comptime_impl.stderr +++ b/tests/ui/comptime/comptime_impl.stderr @@ -1,13 +1,5 @@ -error: the `rustc_comptime` attribute cannot be used on trait impl blocks - --> $DIR/comptime_impl.rs:16:3 - | -LL | #[rustc_comptime] - | ^^^^^^^^^^^^^^ - | - = help: the `rustc_comptime` attribute can be applied to functions and inherent impl blocks - error[E0277]: the trait bound `Bar: const Foo` is not satisfied - --> $DIR/comptime_impl.rs:29:9 + --> $DIR/comptime_impl.rs:28:9 | LL | Bar.foo(); | ^^^ @@ -18,7 +10,7 @@ LL | const impl Foo for Bar { | +++++ error[E0277]: the trait bound `Bar: const Foo` is not satisfied - --> $DIR/comptime_impl.rs:31:9 + --> $DIR/comptime_impl.rs:30:9 | LL | Bar.bar(); | ^^^ @@ -28,6 +20,6 @@ help: make the `impl` of trait `Foo` `const` LL | const impl Foo for Bar { | +++++ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/comptime/comptime_method.rs b/tests/ui/comptime/comptime_method.rs index a55c950b01680..599b09d867e2a 100644 --- a/tests/ui/comptime/comptime_method.rs +++ b/tests/ui/comptime/comptime_method.rs @@ -1,8 +1,8 @@ -#![feature(rustc_attrs)] +#![feature(comptime)] struct Bar; -#[rustc_comptime] +#[comptime] impl Bar { fn boo(&self) {} } diff --git a/tests/ui/comptime/comptime_method_bounds.rs b/tests/ui/comptime/comptime_method_bounds.rs index 993fd28abd1f1..279ad3eb45c14 100644 --- a/tests/ui/comptime/comptime_method_bounds.rs +++ b/tests/ui/comptime/comptime_method_bounds.rs @@ -1,6 +1,6 @@ //@check-pass -#![feature(rustc_attrs, const_trait_impl)] +#![feature(const_trait_impl, comptime)] struct Bar(T); @@ -8,7 +8,7 @@ const trait Trait { fn method(&self) {} } -#[rustc_comptime] +#[comptime] impl Bar { fn boo(&self) { self.0.method() diff --git a/tests/ui/comptime/comptime_trait.rs b/tests/ui/comptime/comptime_trait.rs index b7f2ffe7faf3e..efce2a2d68b1a 100644 --- a/tests/ui/comptime/comptime_trait.rs +++ b/tests/ui/comptime/comptime_trait.rs @@ -1,30 +1,35 @@ -#![feature(rustc_attrs, const_trait_impl, trait_alias)] +#![feature(const_trait_impl, trait_alias, comptime)] -#[rustc_comptime] -//~^ ERROR: the `rustc_comptime` attribute cannot be used on traits +#[comptime] +//~^ ERROR: only functions, trait impls, and methods may be comptime trait Trait { fn method(&self) {} } const impl Trait for () {} +//~^ ERROR: const `impl` for trait `Trait` which is not `const` -#[rustc_comptime] -//~^ ERROR: the `rustc_comptime` attribute cannot be used on trait impl +#[comptime] impl Trait for u32 { + //~^ ERROR: comptime `impl` for trait `Trait` which is not `const` fn method(&self) { comptime_fn(); } } -#[rustc_comptime] +#[comptime] fn comptime_fn() {} -#[rustc_comptime] -//~^ ERROR: the `rustc_comptime` attribute cannot be used on trait aliases +#[comptime] +//~^ ERROR: only functions, trait impls, and methods may be comptime trait TraitAlias = const Trait; +//~^ ERROR: `const` can only be applied to `const` traits +//~| ERROR: `const` can only be applied to `const` traits +//~| ERROR: `const` can only be applied to `const` traits -#[rustc_comptime] +#[comptime] fn func(t: &T) { + //~^ ERROR: `const` can only be applied to `const` traits t.method() //~^ ERROR: cannot call non-const method `::method` in constants } diff --git a/tests/ui/comptime/comptime_trait.stderr b/tests/ui/comptime/comptime_trait.stderr index 71fa410608405..b5ac7a2c80f17 100644 --- a/tests/ui/comptime/comptime_trait.stderr +++ b/tests/ui/comptime/comptime_trait.stderr @@ -1,35 +1,106 @@ -error: the `rustc_comptime` attribute cannot be used on traits - --> $DIR/comptime_trait.rs:3:3 +error: only functions, trait impls, and methods may be comptime + --> $DIR/comptime_trait.rs:3:1 | -LL | #[rustc_comptime] - | ^^^^^^^^^^^^^^ +LL | #[comptime] + | ^^^^^^^^^^^ + +error: only functions, trait impls, and methods may be comptime + --> $DIR/comptime_trait.rs:23:1 + | +LL | #[comptime] + | ^^^^^^^^^^^ + +error: const `impl` for trait `Trait` which is not `const` + --> $DIR/comptime_trait.rs:9:12 | - = help: the `rustc_comptime` attribute can be applied to functions and inherent impl blocks +LL | const impl Trait for () {} + | ^^^^^ this trait is not `const` + | + = note: marking a trait with `const` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change +help: mark `Trait` as `const` to allow it to have `const` implementations + | +LL | const trait Trait { + | +++++ -error: the `rustc_comptime` attribute cannot be used on trait impl blocks - --> $DIR/comptime_trait.rs:11:3 +error: comptime `impl` for trait `Trait` which is not `const` + --> $DIR/comptime_trait.rs:13:6 + | +LL | impl Trait for u32 { + | ^^^^^ this trait is not `const` | -LL | #[rustc_comptime] - | ^^^^^^^^^^^^^^ + = note: marking a trait with `const` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change +help: mark `Trait` as `const` to allow it to have `const` implementations | - = help: the `rustc_comptime` attribute can be applied to functions and inherent impl blocks +LL | const trait Trait { + | +++++ -error: the `rustc_comptime` attribute cannot be used on trait aliases - --> $DIR/comptime_trait.rs:22:3 +error: `const` can only be applied to `const` traits + --> $DIR/comptime_trait.rs:25:20 + | +LL | trait TraitAlias = const Trait; + | ^^^^^ can't be applied to `Trait` + | +help: mark `Trait` as `const` to allow it to have `const` implementations + | +LL | const trait Trait { + | +++++ + +error: `const` can only be applied to `const` traits + --> $DIR/comptime_trait.rs:25:20 + | +LL | trait TraitAlias = const Trait; + | ^^^^^ can't be applied to `Trait` | -LL | #[rustc_comptime] - | ^^^^^^^^^^^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: mark `Trait` as `const` to allow it to have `const` implementations | - = help: the `rustc_comptime` attribute can be applied to functions and inherent impl blocks +LL | const trait Trait { + | +++++ + +error: `const` can only be applied to `const` traits + --> $DIR/comptime_trait.rs:25:20 + | +LL | trait TraitAlias = const Trait; + | ^^^^^ can't be applied to `Trait` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: mark `Trait` as `const` to allow it to have `const` implementations + | +LL | const trait Trait { + | +++++ + +error: `const` can only be applied to `const` traits + --> $DIR/comptime_trait.rs:31:12 + | +LL | fn func(t: &T) { + | ^^^^^ can't be applied to `TraitAlias` + | +help: mark `TraitAlias` as `const` to allow it to have `const` implementations + | +LL | const trait TraitAlias = const Trait; + | +++++ error[E0015]: cannot call non-const method `::method` in constants - --> $DIR/comptime_trait.rs:28:7 + --> $DIR/comptime_trait.rs:33:7 | LL | t.method() | ^^^^^^^^ | +note: method `method` is not const because trait `Trait` is not const + --> $DIR/comptime_trait.rs:5:1 + | +LL | trait Trait { + | ^^^^^^^^^^^ this trait is not const +LL | fn method(&self) {} + | ---------------- this method is not const = note: calls in constants are limited to constant functions, tuple structs and tuple variants +help: consider making trait `Trait` const + | +LL | const trait Trait { + | +++++ -error: aborting due to 4 previous errors +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/comptime/const_comptime.rs b/tests/ui/comptime/const_comptime.rs index 827e4dfcf545b..cbc98cc4c2beb 100644 --- a/tests/ui/comptime/const_comptime.rs +++ b/tests/ui/comptime/const_comptime.rs @@ -1,6 +1,6 @@ -#![feature(rustc_attrs)] +#![feature(comptime)] -#[rustc_comptime] +#[comptime] const fn foo() {} //~^ ERROR a function cannot be both `comptime` and `const` diff --git a/tests/ui/comptime/const_comptime.stderr b/tests/ui/comptime/const_comptime.stderr index 8be8ee7d69a1d..8a120103971df 100644 --- a/tests/ui/comptime/const_comptime.stderr +++ b/tests/ui/comptime/const_comptime.stderr @@ -1,14 +1,6 @@ error: a function cannot be both `comptime` and `const` --> $DIR/const_comptime.rs:4:1 | -LL | #[rustc_comptime] - | ----------------- `comptime` because of this -LL | const fn foo() {} - | ^^^^^ help: remove the `const` - | -note: `const` implies the function can be called at runtime, too - --> $DIR/const_comptime.rs:4:1 - | LL | const fn foo() {} | ^^^^^ diff --git a/tests/ui/comptime/feature-gate-test.rs b/tests/ui/comptime/feature-gate-test.rs index cd4ee521997e0..3ed2e4b3cd377 100644 --- a/tests/ui/comptime/feature-gate-test.rs +++ b/tests/ui/comptime/feature-gate-test.rs @@ -1,5 +1,5 @@ -#[rustc_comptime] -//~^ ERROR use of an internal attribute +#[comptime] +//~^ ERROR use of unstable library feature `comptime` fn foo() {} fn main() {} diff --git a/tests/ui/comptime/feature-gate-test.stderr b/tests/ui/comptime/feature-gate-test.stderr index b65965c777221..c95c6e7db0528 100644 --- a/tests/ui/comptime/feature-gate-test.stderr +++ b/tests/ui/comptime/feature-gate-test.stderr @@ -1,11 +1,12 @@ -error[E0658]: use of an internal attribute +error[E0658]: use of unstable library feature `comptime`: `comptime` has open design concerns --> $DIR/feature-gate-test.rs:1:3 | -LL | #[rustc_comptime] - | ^^^^^^^^^^^^^^ +LL | #[comptime] + | ^^^^^^^^ | - = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable - = note: the `rustc_comptime` attribute is an internal implementation detail that will never be stable + = note: see issue #146922 for more information + = help: add `#![feature(comptime)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 1 previous error diff --git a/tests/ui/comptime/link-dead-code.rs b/tests/ui/comptime/link-dead-code.rs index 4f359420521f6..00e1823743aea 100644 --- a/tests/ui/comptime/link-dead-code.rs +++ b/tests/ui/comptime/link-dead-code.rs @@ -3,9 +3,9 @@ //! Check that we don't try to generate assembly for comptime //! fns, even when link-dead-code is active. -#![feature(rustc_attrs)] +#![feature(comptime)] -#[rustc_comptime] +#[comptime] fn f() {} fn main() {} diff --git a/tests/ui/comptime/not_callable.rs b/tests/ui/comptime/not_callable.rs index c06e643d5403e..d2738de61f8fe 100644 --- a/tests/ui/comptime/not_callable.rs +++ b/tests/ui/comptime/not_callable.rs @@ -1,6 +1,6 @@ -#![feature(rustc_attrs, const_trait_impl)] +#![feature(comptime, const_trait_impl)] -#[rustc_comptime] +#[comptime] fn foo() {} fn main() { @@ -15,7 +15,7 @@ const fn bar() { foo(); //~ ERROR: comptime fns can only be called at compile time } -#[rustc_comptime] +#[comptime] fn baz() { // Ok foo(); diff --git a/tests/ui/comptime/trait_bounds.rs b/tests/ui/comptime/trait_bounds.rs index 3df2f41558fcc..78c1b6d8d5b0c 100644 --- a/tests/ui/comptime/trait_bounds.rs +++ b/tests/ui/comptime/trait_bounds.rs @@ -1,22 +1,22 @@ -#![feature(rustc_attrs, const_trait_impl)] +#![feature(comptime, const_trait_impl)] const trait Trait { fn method() {} } -#[rustc_comptime] +#[comptime] fn always_const() { T::method() } -#[rustc_comptime] +#[comptime] fn conditionally_const() { //~^ ERROR: `[const]` is not allowed here T::method() //~^ ERROR: `T: const Trait` is not satisfied } -#[rustc_comptime] +#[comptime] fn non_const() { T::method() //~^ ERROR: `T: const Trait` is not satisfied diff --git a/tests/ui/comptime/trait_comptime.rs b/tests/ui/comptime/trait_comptime.rs index a42e85c49f702..2226918b3f14e 100644 --- a/tests/ui/comptime/trait_comptime.rs +++ b/tests/ui/comptime/trait_comptime.rs @@ -1,25 +1,25 @@ -#![feature(rustc_attrs)] +#![feature(comptime)] trait Foo { - #[rustc_comptime] - //~^ ERROR: cannot be used on required trait methods + #[comptime] + //~^ ERROR: functions in traits cannot be declared #[comptime] fn foo(); - #[rustc_comptime] - //~^ ERROR: cannot be used on provided trait methods + #[comptime] + //~^ ERROR: functions in traits cannot be declared #[comptime] fn bar() {} } struct Bar; impl Bar { - #[rustc_comptime] + #[comptime] fn foo() {} } impl Foo for Bar { - #[rustc_comptime] - //~^ ERROR: cannot be used on trait methods + #[comptime] + //~^ ERROR: functions in trait impls cannot be declared #[comptime] fn foo() {} } diff --git a/tests/ui/comptime/trait_comptime.stderr b/tests/ui/comptime/trait_comptime.stderr index 2411ebe70759b..3fe13d427085d 100644 --- a/tests/ui/comptime/trait_comptime.stderr +++ b/tests/ui/comptime/trait_comptime.stderr @@ -1,26 +1,36 @@ -error: the `rustc_comptime` attribute cannot be used on required trait methods - --> $DIR/trait_comptime.rs:4:7 +error[E0379]: functions in traits cannot be declared #[comptime] + --> $DIR/trait_comptime.rs:4:5 | -LL | #[rustc_comptime] - | ^^^^^^^^^^^^^^ - | - = help: the `rustc_comptime` attribute can be applied to functions with a body and inherent impl blocks +LL | #[comptime] + | -^^^^^^^^^^ + | | + | _____functions in traits cannot be #[comptime] + | | +LL | | + | |____- help: remove the `#[comptime]` -error: the `rustc_comptime` attribute cannot be used on provided trait methods - --> $DIR/trait_comptime.rs:8:7 - | -LL | #[rustc_comptime] - | ^^^^^^^^^^^^^^ +error[E0379]: functions in traits cannot be declared #[comptime] + --> $DIR/trait_comptime.rs:8:5 | - = help: the `rustc_comptime` attribute can be applied to functions, inherent impl blocks, and inherent methods +LL | #[comptime] + | -^^^^^^^^^^ + | | + | _____functions in traits cannot be #[comptime] + | | +LL | | + | |____- help: remove the `#[comptime]` -error: the `rustc_comptime` attribute cannot be used on trait methods in impl blocks - --> $DIR/trait_comptime.rs:21:7 - | -LL | #[rustc_comptime] - | ^^^^^^^^^^^^^^ +error[E0379]: functions in trait impls cannot be declared #[comptime] + --> $DIR/trait_comptime.rs:21:5 | - = help: the `rustc_comptime` attribute can be applied to functions, inherent impl blocks, and inherent methods +LL | #[comptime] + | -^^^^^^^^^^ + | | + | _____functions in trait impls cannot be #[comptime] + | | +LL | | + | |____- help: remove the `#[comptime]` error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0379`. From 7ef76bce268a6dd70f927c7105be24c31735afd2 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 19 Jun 2026 15:40:03 +0200 Subject: [PATCH 4/5] Load the `DefKind` of assoc fns directly from the query instead of guessing it --- compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index b413d0c0bb2de..32ae2da8d5a19 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -251,7 +251,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { method: MethodCallee<'tcx>, ) { self.enforce_context_effects(Some(hir_id), span, method.def_id, method.args); - self.write_resolution(hir_id, Ok((DefKind::AssocFn, method.def_id))); + self.write_resolution(hir_id, Ok((self.tcx.def_kind(method.def_id), method.def_id))); self.write_args(hir_id, method.args); } From 04e19039c3e176ee0b5c8e7a90f1850fc3d134c5 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 16 Jun 2026 21:48:43 +0200 Subject: [PATCH 5/5] Feed constness in def collection --- .../rustc_ast_passes/src/ast_validation.rs | 78 +----- compiler/rustc_ast_passes/src/diagnostics.rs | 52 +--- .../src/collect/predicates_of.rs | 5 +- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- compiler/rustc_resolve/src/def_collector.rs | 264 +++++++++++++++--- compiler/rustc_resolve/src/diagnostics/mod.rs | 51 ++++ compiler/rustc_resolve/src/lib.rs | 18 ++ .../ui/parser/fn-header-semantic-fail.stderr | 36 +-- ...sure-in-non-const-trait-impl-method.stderr | 2 +- ...t-closure-in-non-const-trait-method.stderr | 2 +- ...st-op-const-closure-non-const-outer.stderr | 2 +- 11 files changed, 333 insertions(+), 179 deletions(-) diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 524bd9a0bc548..d64c0056f70a1 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -82,8 +82,8 @@ impl SplatSemantic { } enum TraitOrImpl { - Trait { vis: Span, constness: Const }, - TraitImpl { constness: Const, polarity: ImplPolarity, trait_ref_span: Span }, + Trait { constness: Const }, + TraitImpl { constness: Const }, Impl { constness: Const }, } @@ -160,10 +160,10 @@ impl<'a> AstValidator<'a> { self.outer_trait_or_trait_impl = old; } - fn with_in_trait(&mut self, vis: Span, constness: Const, f: impl FnOnce(&mut Self)) { + fn with_in_trait(&mut self, constness: Const, f: impl FnOnce(&mut Self)) { let old = mem::replace( &mut self.outer_trait_or_trait_impl, - Some(TraitOrImpl::Trait { vis, constness }), + Some(TraitOrImpl::Trait { constness }), ); f(self); self.outer_trait_or_trait_impl = old; @@ -303,67 +303,12 @@ impl<'a> AstValidator<'a> { } } - fn check_impl_fn_not_const(&self, constness: Const, parent_constness: Const) { - let Const::Yes(span) = constness else { - return; - }; - - let span = self.sess.source_map().span_extend_while_whitespace(span); - - let Const::Yes(parent_constness) = parent_constness else { - return; - }; - - self.dcx().emit_err(diagnostics::ImplFnConst { span, parent_constness }); - } - - fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrImpl) { + fn check_trait_fn_not_const(&self, constness: Const, _parent: &TraitOrImpl) { let (Const::Yes(span) | Const::Always(span)) = constness else { return; }; - let const_trait_impl = self.features.const_trait_impl(); - let make_impl_const_sugg = if const_trait_impl - && let TraitOrImpl::TraitImpl { - constness: Const::No, - polarity: ImplPolarity::Positive, - trait_ref_span, - .. - } = parent - { - Some(trait_ref_span.shrink_to_lo()) - } else { - None - }; - - let map = self.sess.source_map(); - - let make_trait_const_sugg = if const_trait_impl - && let &TraitOrImpl::Trait { vis, constness: ast::Const::No } = parent - { - Some(map.span_extend_while_whitespace(vis).shrink_to_hi()) - } else { - None - }; - - let parent_constness = parent.constness(); - self.dcx().emit_err(diagnostics::TraitFnConst { - span, - in_impl: matches!(parent, TraitOrImpl::TraitImpl { .. }), - const_context_label: parent_constness, - remove_const_sugg: ( - map.span_extend_while_whitespace(span), - match parent_constness { - Some(_) => rustc_errors::Applicability::MachineApplicable, - None => rustc_errors::Applicability::MaybeIncorrect, - }, - ), - requires_multiple_changes: make_impl_const_sugg.is_some() - || make_trait_const_sugg.is_some(), - make_impl_const_sugg, - make_trait_const_sugg, - constness: constness.descr(), - }); + self.dcx().span_delayed_bug(span, "should have rejected this in def collection"); } fn check_async_fn_in_const_trait_or_impl(&self, sig: &FnSig, parent: &TraitOrImpl) { @@ -1426,11 +1371,7 @@ impl Visitor<'_> for AstValidator<'_> { self.visit_ty(self_ty); self.with_in_trait_or_impl( - Some(TraitOrImpl::TraitImpl { - constness: *constness, - polarity: *polarity, - trait_ref_span: t.path.span, - }), + Some(TraitOrImpl::TraitImpl { constness: *constness }), |this| { walk_list!( this, @@ -1584,7 +1525,7 @@ impl Visitor<'_> for AstValidator<'_> { this.visit_generics(generics); walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits) }); - self.with_in_trait(item.span, *constness, |this| { + self.with_in_trait(*constness, |this| { walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait); }); } @@ -2117,9 +2058,8 @@ impl Visitor<'_> for AstValidator<'_> { self.check_async_fn_in_const_trait_or_impl(sig, parent); } } - Some(parent @ TraitOrImpl::Impl { constness }) => { + Some(parent @ TraitOrImpl::Impl { .. }) => { if let AssocItemKind::Fn(Fn { sig, .. }) = &item.kind { - self.check_impl_fn_not_const(sig.header.constness, *constness); self.check_async_fn_in_const_trait_or_impl(sig, parent); } } diff --git a/compiler/rustc_ast_passes/src/diagnostics.rs b/compiler/rustc_ast_passes/src/diagnostics.rs index 8a3544cc76452..597f85d6de74b 100644 --- a/compiler/rustc_ast_passes/src/diagnostics.rs +++ b/compiler/rustc_ast_passes/src/diagnostics.rs @@ -2,7 +2,7 @@ use rustc_abi::ExternAbi; use rustc_errors::codes::*; -use rustc_errors::{Applicability, Diag, EmissionGuarantee, Subdiagnostic}; +use rustc_errors::{Diag, EmissionGuarantee, Subdiagnostic}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Ident, Span, Symbol}; @@ -28,56 +28,6 @@ pub(crate) enum VisibilityNotPermittedNote { #[note("place qualifiers on individual foreign items instead")] IndividualForeignItems, } -#[derive(Diagnostic)] -#[diag("redundant `const` fn marker in const impl")] -pub(crate) struct ImplFnConst { - #[primary_span] - #[suggestion("remove the `const`", code = "", applicability = "machine-applicable")] - pub span: Span, - #[label("this declares all associated functions implicitly const")] - pub parent_constness: Span, -} - -#[derive(Diagnostic)] -#[diag("functions in {$in_impl -> - [true] trait impls - *[false] traits - } cannot be declared {$constness}", code = E0379)] -pub(crate) struct TraitFnConst { - #[primary_span] - #[label( - "functions in {$in_impl -> - [true] trait impls - *[false] traits - } cannot be {$constness}" - )] - pub span: Span, - pub in_impl: bool, - #[label("this declares all associated functions implicitly {$constness}")] - pub const_context_label: Option, - #[suggestion( - "remove the `{$constness}`{$requires_multiple_changes -> - [true] {\" ...\"} - *[false] {\"\"} - }", - code = "" - )] - pub remove_const_sugg: (Span, Applicability), - pub requires_multiple_changes: bool, - #[suggestion( - "... and declare the impl to be {$constness} instead", - code = "{constness} ", - applicability = "maybe-incorrect" - )] - pub make_impl_const_sugg: Option, - #[suggestion( - "... and declare the trait to be {$constness} instead", - code = "{constness} ", - applicability = "maybe-incorrect" - )] - pub make_trait_const_sugg: Option, - pub constness: &'static str, -} #[derive(Diagnostic)] #[diag( diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 46f90ad160cac..352a8091f552e 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -1053,7 +1053,10 @@ pub(super) fn const_conditions<'tcx>( def_id: LocalDefId, ) -> ty::ConstConditions<'tcx> { if !tcx.is_conditionally_const(def_id) { - bug!("const_conditions invoked for item that is not conditionally const: {def_id:?}"); + bug!( + "const_conditions invoked for item that is not conditionally const: {def_id:?}, {:?}", + tcx.def_kind(def_id) + ); } match tcx.opt_rpitit_info(def_id.to_def_id()) { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 3614a67b71045..0c8ba1dda0083 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -434,7 +434,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { | DefKind::Enum | DefKind::Trait | DefKind::TyAlias - | DefKind::Fn + | DefKind::Fn { .. } | DefKind::Const { .. } | DefKind::Static { .. } = kind { diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 0b54b265fcee7..1eb116b06ee67 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -15,9 +15,11 @@ use rustc_middle::ty::{PerOwnerResolverData, TyCtxtFeed}; use rustc_span::{Span, Symbol, sym}; use tracing::{debug, instrument}; +use crate::diagnostics::{ImplFnConst, TraitFnConst}; use crate::macros::MacroRulesScopeRef; use crate::{ - ImplTraitContext, InvocationParent, ParentScope, Resolver, with_owner, with_owner_tables, + ConstOwner, ImplTraitContext, InvocationParent, ParentScope, Resolver, with_owner, + with_owner_tables, }; pub(crate) fn collect_definitions<'ra>( @@ -66,12 +68,14 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { ) } + #[instrument(level = "trace", skip(self, f))] fn with_parent(&mut self, parent_def: LocalDefId, f: F) { let orig_parent_def = mem::replace(&mut self.invocation_parent.parent_def, parent_def); f(self); self.invocation_parent.parent_def = orig_parent_def; } + #[instrument(level = "trace", skip(self, f))] pub(super) fn with_owner)>( &mut self, owner: NodeId, @@ -103,6 +107,16 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { assert_eq!(old, owner); } + fn with_const_owner( + &mut self, + const_owner: Option<(ConstOwner, ast::Const)>, + f: F, + ) { + let orig_itc = mem::replace(&mut self.invocation_parent.const_owner, const_owner); + f(self); + self.invocation_parent.const_owner = orig_itc; + } + fn with_impl_trait( &mut self, impl_trait_context: ImplTraitContext, @@ -142,6 +156,35 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { let old_parent = self.r.invocation_parents.insert(id, self.invocation_parent); assert!(old_parent.is_none(), "parent `LocalDefId` is reset for an invocation"); } + + fn lower_constness(&self, constness: Const) -> hir::Constness { + match constness { + Const::Always(_) => hir::Constness::Const { always: true }, + Const::Yes(_) => hir::Constness::Const { always: false }, + Const::No => hir::Constness::NotConst, + } + } + + fn create_closure(&mut self, expr: &'a Expr, constness: Const) { + let feed = self.create_def(expr.id, None, DefKind::Closure, expr.span); + + let constness = match (constness, self.invocation_parent.const_owner) { + (Const::No, _) => Const::No, + // FIXME(const_closures, comptime): always const closures + (Const::Always(_), _) => unimplemented!(), + (Const::Yes(span), None | Some((_, Const::No))) => { + self.r + .tcx + .dcx() + .span_err(span, "cannot use `const` closures outside of const contexts"); + Const::No + } + (Const::Yes(_), Some((_, Const::Yes(_) | Const::Always(_)))) => constness, + }; + let constness = self.lower_constness(constness); + feed.constness(constness); + self.with_parent(feed.def_id(), |this| visit::walk_expr(this, expr)); + } } impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { @@ -149,28 +192,43 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { // Pick the def data. This need not be unique, but the more // information we encapsulate into, the better let mut opt_syn_ext = None; - let def_kind = match &i.kind { - ItemKind::Impl(i) => DefKind::Impl { of_trait: i.of_trait.is_some() }, - ItemKind::ForeignMod(..) => DefKind::ForeignMod, - ItemKind::Mod(..) => DefKind::Mod, - ItemKind::Trait(..) => DefKind::Trait, - ItemKind::TraitAlias(..) => DefKind::TraitAlias, - ItemKind::Enum(..) => DefKind::Enum, - ItemKind::Struct(..) => DefKind::Struct, - ItemKind::Union(..) => DefKind::Union, - ItemKind::ExternCrate(..) => DefKind::ExternCrate, - ItemKind::TyAlias(..) => DefKind::TyAlias, - ItemKind::Static(s) => DefKind::Static { - safety: hir::Safety::Safe, - mutability: s.mutability, - nested: false, - }, + + let (def_kind, constness) = match &i.kind { + ItemKind::Impl(i) => ( + DefKind::Impl { of_trait: i.of_trait.is_some() }, + Some(self.lower_constness(i.constness)), + ), + ItemKind::ForeignMod(..) => (DefKind::ForeignMod, None), + ItemKind::Mod(..) => (DefKind::Mod, None), + ItemKind::Trait(tr) => (DefKind::Trait, Some(self.lower_constness(tr.constness))), + ItemKind::TraitAlias(ta) => { + (DefKind::TraitAlias, Some(self.lower_constness(ta.constness))) + } + ItemKind::Enum(..) => (DefKind::Enum, None), + ItemKind::Struct(..) => (DefKind::Struct, None), + ItemKind::Union(..) => (DefKind::Union, None), + ItemKind::ExternCrate(..) => (DefKind::ExternCrate, None), + ItemKind::TyAlias(..) => (DefKind::TyAlias, None), + ItemKind::Static(s) => ( + DefKind::Static { + safety: hir::Safety::Safe, + mutability: s.mutability, + nested: false, + }, + None, + ), ItemKind::Const(citem) => { let is_type_const = citem.kind == ConstItemKind::TypeConst; - DefKind::Const { is_type_const } + (DefKind::Const { is_type_const }, None) + } + ItemKind::ConstBlock(..) => (DefKind::Const { is_type_const: false }, None), + ItemKind::Fn(func) => { + (DefKind::Fn, Some(self.lower_constness(func.sig.header.constness))) + } + ItemKind::Delegation(..) => { + // Need to compute constness lazily + (DefKind::Fn, None) } - ItemKind::ConstBlock(..) => DefKind::Const { is_type_const: false }, - ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn, ItemKind::MacroDef(ident, def) => { let edition = i.span.edition(); @@ -199,9 +257,9 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { let ext = self.r.compile_macro(def, *ident, &attrs, i.span, i.id, edition); let macro_kinds = ext.macro_kinds(); opt_syn_ext = Some(ext); - DefKind::Macro(macro_kinds) + (DefKind::Macro(macro_kinds), None) } - ItemKind::GlobalAsm(..) => DefKind::GlobalAsm, + ItemKind::GlobalAsm(..) => (DefKind::GlobalAsm, None), ItemKind::Use(_) => { return self.with_owner(i.id, None, DefKind::Use, i.span, |this, feed| { this.brg_visit_item(i, feed); @@ -220,13 +278,38 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { def_kind, i.span, |this, feed| { + if let Some(constness) = constness { + feed.constness(constness); + } if let Some(ext) = opt_syn_ext { this.r.local_macro_map.insert(feed.def_id(), this.r.arenas.alloc_macro(ext)); } this.with_parent(feed.def_id(), |this| { - this.with_impl_trait(ImplTraitContext::Existential, |this| { - this.brg_visit_item(i, feed) + let const_owner = match &i.kind { + ItemKind::Impl(i) => Some(( + match &i.of_trait { + None => ConstOwner::InherentImpl, + Some(tr) => ConstOwner::TraitImpl { + polarity: tr.polarity, + trait_ref_span: tr.trait_ref.path.span, + }, + }, + i.constness, + )), + ItemKind::Trait(t) => { + Some((ConstOwner::Trait { vis: i.span }, t.constness)) + } + ItemKind::Fn(f) => Some((ConstOwner::Fn, f.sig.header.constness)), + ItemKind::Static(_) | ItemKind::Const(_) => { + Some((ConstOwner::Const, Const::Yes(i.span))) + } + _ => None, + }; + this.with_const_owner(const_owner, |this| { + this.with_impl_trait(ImplTraitContext::Existential, |this| { + this.brg_visit_item(i, feed) + }) }) }); }, @@ -382,17 +465,120 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { } fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) { - let (ident, def_kind, ns) = match &i.kind { - AssocItemKind::Fn(Fn { ident, .. }) - | AssocItemKind::Delegation(Delegation { ident, .. }) => { - (*ident, DefKind::AssocFn, ValueNS) + let (ident, def_kind, ns, constness) = match &i.kind { + AssocItemKind::Fn(Fn { ident, sig, .. }) => { + let constness = + match (sig.header.constness, self.invocation_parent.const_owner.unwrap(), ctxt) + { + (Const::No, (_, other), _) => other, + + (other, (_, Const::No), visit::AssocCtxt::Impl { of_trait: false }) => { + other + } + ( + Const::Always(span) | Const::Yes(span), + (parent, parent_constness), + visit::AssocCtxt::Trait | visit::AssocCtxt::Impl { of_trait: true }, + ) => { + let const_trait_impl = self.r.features.const_trait_impl(); + let make_impl_const_sugg = if const_trait_impl + && let visit::AssocCtxt::Impl { of_trait: true } = ctxt + && let Const::No = parent_constness + && let ConstOwner::TraitImpl { + polarity: ImplPolarity::Positive, + trait_ref_span, + } = parent + { + Some(trait_ref_span.shrink_to_lo()) + } else { + None + }; + + let map = self.r.tcx.sess.source_map(); + + let make_trait_const_sugg = if const_trait_impl + && let (ConstOwner::Trait { vis }, Const::No) = + (parent, parent_constness) + { + Some(map.span_extend_while_whitespace(vis).shrink_to_hi()) + } else { + None + }; + self.r.tcx.dcx().emit_err(TraitFnConst { + span, + in_impl: matches!(ctxt, visit::AssocCtxt::Impl { of_trait: true }), + const_context_label: match parent_constness { + Const::Always(span) | Const::Yes(span) => Some(span), + Const::No => None, + }, + remove_const_sugg: ( + map.span_extend_while_whitespace(span), + match parent_constness { + Const::Always(_) | Const::Yes(_) => { + rustc_errors::Applicability::MachineApplicable + } + Const::No => rustc_errors::Applicability::MaybeIncorrect, + }, + ), + requires_multiple_changes: make_impl_const_sugg.is_some() + || make_trait_const_sugg.is_some(), + make_impl_const_sugg, + make_trait_const_sugg, + constness: sig.header.constness.descr(), + }); + parent_constness + } + ( + Const::Yes(span), + (_, Const::Yes(parent_constness)), + visit::AssocCtxt::Impl { of_trait: false }, + ) => { + let span = + self.r.tcx.sess.source_map().span_extend_while_whitespace(span); + self.r.tcx.dcx().emit_err(ImplFnConst { span, parent_constness }); + Const::Yes(parent_constness) + } + ( + Const::Yes(span) | Const::Always(span), + (_, parent_constness @ (Const::Yes(parent) | Const::Always(parent))), + _, + ) => { + self.r + .tcx + .dcx() + .struct_span_err( + span, + "conflicting `const`/`comptime` fn marker in const impl", + ) + .with_span_label( + parent, + "this declares all associated functions implicitly const", + ) + .emit(); + parent_constness + } + }; + let constness = if i + .attrs + .iter() + .any(|attr| attr.has_name(sym::rustc_non_const_trait_method)) + { + Const::No + } else { + constness + }; + (*ident, DefKind::AssocFn, ValueNS, Some(constness)) + } + AssocItemKind::Delegation(Delegation { ident, .. }) => { + (*ident, DefKind::AssocFn, ValueNS, None) } AssocItemKind::Const(ConstItem { ident, kind, .. }) => ( *ident, DefKind::AssocConst { is_type_const: *kind == ConstItemKind::TypeConst }, ValueNS, + None, ), - AssocItemKind::Type(TyAlias { ident, .. }) => (*ident, DefKind::AssocTy, TypeNS), + AssocItemKind::Type(TyAlias { ident, .. }) => (*ident, DefKind::AssocTy, TypeNS, None), AssocItemKind::MacCall(..) => { self.visit_macro_invoc(i.id); self.visit_assoc_item_mac_call(i, ctxt); @@ -404,8 +590,13 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { }; self.with_owner(i.id, Some(ident.name), def_kind, i.span, |this, feed| { - this.with_parent(feed.def_id(), |this| { - this.brg_visit_assoc_item(i, ctxt, ident, ns, feed) + if let Some(constness) = constness { + feed.constness(this.lower_constness(constness)); + } + this.with_const_owner(constness.map(|c| (ConstOwner::Fn, c)), |this| { + this.with_parent(feed.def_id(), |this| { + this.brg_visit_assoc_item(i, ctxt, ident, ns, feed) + }) }); }) } @@ -423,7 +614,10 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { fn visit_anon_const(&mut self, constant: &'a AnonConst) { let parent = self.create_def(constant.id, None, DefKind::AnonConst, constant.value.span).def_id(); - self.with_parent(parent, |this| visit::walk_anon_const(this, constant)); + + self.with_const_owner(Some((ConstOwner::Const, Const::Yes(constant.value.span))), |this| { + this.with_parent(parent, |this| visit::walk_anon_const(this, constant)) + }); } #[instrument(level = "debug", skip(self))] @@ -435,10 +629,8 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { self.visit_macro_invoc(expr.id); self.visit_invoc(expr.id); } - ExprKind::Closure(..) | ExprKind::Gen(..) => { - let def = self.create_def(expr.id, None, DefKind::Closure, expr.span).def_id(); - self.with_parent(def, |this| visit::walk_expr(this, expr)); - } + ExprKind::Closure(closure) => self.create_closure(expr, closure.constness), + ExprKind::Gen(..) => self.create_closure(expr, Const::No), _ => visit::walk_expr(self, expr), } } diff --git a/compiler/rustc_resolve/src/diagnostics/mod.rs b/compiler/rustc_resolve/src/diagnostics/mod.rs index 9de2a682dc1fd..ff8f50bf128f9 100644 --- a/compiler/rustc_resolve/src/diagnostics/mod.rs +++ b/compiler/rustc_resolve/src/diagnostics/mod.rs @@ -1769,3 +1769,54 @@ pub(crate) enum UnusedImportsSugg { num_to_remove: usize, }, } + +#[derive(Diagnostic)] +#[diag("redundant `const` fn marker in const impl")] +pub(crate) struct ImplFnConst { + #[primary_span] + #[suggestion("remove the `const`", code = "", applicability = "machine-applicable")] + pub span: Span, + #[label("this declares all associated functions implicitly const")] + pub parent_constness: Span, +} + +#[derive(Diagnostic)] +#[diag("functions in {$in_impl -> + [true] trait impls + *[false] traits + } cannot be declared {$constness}", code = E0379)] +pub(crate) struct TraitFnConst { + #[primary_span] + #[label( + "functions in {$in_impl -> + [true] trait impls + *[false] traits + } cannot be {$constness}" + )] + pub span: Span, + pub in_impl: bool, + #[label("this declares all associated functions implicitly {$constness}")] + pub const_context_label: Option, + #[suggestion( + "remove the `{$constness}`{$requires_multiple_changes -> + [true] {\" ...\"} + *[false] {\"\"} + }", + code = "" + )] + pub remove_const_sugg: (Span, Applicability), + pub requires_multiple_changes: bool, + #[suggestion( + "... and declare the impl to be {$constness} instead", + code = "{constness} ", + applicability = "maybe-incorrect" + )] + pub make_impl_const_sugg: Option, + #[suggestion( + "... and declare the trait to be {$constness} instead", + code = "{constness} ", + applicability = "maybe-incorrect" + )] + pub make_trait_const_sugg: Option, + pub constness: &'static str, +} diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 111eae6a4134f..c61a392e6d282 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -190,6 +190,23 @@ struct InvocationParent { impl_trait_context: ImplTraitContext, in_attr: bool, owner: NodeId, + pub(crate) const_owner: Option<(ConstOwner, ast::Const)>, +} + +#[derive(Copy, Debug, Clone)] +enum ConstOwner { + TraitImpl { + polarity: ast::ImplPolarity, + trait_ref_span: Span, + }, + Trait { + vis: Span, + }, + InherentImpl, + /// Const and nonconst fns or methods. + Fn, + /// Anon consts, const blocks, free consts, assoc consts, ... + Const, } impl InvocationParent { @@ -198,6 +215,7 @@ impl InvocationParent { impl_trait_context: ImplTraitContext::Existential, in_attr: false, owner: CRATE_NODE_ID, + const_owner: None, }; } diff --git a/tests/ui/parser/fn-header-semantic-fail.stderr b/tests/ui/parser/fn-header-semantic-fail.stderr index 17e880c3a79d9..44446531933a6 100644 --- a/tests/ui/parser/fn-header-semantic-fail.stderr +++ b/tests/ui/parser/fn-header-semantic-fail.stderr @@ -1,12 +1,3 @@ -error: functions cannot be both `const` and `async` - --> $DIR/fn-header-semantic-fail.rs:10:5 - | -LL | const async unsafe extern "C" fn ff5() {} - | ^^^^^-^^^^^------------------------------ - | | | - | | `async` because of this - | `const` because of this - error[E0379]: functions in traits cannot be declared const --> $DIR/fn-header-semantic-fail.rs:16:9 | @@ -25,15 +16,6 @@ LL | const async unsafe extern "C" fn ft5(); | functions in traits cannot be const | help: remove the `const` -error: functions cannot be both `const` and `async` - --> $DIR/fn-header-semantic-fail.rs:18:9 - | -LL | const async unsafe extern "C" fn ft5(); - | ^^^^^-^^^^^---------------------------- - | | | - | | `async` because of this - | `const` because of this - error[E0379]: functions in trait impls cannot be declared const --> $DIR/fn-header-semantic-fail.rs:27:9 | @@ -52,6 +34,24 @@ LL | const async unsafe extern "C" fn ft5() {} | functions in trait impls cannot be const | help: remove the `const` +error: functions cannot be both `const` and `async` + --> $DIR/fn-header-semantic-fail.rs:10:5 + | +LL | const async unsafe extern "C" fn ff5() {} + | ^^^^^-^^^^^------------------------------ + | | | + | | `async` because of this + | `const` because of this + +error: functions cannot be both `const` and `async` + --> $DIR/fn-header-semantic-fail.rs:18:9 + | +LL | const async unsafe extern "C" fn ft5(); + | ^^^^^-^^^^^---------------------------- + | | | + | | `async` because of this + | `const` because of this + error: functions cannot be both `const` and `async` --> $DIR/fn-header-semantic-fail.rs:29:9 | diff --git a/tests/ui/traits/const-traits/const-closure-in-non-const-trait-impl-method.stderr b/tests/ui/traits/const-traits/const-closure-in-non-const-trait-impl-method.stderr index 15bc5b8458d80..f16c0481800eb 100644 --- a/tests/ui/traits/const-traits/const-closure-in-non-const-trait-impl-method.stderr +++ b/tests/ui/traits/const-traits/const-closure-in-non-const-trait-impl-method.stderr @@ -18,7 +18,7 @@ error: cannot use `const` closures outside of const contexts --> $DIR/const-closure-in-non-const-trait-impl-method.rs:13:9 | LL | const move || {} - | ^^^^^^^^^^^^^ + | ^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/const-closure-in-non-const-trait-method.stderr b/tests/ui/traits/const-traits/const-closure-in-non-const-trait-method.stderr index dd728840b8252..281da9ef559c9 100644 --- a/tests/ui/traits/const-traits/const-closure-in-non-const-trait-method.stderr +++ b/tests/ui/traits/const-traits/const-closure-in-non-const-trait-method.stderr @@ -11,7 +11,7 @@ error: cannot use `const` closures outside of const contexts --> $DIR/const-closure-in-non-const-trait-method.rs:8:10 | LL | (const || {})() - | ^^^^^^^^ + | ^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr b/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr index 7befeec496d80..f5521b90cc2d9 100644 --- a/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr +++ b/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr @@ -2,7 +2,7 @@ error: cannot use `const` closures outside of const contexts --> $DIR/non-const-op-const-closure-non-const-outer.rs:14:6 | LL | (const || { (()).foo() })(); - | ^^^^^^^^ + | ^^^^^ error: aborting due to 1 previous error