Skip to content

Commit 47a255d

Browse files
committed
Check comptime fns
1 parent 5888266 commit 47a255d

File tree

17 files changed

+156
-9
lines changed

17 files changed

+156
-9
lines changed

compiler/rustc_ast_lowering/messages.ftl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ ast_lowering_clobber_abi_not_supported =
5050
5151
ast_lowering_closure_cannot_be_static = closures cannot be static
5252
53+
ast_lowering_const_comptime_fn = a function cannot be both `comptime` and `const`
54+
.suggestion = remove the `const`
55+
.label = `comptime` because of this
56+
.note = `const` implies the function can be called at runtime, too
57+
5358
ast_lowering_coroutine_too_many_parameters =
5459
too many parameters for a coroutine (expected 0 or 1 parameters)
5560

compiler/rustc_ast_lowering/src/errors.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,16 @@ use rustc_errors::codes::*;
33
use rustc_macros::{Diagnostic, Subdiagnostic};
44
use rustc_span::{Ident, Span, Symbol};
55

6+
#[derive(Diagnostic)]
7+
#[diag(ast_lowering_const_comptime_fn)]
8+
pub(crate) struct ConstComptimeFn {
9+
#[primary_span]
10+
#[suggestion(applicability = "machine-applicable", code = "")]
11+
pub span: Span,
12+
#[label]
13+
pub attr_span: Span,
14+
}
15+
616
#[derive(Diagnostic)]
717
#[diag(ast_lowering_generic_type_with_parentheses, code = E0214)]
818
pub(crate) struct GenericTypeWithParentheses {

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use super::{
2323
AstOwner, FnDeclKind, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode,
2424
RelaxedBoundForbiddenReason, RelaxedBoundPolicy, ResolverAstLoweringExt,
2525
};
26+
use crate::errors::ConstComptimeFn;
2627

2728
pub(super) struct ItemLowerer<'a, 'hir> {
2829
pub(super) tcx: TyCtxt<'hir>,
@@ -1537,12 +1538,23 @@ impl<'hir> LoweringContext<'_, 'hir> {
15371538
safety.into()
15381539
};
15391540

1540-
hir::FnHeader {
1541-
safety,
1542-
asyncness,
1543-
constness: self.lower_constness(h.constness),
1544-
abi: self.lower_extern(h.ext),
1541+
let mut constness = self.lower_constness(h.constness);
1542+
if let Some(&attr_span) = find_attr!(attrs, AttributeKind::Comptime(span) => span) {
1543+
match std::mem::replace(&mut constness, rustc_hir::Constness::Comptime) {
1544+
rustc_hir::Constness::Comptime => {
1545+
unreachable!("lower_constness cannot produce comptime")
1546+
}
1547+
// A function can't be `const` and `comptime` at the same time
1548+
rustc_hir::Constness::Const => {
1549+
let Const::Yes(span) = h.constness else { unreachable!() };
1550+
self.dcx().emit_err(ConstComptimeFn { span, attr_span });
1551+
}
1552+
// Good
1553+
rustc_hir::Constness::NotConst => {}
1554+
}
15451555
}
1556+
1557+
hir::FnHeader { safety, asyncness, constness, abi: self.lower_extern(h.ext) }
15461558
}
15471559

15481560
pub(super) fn lower_abi(&mut self, abi_str: StrLit) -> ExternAbi {

compiler/rustc_attr_parsing/src/attributes/semantics.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,14 @@ impl<S: Stage> NoArgsAttributeParser<S> for MayDangleParser {
77
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs`
88
const CREATE: fn(span: Span) -> AttributeKind = AttributeKind::MayDangle;
99
}
10+
11+
pub(crate) struct ComptimeParser;
12+
impl<S: Stage> NoArgsAttributeParser<S> for ComptimeParser {
13+
const PATH: &[Symbol] = &[sym::rustc_comptime];
14+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
15+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
16+
Allow(Target::Method(MethodKind::Inherent)),
17+
Allow(Target::Fn),
18+
]);
19+
const CREATE: fn(Span) -> AttributeKind = AttributeKind::Comptime;
20+
}

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ use crate::attributes::rustc_internal::{
5858
RustcLayoutScalarValidRangeEndParser, RustcLayoutScalarValidRangeStartParser, RustcMainParser,
5959
RustcObjectLifetimeDefaultParser, RustcSimdMonomorphizeLaneLimitParser,
6060
};
61-
use crate::attributes::semantics::MayDangleParser;
61+
use crate::attributes::semantics::{ComptimeParser, MayDangleParser};
6262
use crate::attributes::stability::{
6363
BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser,
6464
};
@@ -216,6 +216,7 @@ attribute_parsers!(
216216
Single<WithoutArgs<AutomaticallyDerivedParser>>,
217217
Single<WithoutArgs<CoinductiveParser>>,
218218
Single<WithoutArgs<ColdParser>>,
219+
Single<WithoutArgs<ComptimeParser>>,
219220
Single<WithoutArgs<ConstContinueParser>>,
220221
Single<WithoutArgs<ConstStabilityIndirectParser>>,
221222
Single<WithoutArgs<CoroutineParser>>,

compiler/rustc_const_eval/src/const_eval/fn_queries.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
3434
hir::Node::Item(i) if let hir::ItemKind::Impl(impl_) = i.kind => impl_.constness,
3535
_ => {
3636
if let Some(fn_kind) = node.fn_kind() {
37-
if fn_kind.constness() == hir::Constness::Const {
38-
return hir::Constness::Const;
37+
if fn_kind.constness() != hir::Constness::NotConst {
38+
return fn_kind.constness();
3939
}
4040

4141
// If the function itself is not annotated with `const`, it may still be a `const fn`

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,6 +1407,11 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
14071407
rustc_force_inline, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing, EncodeCrossCrate::Yes,
14081408
"`#[rustc_force_inline]` forces a free function to be inlined"
14091409
),
1410+
rustc_attr!(
1411+
rustc_comptime, Normal, template!(Word), ErrorFollowing,
1412+
EncodeCrossCrate::No,
1413+
"the `#[rustc_comptime]` attribute is just used to avoid adding syntax for `comptime fn`"
1414+
),
14101415

14111416
// ==========================================================================
14121417
// Internal attributes, Testing:

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,9 @@ pub enum AttributeKind {
491491
/// Represents `#[cold]`.
492492
Cold(Span),
493493

494+
/// Represents `#[rustc_comptime]`
495+
Comptime(Span),
496+
494497
/// Represents `#[rustc_confusables]`.
495498
Confusables {
496499
symbols: ThinVec<Symbol>,

compiler/rustc_hir/src/attrs/encode_cross_crate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ impl AttributeKind {
2828
BodyStability { .. } => No,
2929
Coinductive(..) => No,
3030
Cold(..) => No,
31+
Comptime(..) => No,
3132
Confusables { .. } => Yes,
3233
ConstContinue(..) => No,
3334
ConstStability { .. } => Yes,

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2137,7 +2137,10 @@ impl<'tcx> TyCtxt<'tcx> {
21372137
matches!(
21382138
self.def_kind(def_id),
21392139
DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Closure
2140-
) && self.constness(def_id) == hir::Constness::Const
2140+
) && match self.constness(def_id) {
2141+
hir::Constness::Comptime | hir::Constness::Const => true,
2142+
hir::Constness::NotConst => false,
2143+
}
21412144
}
21422145

21432146
/// Whether this item is conditionally constant for the purposes of the

0 commit comments

Comments
 (0)