Skip to content

Commit fecd998

Browse files
committed
Setup unstable feature bound attribute
1 parent a9fb610 commit fecd998

File tree

7 files changed

+123
-0
lines changed

7 files changed

+123
-0
lines changed

compiler/rustc_attr_data_structures/src/attributes.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,9 @@ pub enum AttributeKind {
417417
/// Represents `#[rustc_unsafe_specialization_marker]`.
418418
UnsafeSpecializationMarker(Span),
419419

420+
/// Represents `#[unstable_feature_bound]`.
421+
UnstableFeatureBound(ThinVec<(Symbol, Span)>),
422+
420423
/// Represents `#[used]`
421424
Used { used_by: UsedBy, span: Span },
422425
// tidy-alphabetical-end

compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,26 @@ impl<S: Stage> CombineAttributeParser<S> for AllowInternalUnstableParser {
2727
}
2828
}
2929

30+
pub(crate) struct UnstableFeatureBoundParser;
31+
impl<S: Stage> CombineAttributeParser<S> for UnstableFeatureBoundParser {
32+
const PATH: &'static [rustc_span::Symbol] = &[sym::unstable_feature_bound];
33+
type Item = (Symbol, Span);
34+
const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::UnstableFeatureBound(items);
35+
const TEMPLATE: AttributeTemplate = template!(Word, List: "feat1, feat2, ...");
36+
37+
fn extend<'c>(
38+
cx: &'c mut AcceptContext<'_, '_, S>,
39+
args: &'c ArgParser<'_>,
40+
) -> impl IntoIterator<Item = Self::Item> {
41+
if !cx.features().staged_api() {
42+
cx.emit_err(session_diagnostics::StabilityOutsideStd { span: cx.attr_span });
43+
}
44+
parse_unstable(cx, args, <Self as CombineAttributeParser<S>>::PATH[0])
45+
.into_iter()
46+
.zip(iter::repeat(cx.attr_span))
47+
}
48+
}
49+
3050
pub(crate) struct AllowConstFnUnstableParser;
3151
impl<S: Stage> CombineAttributeParser<S> for AllowConstFnUnstableParser {
3252
const PATH: &[Symbol] = &[sym::rustc_allow_const_fn_unstable];

compiler/rustc_passes/messages.ftl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,10 @@ passes_rustc_std_internal_symbol =
667667
attribute should be applied to functions or statics
668668
.label = not a function or static
669669
670+
passes_rustc_unstable_feature_bound =
671+
attribute should be applied to `impl` or free function outside of any `impl` or trait
672+
.label = not an `impl` or free function
673+
670674
passes_should_be_applied_to_fn =
671675
attribute should be applied to a function definition
672676
.label = {$on_crate ->

compiler/rustc_passes/src/check_attr.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
247247
&Attribute::Parsed(AttributeKind::FfiPure(attr_span)) => {
248248
self.check_ffi_pure(attr_span, attrs, target)
249249
}
250+
Attribute::Parsed(AttributeKind::UnstableFeatureBound(syms)) => {
251+
self.check_unstable_feature_bound(syms.first().unwrap().1, span, target)
252+
}
250253
Attribute::Parsed(
251254
AttributeKind::BodyStability { .. }
252255
| AttributeKind::ConstStabilityIndirect
@@ -2267,6 +2270,47 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
22672270
}
22682271
}
22692272

2273+
fn check_unstable_feature_bound(&self, attr_span: Span, span: Span, target: Target) {
2274+
match target {
2275+
// FIXME(staged_api): There's no reason we can't support more targets here. We're just
2276+
// being conservative to begin with.
2277+
Target::Fn | Target::Impl => {}
2278+
Target::ExternCrate
2279+
| Target::Use
2280+
| Target::Static
2281+
| Target::Const
2282+
| Target::Closure
2283+
| Target::Mod
2284+
| Target::ForeignMod
2285+
| Target::GlobalAsm
2286+
| Target::TyAlias
2287+
| Target::Enum
2288+
| Target::Variant
2289+
| Target::Struct
2290+
| Target::Field
2291+
| Target::Union
2292+
| Target::Trait
2293+
| Target::TraitAlias
2294+
| Target::Expression
2295+
| Target::Statement
2296+
| Target::Arm
2297+
| Target::AssocConst
2298+
| Target::Method(_)
2299+
| Target::AssocTy
2300+
| Target::ForeignFn
2301+
| Target::ForeignStatic
2302+
| Target::ForeignTy
2303+
| Target::GenericParam(_)
2304+
| Target::MacroDef
2305+
| Target::Param
2306+
| Target::PatField
2307+
| Target::ExprField
2308+
| Target::WherePredicate => {
2309+
self.tcx.dcx().emit_err(errors::RustcUnstableFeatureBound { attr_span, span });
2310+
}
2311+
}
2312+
}
2313+
22702314
fn check_rustc_std_internal_symbol(&self, attr_span: Span, span: Span, target: Target) {
22712315
match target {
22722316
Target::Fn | Target::Static | Target::ForeignFn | Target::ForeignStatic => {}

compiler/rustc_passes/src/errors.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,15 @@ pub(crate) struct RustcAllowConstFnUnstable {
686686
pub span: Span,
687687
}
688688

689+
#[derive(Diagnostic)]
690+
#[diag(passes_rustc_unstable_feature_bound)]
691+
pub(crate) struct RustcUnstableFeatureBound {
692+
#[primary_span]
693+
pub attr_span: Span,
694+
#[label]
695+
pub span: Span,
696+
}
697+
689698
#[derive(Diagnostic)]
690699
#[diag(passes_rustc_std_internal_symbol)]
691700
pub(crate) struct RustcStdInternalSymbol {
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#![allow(internal_features)]
2+
#![feature(staged_api)]
3+
#![stable(feature = "a", since = "1.1.1" )]
4+
5+
/// FIXME(tiif): we haven't allowed marking trait and impl method as
6+
/// unstable yet, but it should be possible.
7+
8+
#[stable(feature = "a", since = "1.1.1" )]
9+
pub trait Trait {
10+
#[unstable(feature = "feat", issue = "none" )]
11+
#[unstable_feature_bound(foo)]
12+
//~^ ERROR: attribute should be applied to `impl` or free function outside of any `impl` or trait
13+
fn foo();
14+
}
15+
16+
#[stable(feature = "a", since = "1.1.1" )]
17+
impl Trait for u8 {
18+
#[unstable_feature_bound(foo)]
19+
//~^ ERROR: attribute should be applied to `impl` or free function outside of any `impl` or trait
20+
fn foo() {}
21+
}
22+
23+
fn main() {}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: attribute should be applied to `impl` or free function outside of any `impl` or trait
2+
--> $DIR/unstable_inherent_method.rs:11:5
3+
|
4+
LL | #[unstable_feature_bound(foo)]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
LL |
7+
LL | fn foo();
8+
| --------- not an `impl` or free function
9+
10+
error: attribute should be applied to `impl` or free function outside of any `impl` or trait
11+
--> $DIR/unstable_inherent_method.rs:18:5
12+
|
13+
LL | #[unstable_feature_bound(foo)]
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15+
LL |
16+
LL | fn foo() {}
17+
| ----------- not an `impl` or free function
18+
19+
error: aborting due to 2 previous errors
20+

0 commit comments

Comments
 (0)