Skip to content

Commit 405e50f

Browse files
committed
Check comptime fns
1 parent c8f3769 commit 405e50f

File tree

17 files changed

+139
-5
lines changed

17 files changed

+139
-5
lines changed

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
@@ -32,8 +32,8 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
3232
hir::Node::Expr(e) if let hir::ExprKind::Closure(c) = e.kind => c.constness,
3333
_ => {
3434
if let Some(fn_kind) = node.fn_kind() {
35-
if fn_kind.constness() == hir::Constness::Const {
36-
return hir::Constness::Const;
35+
if fn_kind.constness() != hir::Constness::NotConst {
36+
return fn_kind.constness();
3737
}
3838

3939
// 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
@@ -1390,6 +1390,11 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
13901390
rustc_force_inline, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing, EncodeCrossCrate::Yes,
13911391
"`#[rustc_force_inline]` forces a free function to be inlined"
13921392
),
1393+
rustc_attr!(
1394+
rustc_comptime, Normal, template!(Word), ErrorFollowing,
1395+
EncodeCrossCrate::Yes,
1396+
"the `#[rustc_comptime]` attribute is just used to avoid adding syntax for `comptime fn`"
1397+
),
13931398

13941399
// ==========================================================================
13951400
// 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
@@ -479,6 +479,9 @@ pub enum AttributeKind {
479479
/// Represents `#[cold]`.
480480
Cold(Span),
481481

482+
/// Represents `#[rustc_comptime]`
483+
Comptime(Span),
484+
482485
/// Represents `#[rustc_confusables]`.
483486
Confusables {
484487
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(..) => Yes,
3132
Confusables { .. } => Yes,
3233
ConstContinue(..) => No,
3334
ConstStability { .. } => Yes,

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2138,7 +2138,7 @@ impl<'tcx> TyCtxt<'tcx> {
21382138
matches!(
21392139
self.def_kind(def_id),
21402140
DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Closure
2141-
) && self.constness(def_id) == hir::Constness::Const
2141+
) && self.constness(def_id) != hir::Constness::NotConst
21422142
}
21432143

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

compiler/rustc_parse/messages.ftl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,11 @@ parse_compound_assignment_expression_in_let = can't reassign to an uninitialized
143143
.suggestion = initialize the variable
144144
.help = if you meant to overwrite, remove the `let` binding
145145
146+
parse_const_comptime_fn = a function cannot be both `comptime` and `const`
147+
.suggestion = remove the `const`
148+
.label = `comptime` because of this
149+
.note = `const` implies the function can be called at runtime, too
150+
146151
parse_const_generic_without_braces = expressions must be enclosed in braces to be used as const generic arguments
147152
.suggestion = enclose the `const` expression in braces
148153

compiler/rustc_parse/src/errors.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1686,6 +1686,16 @@ pub(crate) struct UnexpectedIfWithIf(
16861686
pub Span,
16871687
);
16881688

1689+
#[derive(Diagnostic)]
1690+
#[diag(parse_const_comptime_fn)]
1691+
pub(crate) struct ConstComptimeFn {
1692+
#[primary_span]
1693+
#[suggestion(applicability = "machine-applicable", code = "")]
1694+
pub span: Span,
1695+
#[label]
1696+
pub attr_span: Span,
1697+
}
1698+
16891699
#[derive(Diagnostic)]
16901700
#[diag(parse_maybe_fn_typo_with_impl)]
16911701
pub(crate) struct FnTypoWithImpl {

compiler/rustc_parse/src/parser/item.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2449,7 +2449,20 @@ impl<'a> Parser<'a> {
24492449
case: Case,
24502450
) -> PResult<'a, (Ident, FnSig, Generics, Option<Box<FnContract>>, Option<Box<Block>>)> {
24512451
let fn_span = self.token.span;
2452-
let header = self.parse_fn_front_matter(vis, case, FrontMatterParsingMode::Function)?; // `const ... fn`
2452+
let mut header = self.parse_fn_front_matter(vis, case, FrontMatterParsingMode::Function)?; // `const ... fn`
2453+
if let Some(attr) = attrs.iter().find(|attr| attr.has_name(sym::rustc_comptime)) {
2454+
match std::mem::replace(&mut header.constness, Const::Comptime(attr.span)) {
2455+
Const::Comptime(_) => unreachable!("there is no syntax for comptime fn"),
2456+
// A function can't be `const` and `comptime` at the same time
2457+
Const::Yes(span) => {
2458+
return Err(self
2459+
.dcx()
2460+
.create_err(errors::ConstComptimeFn { span, attr_span: attr.span }));
2461+
}
2462+
// Good
2463+
Const::No => {}
2464+
}
2465+
}
24532466
let ident = self.parse_ident()?; // `foo`
24542467
let mut generics = self.parse_generics()?; // `<'a, T, ...>`
24552468
let decl = match self.parse_fn_decl(&fn_parse_mode, AllowPlus::Yes, RecoverReturnSign::Yes)

0 commit comments

Comments
 (0)