diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 4de9d61e7f752..d1f5dd89bd822 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3097,6 +3097,7 @@ impl CoroutineKind { #[derive(Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable, Debug)] #[derive(HashStable_Generic, Walkable)] pub enum Const { + Comptime(Span), Yes(Span), No, } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index fed4eb1b0ca41..b02ea4c548f2f 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1603,6 +1603,7 @@ impl<'hir> LoweringContext<'_, 'hir> { pub(super) fn lower_constness(&mut self, c: Const) -> hir::Constness { match c { + Const::Comptime(_) => hir::Constness::Comptime, Const::Yes(_) => hir::Constness::Const, 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 c203e5426b1e4..9eeadea84fc41 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -637,6 +637,7 @@ impl<'a> AstValidator<'a> { None => (), } match constness { + Const::Comptime(span) => report_err(span, "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 21b14f1610779..7f71eca41cfbb 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -2109,6 +2109,7 @@ impl<'a> State<'a> { match s { ast::Const::No => {} ast::Const::Yes(_) => self.word_nbsp("const"), + ast::Const::Comptime(_) => self.word_nbsp("comptime"), } } diff --git a/compiler/rustc_attr_parsing/src/attributes/semantics.rs b/compiler/rustc_attr_parsing/src/attributes/semantics.rs index d7f624832971f..0827bcf1bb0a7 100644 --- a/compiler/rustc_attr_parsing/src/attributes/semantics.rs +++ b/compiler/rustc_attr_parsing/src/attributes/semantics.rs @@ -7,3 +7,14 @@ impl NoArgsAttributeParser for MayDangleParser { const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs` 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), + ]); + const CREATE: fn(Span) -> AttributeKind = AttributeKind::Comptime; +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 4789f27785cb9..5058689577ebc 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -58,7 +58,7 @@ use crate::attributes::rustc_internal::{ RustcLayoutScalarValidRangeEndParser, RustcLayoutScalarValidRangeStartParser, RustcMainParser, RustcObjectLifetimeDefaultParser, RustcSimdMonomorphizeLaneLimitParser, }; -use crate::attributes::semantics::MayDangleParser; +use crate::attributes::semantics::{ComptimeParser, MayDangleParser}; use crate::attributes::stability::{ BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser, }; @@ -216,6 +216,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs index 530d8d4b1fa62..8cdb73190175b 100644 --- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs @@ -32,8 +32,8 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness { hir::Node::Expr(e) if let hir::ExprKind::Closure(c) = e.kind => c.constness, _ => { if let Some(fn_kind) = node.fn_kind() { - if fn_kind.constness() == hir::Constness::Const { - return hir::Constness::Const; + if fn_kind.constness() != hir::Constness::NotConst { + return fn_kind.constness(); } // If the function itself is not annotated with `const`, it may still be a `const fn` diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 4d50b9683fc57..ea4e6177143c4 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -1390,6 +1390,11 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_force_inline, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing, EncodeCrossCrate::Yes, "`#[rustc_force_inline]` forces a free function to be inlined" ), + rustc_attr!( + rustc_comptime, Normal, template!(Word), ErrorFollowing, + EncodeCrossCrate::Yes, + "the `#[rustc_comptime]` attribute is just used to avoid adding syntax for `comptime fn`" + ), // ========================================================================== // Internal attributes, Testing: diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 7ddd71c346006..b5e6fde281650 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -479,6 +479,9 @@ pub enum AttributeKind { /// Represents `#[cold]`. Cold(Span), + /// Represents `#[rustc_comptime]` + Comptime(Span), + /// Represents `#[rustc_confusables]`. Confusables { symbols: ThinVec, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 2ccfdc2ad983d..f3f4c6a233fe7 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -28,6 +28,7 @@ impl AttributeKind { BodyStability { .. } => No, Coinductive(..) => No, Cold(..) => No, + Comptime(..) => Yes, Confusables { .. } => Yes, ConstContinue(..) => No, ConstStability { .. } => Yes, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 786280c24c119..9e65d721e7fc6 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2264,10 +2264,12 @@ pub enum ConstContext { /// - Array length expressions /// - Enum discriminants /// - Const generics - /// - /// For the most part, other contexts are treated just like a regular `const`, so they are - /// lumped into the same category. - Const { inline: bool }, + Const { + /// For backwards compatibility `const` items allow + /// calls to `const fn` to get promoted. + /// We forbid that in comptime fns and inline consts. + allow_const_fn_promotion: bool, + }, } impl ConstContext { @@ -4225,6 +4227,7 @@ impl fmt::Display for Safety { #[derive(Copy, Clone, PartialEq, Eq, Debug, Encodable, Decodable, HashStable_Generic)] pub enum Constness { + Comptime, Const, NotConst, } @@ -4232,6 +4235,7 @@ pub enum Constness { impl fmt::Display for Constness { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(match *self { + Self::Comptime => "comptime", Self::Const => "const", Self::NotConst => "non-const", }) diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 308e604deb40c..f1644a15fc742 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -2567,6 +2567,7 @@ impl<'a> State<'a> { match s { hir::Constness::NotConst => {} hir::Constness::Const => self.word_nbsp("const"), + hir::Constness::Comptime => self.word_nbsp("comptime"), } } diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index f59fcab46661f..367ea383bba55 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -917,7 +917,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; } - let host = match self.tcx.hir_body_const_context(self.body_id) { + let const_context = self.tcx.hir_body_const_context(self.body_id); + + if let hir::Constness::Comptime = self.tcx.constness(callee_did) { + match const_context { + Some(hir::ConstContext::Const { .. } | hir::ConstContext::Static(_)) => {} + Some(hir::ConstContext::ConstFn) | None => { + self.dcx().span_err(span, "comptime fns can only be called at compile time"); + } + } + } + + let host = match const_context { Some(hir::ConstContext::Const { .. } | hir::ConstContext::Static(_)) => { ty::BoundConstness::Const } diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index a882ee4f2b92e..e9c0cf0843af7 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -180,6 +180,7 @@ fixed_size_enum! { hir::Constness { ( NotConst ) ( Const ) + ( Comptime ) } } diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 430cd329408f5..57412342e57e8 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -314,12 +314,18 @@ impl<'tcx> TyCtxt<'tcx> { pub fn hir_body_const_context(self, def_id: LocalDefId) -> Option { let def_id = def_id.into(); let ccx = match self.hir_body_owner_kind(def_id) { - BodyOwnerKind::Const { inline } => ConstContext::Const { inline }, + BodyOwnerKind::Const { inline } => { + ConstContext::Const { allow_const_fn_promotion: !inline } + } BodyOwnerKind::Static(mutability) => ConstContext::Static(mutability), BodyOwnerKind::Fn if self.is_constructor(def_id) => return None, BodyOwnerKind::Fn | BodyOwnerKind::Closure if self.is_const_fn(def_id) => { - ConstContext::ConstFn + if self.constness(def_id) == rustc_hir::Constness::Comptime { + ConstContext::Const { allow_const_fn_promotion: false } + } else { + ConstContext::ConstFn + } } BodyOwnerKind::Fn if self.is_const_default_method(def_id) => ConstContext::ConstFn, BodyOwnerKind::Fn | BodyOwnerKind::Closure | BodyOwnerKind::GlobalAsm => return None, diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 510c546f82a4e..823b6002bee7c 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -247,6 +247,7 @@ impl<'tcx> rustc_type_ir::inherent::AdtDef> for AdtDef<'tcx> { fn destructor(self, tcx: TyCtxt<'tcx>) -> Option { Some(match tcx.constness(self.destructor(tcx)?.did) { + hir::Constness::Comptime => todo!("FIXME(comptime)"), hir::Constness::Const => AdtDestructorKind::Const, hir::Constness::NotConst => AdtDestructorKind::NotConst, }) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index faa8420c20d0e..d18459a89322b 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2138,7 +2138,7 @@ impl<'tcx> TyCtxt<'tcx> { matches!( self.def_kind(def_id), DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Closure - ) && self.constness(def_id) == hir::Constness::Const + ) && self.constness(def_id) != hir::Constness::NotConst } /// Whether this item is conditionally constant for the purposes of the diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index da5814c6b4cce..f40703ee1fede 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -668,7 +668,10 @@ impl<'tcx> Validator<'_, 'tcx> { // backwards compatibility reason to allow more promotion inside of them. let promote_all_fn = matches!( self.const_kind, - Some(hir::ConstContext::Static(_) | hir::ConstContext::Const { inline: false }) + Some( + hir::ConstContext::Static(_) + | hir::ConstContext::Const { allow_const_fn_promotion: false } + ) ); if !promote_all_fn { return Err(Unpromotable); diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 1862900077f0f..8f397651a7968 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -143,6 +143,11 @@ parse_compound_assignment_expression_in_let = can't reassign to an uninitialized .suggestion = initialize the variable .help = if you meant to overwrite, remove the `let` binding +parse_const_comptime_fn = a function cannot be both `comptime` and `const` + .suggestion = remove the `const` + .label = `comptime` because of this + .note = `const` implies the function can be called at runtime, too + parse_const_generic_without_braces = expressions must be enclosed in braces to be used as const generic arguments .suggestion = enclose the `const` expression in braces diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index a35c5c304d95e..7f68d2b5a2025 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1686,6 +1686,16 @@ pub(crate) struct UnexpectedIfWithIf( pub Span, ); +#[derive(Diagnostic)] +#[diag(parse_const_comptime_fn)] +pub(crate) struct ConstComptimeFn { + #[primary_span] + #[suggestion(applicability = "machine-applicable", code = "")] + pub span: Span, + #[label] + pub attr_span: Span, +} + #[derive(Diagnostic)] #[diag(parse_maybe_fn_typo_with_impl)] pub(crate) struct FnTypoWithImpl { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 599ec80e0a387..dcc0d797da239 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2449,7 +2449,20 @@ impl<'a> Parser<'a> { case: Case, ) -> PResult<'a, (Ident, FnSig, Generics, Option>, Option>)> { let fn_span = self.token.span; - let header = self.parse_fn_front_matter(vis, case, FrontMatterParsingMode::Function)?; // `const ... fn` + let mut header = self.parse_fn_front_matter(vis, case, FrontMatterParsingMode::Function)?; // `const ... fn` + if let Some(attr) = attrs.iter().find(|attr| attr.has_name(sym::rustc_comptime)) { + match std::mem::replace(&mut header.constness, Const::Comptime(attr.span)) { + Const::Comptime(_) => unreachable!("there is no syntax for comptime fn"), + // A function can't be `const` and `comptime` at the same time + Const::Yes(span) => { + return Err(self + .dcx() + .create_err(errors::ConstComptimeFn { span, attr_span: attr.span })); + } + // Good + Const::No => {} + } + } let ident = self.parse_ident()?; // `foo` let mut generics = self.parse_generics()?; // `<'a, T, ...>` let decl = match self.parse_fn_decl(&fn_parse_mode, AllowPlus::Yes, RecoverReturnSign::Yes) @@ -2786,7 +2799,7 @@ 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::Yes(sp) => Some(WrongKw::Duplicated(sp)), + Const::Comptime(sp) | Const::Yes(sp) => Some(WrongKw::Duplicated(sp)), Const::No => { recover_constness = Const::Yes(self.token.span); match parsing_mode { diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 347e103af9378..fca281d835dcf 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -232,6 +232,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::Marker(..) | AttributeKind::SkipDuringMethodDispatch { .. } | AttributeKind::Coinductive(..) + | AttributeKind::Comptime(..) | AttributeKind::DenyExplicitImpl(..) | AttributeKind::DoNotImplementViaObject(..) | AttributeKind::SpecializationTrait(..) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d0704f597c715..2f52d8fee4fd6 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1907,6 +1907,7 @@ 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_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs index d661c585d68e8..94138d1ad9861 100644 --- a/compiler/rustc_trait_selection/src/traits/effects.rs +++ b/compiler/rustc_trait_selection/src/traits/effects.rs @@ -435,6 +435,7 @@ fn evaluate_host_effect_for_destruct_goal<'tcx>( .map(|field| ty::TraitRef::new(tcx, destruct_def_id, [field.ty(tcx, args)])) .collect(); match adt_def.destructor(tcx).map(|dtor| tcx.constness(dtor.did)) { + Some(hir::Constness::Comptime) => todo!("FIXME(comptime)"), // `Drop` impl exists, but it's not const. Type cannot be `[const] Destruct`. Some(hir::Constness::NotConst) => return Err(EvaluationFailure::NoSolution), // `Drop` impl exists, and it's const. Require `Ty: [const] Drop` to hold. @@ -530,6 +531,8 @@ fn evaluate_host_effect_for_fn_goal<'tcx>( }; match tcx.constness(def) { + // FIXME(comptime) + hir::Constness::Comptime => Err(EvaluationFailure::NoSolution), hir::Constness::Const => Ok(tcx .const_conditions(def) .instantiate(tcx, args) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 337429a6248d9..6f7a8c3784d47 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1445,14 +1445,18 @@ pub(crate) fn print_constness_with_space( const_stab: Option, ) -> &'static str { match c { - hir::Constness::Const => match (overall_stab, const_stab) { + hir::Constness::Comptime | hir::Constness::Const => match (overall_stab, const_stab) { // const stable... (_, Some(ConstStability { level: StabilityLevel::Stable { .. }, .. })) // ...or when feature(staged_api) is not set... | (_, None) // ...or when const unstable, but overall unstable too | (None, Some(ConstStability { level: StabilityLevel::Unstable { .. }, .. })) => { - "const " + match c { + hir::Constness::Comptime => "comptime ", + hir::Constness::Const => "const ", + _ => unreachable!(), + } } // const unstable (and overall stable) (Some(_), Some(ConstStability { level: StabilityLevel::Unstable { .. }, .. })) => "", diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs index 3a2975024a33b..b6e100ffdea17 100644 --- a/src/tools/rustfmt/src/utils.rs +++ b/src/tools/rustfmt/src/utils.rs @@ -86,6 +86,7 @@ pub(crate) fn format_coro(coroutine_kind: &ast::CoroutineKind) -> &'static str { #[inline] pub(crate) fn format_constness(constness: ast::Const) -> &'static str { match constness { + ast::Const::Comptime(..) => "comptime ", ast::Const::Yes(..) => "const ", ast::Const::No => "", } @@ -94,6 +95,7 @@ pub(crate) fn format_constness(constness: ast::Const) -> &'static str { #[inline] pub(crate) fn format_constness_right(constness: ast::Const) -> &'static str { match constness { + ast::Const::Comptime(..) => " comptime", ast::Const::Yes(..) => " const", ast::Const::No => "", } diff --git a/tests/ui/comptime/const_comptime.rs b/tests/ui/comptime/const_comptime.rs new file mode 100644 index 0000000000000..827e4dfcf545b --- /dev/null +++ b/tests/ui/comptime/const_comptime.rs @@ -0,0 +1,7 @@ +#![feature(rustc_attrs)] + +#[rustc_comptime] +const fn foo() {} +//~^ ERROR a function cannot be both `comptime` and `const` + +fn main() {} diff --git a/tests/ui/comptime/const_comptime.stderr b/tests/ui/comptime/const_comptime.stderr new file mode 100644 index 0000000000000..7d7d13a6291f8 --- /dev/null +++ b/tests/ui/comptime/const_comptime.stderr @@ -0,0 +1,10 @@ +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` + +error: aborting due to 1 previous error + diff --git a/tests/ui/comptime/not_callable.rs b/tests/ui/comptime/not_callable.rs new file mode 100644 index 0000000000000..456b9fe6ee601 --- /dev/null +++ b/tests/ui/comptime/not_callable.rs @@ -0,0 +1,24 @@ +#![feature(rustc_attrs, const_trait_impl)] + +#[rustc_comptime] +fn foo() {} + +fn main() { + // Ok + const { foo() }; + // Not ok + foo(); + //~^ ERROR: comptime fns can only be called at compile time +} + +const fn bar() { + // Not ok + foo(); + //~^ ERROR: comptime fns can only be called at compile time +} + +#[rustc_comptime] +fn baz() { + // Ok + foo(); +} diff --git a/tests/ui/comptime/not_callable.stderr b/tests/ui/comptime/not_callable.stderr new file mode 100644 index 0000000000000..675c2aee48b84 --- /dev/null +++ b/tests/ui/comptime/not_callable.stderr @@ -0,0 +1,14 @@ +error: comptime fns can only be called at compile time + --> $DIR/not_callable.rs:10:5 + | +LL | foo(); + | ^^^^^ + +error: comptime fns can only be called at compile time + --> $DIR/not_callable.rs:16:5 + | +LL | foo(); + | ^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/comptime/trait_bounds.rs b/tests/ui/comptime/trait_bounds.rs new file mode 100644 index 0000000000000..3df2f41558fcc --- /dev/null +++ b/tests/ui/comptime/trait_bounds.rs @@ -0,0 +1,25 @@ +#![feature(rustc_attrs, const_trait_impl)] + +const trait Trait { + fn method() {} +} + +#[rustc_comptime] +fn always_const() { + T::method() +} + +#[rustc_comptime] +fn conditionally_const() { + //~^ ERROR: `[const]` is not allowed here + T::method() + //~^ ERROR: `T: const Trait` is not satisfied +} + +#[rustc_comptime] +fn non_const() { + T::method() + //~^ ERROR: `T: const Trait` is not satisfied +} + +fn main() {} diff --git a/tests/ui/comptime/trait_bounds.stderr b/tests/ui/comptime/trait_bounds.stderr new file mode 100644 index 0000000000000..c5a03af2c0c2c --- /dev/null +++ b/tests/ui/comptime/trait_bounds.stderr @@ -0,0 +1,27 @@ +error: `[const]` is not allowed here + --> $DIR/trait_bounds.rs:13:27 + | +LL | fn conditionally_const() { + | ^^^^^^^ + | +note: this function is not `const`, so it cannot have `[const]` trait bounds + --> $DIR/trait_bounds.rs:13:4 + | +LL | fn conditionally_const() { + | ^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `T: const Trait` is not satisfied + --> $DIR/trait_bounds.rs:15:5 + | +LL | T::method() + | ^ + +error[E0277]: the trait bound `T: const Trait` is not satisfied + --> $DIR/trait_bounds.rs:21:5 + | +LL | T::method() + | ^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/comptime/trait_comptime.rs b/tests/ui/comptime/trait_comptime.rs new file mode 100644 index 0000000000000..a42e85c49f702 --- /dev/null +++ b/tests/ui/comptime/trait_comptime.rs @@ -0,0 +1,26 @@ +#![feature(rustc_attrs)] + +trait Foo { + #[rustc_comptime] + //~^ ERROR: cannot be used on required trait methods + fn foo(); + + #[rustc_comptime] + //~^ ERROR: cannot be used on provided trait methods + fn bar() {} +} + +struct Bar; + +impl Bar { + #[rustc_comptime] + fn foo() {} +} + +impl Foo for Bar { + #[rustc_comptime] + //~^ ERROR: cannot be used on trait methods + fn foo() {} +} + +fn main() {} diff --git a/tests/ui/comptime/trait_comptime.stderr b/tests/ui/comptime/trait_comptime.stderr new file mode 100644 index 0000000000000..77ff09674d2bd --- /dev/null +++ b/tests/ui/comptime/trait_comptime.stderr @@ -0,0 +1,26 @@ +error: `#[rustc_comptime]` attribute cannot be used on required trait methods + --> $DIR/trait_comptime.rs:4:5 + | +LL | #[rustc_comptime] + | ^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_comptime]` can be applied to functions and inherent methods + +error: `#[rustc_comptime]` attribute cannot be used on provided trait methods + --> $DIR/trait_comptime.rs:8:5 + | +LL | #[rustc_comptime] + | ^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_comptime]` can be applied to functions and inherent methods + +error: `#[rustc_comptime]` attribute cannot be used on trait methods in impl blocks + --> $DIR/trait_comptime.rs:21:5 + | +LL | #[rustc_comptime] + | ^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_comptime]` can be applied to functions and inherent methods + +error: aborting due to 3 previous errors +