Skip to content

Commit e144c89

Browse files
committed
Setup unstable feature bound attribute
1 parent 36b2163 commit e144c89

File tree

7 files changed

+122
-0
lines changed

7 files changed

+122
-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
@@ -268,5 +268,8 @@ pub enum AttributeKind {
268268
/// Span of the attribute.
269269
span: Span,
270270
},
271+
272+
/// Represents `#[unstable_feature_bound]`.
273+
UnstableFeatureBound(ThinVec<(Symbol, Span)>),
271274
// tidy-alphabetical-end
272275
}

compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs

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

29+
pub(crate) struct UnstableFeatureBoundParser;
30+
impl<S: Stage> CombineAttributeParser<S> for UnstableFeatureBoundParser {
31+
const PATH: &'static [rustc_span::Symbol] = &[sym::unstable_feature_bound];
32+
type Item = (Symbol, Span);
33+
const CONVERT: ConvertFn<Self::Item> = AttributeKind::UnstableFeatureBound;
34+
const TEMPLATE: AttributeTemplate = template!(Word, List: "feat1, feat2, ...");
35+
36+
fn extend<'c>(
37+
cx: &'c mut AcceptContext<'_, '_, S>,
38+
args: &'c ArgParser<'_>,
39+
) -> impl IntoIterator<Item = Self::Item> {
40+
if !cx.features().staged_api() {
41+
cx.emit_err(session_diagnostics::StabilityOutsideStd { span: cx.attr_span });
42+
}
43+
parse_unstable(cx, args, <Self as CombineAttributeParser<S>>::PATH[0])
44+
.into_iter()
45+
.zip(iter::repeat(cx.attr_span))
46+
}
47+
}
48+
2949
pub(crate) struct AllowConstFnUnstableParser;
3050
impl<S: Stage> CombineAttributeParser<S> for AllowConstFnUnstableParser {
3151
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
@@ -650,6 +650,10 @@ passes_rustc_std_internal_symbol =
650650
attribute should be applied to functions or statics
651651
.label = not a function or static
652652
653+
passes_rustc_unstable_feature_bound =
654+
attribute should be applied to `impl` or free function outside of any `impl` or trait
655+
.label = not an `impl` or free function
656+
653657
passes_should_be_applied_to_fn =
654658
attribute should be applied to a function definition
655659
.label = {$on_crate ->

compiler/rustc_passes/src/check_attr.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
169169
Attribute::Parsed(AttributeKind::Naked(attr_span)) => {
170170
self.check_naked(hir_id, *attr_span, span, target)
171171
}
172+
Attribute::Parsed(AttributeKind::UnstableFeatureBound(syms)) => {
173+
self.check_unstable_feature_bound(syms.first().unwrap().1, span, target)
174+
}
172175
Attribute::Parsed(
173176
AttributeKind::BodyStability { .. }
174177
| AttributeKind::ConstStabilityIndirect
@@ -2225,6 +2228,46 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
22252228
}
22262229
}
22272230

2231+
fn check_unstable_feature_bound(&self, attr_span: Span, span: Span, target: Target) {
2232+
match target {
2233+
// FIXME(staged_api): There's no reason we can't support more targets here. We're just
2234+
// being conservative to begin with.
2235+
Target::Fn | Target::Impl => {}
2236+
Target::ExternCrate
2237+
| Target::Use
2238+
| Target::Static
2239+
| Target::Const
2240+
| Target::Closure
2241+
| Target::Mod
2242+
| Target::ForeignMod
2243+
| Target::GlobalAsm
2244+
| Target::TyAlias
2245+
| Target::Enum
2246+
| Target::Variant
2247+
| Target::Struct
2248+
| Target::Field
2249+
| Target::Union
2250+
| Target::Trait
2251+
| Target::TraitAlias
2252+
| Target::Expression
2253+
| Target::Statement
2254+
| Target::Arm
2255+
| Target::AssocConst
2256+
| Target::Method(_)
2257+
| Target::AssocTy
2258+
| Target::ForeignFn
2259+
| Target::ForeignStatic
2260+
| Target::ForeignTy
2261+
| Target::GenericParam(_)
2262+
| Target::MacroDef
2263+
| Target::Param
2264+
| Target::PatField
2265+
| Target::ExprField
2266+
| Target::WherePredicate => {
2267+
self.tcx.dcx().emit_err(errors::RustcUnstableFeatureBound { attr_span, span });
2268+
}
2269+
}
2270+
}
22282271
fn check_rustc_std_internal_symbol(&self, attr: &Attribute, span: Span, target: Target) {
22292272
match target {
22302273
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
@@ -662,6 +662,15 @@ pub(crate) struct RustcAllowConstFnUnstable {
662662
pub span: Span,
663663
}
664664

665+
#[derive(Diagnostic)]
666+
#[diag(passes_rustc_unstable_feature_bound)]
667+
pub(crate) struct RustcUnstableFeatureBound {
668+
#[primary_span]
669+
pub attr_span: Span,
670+
#[label]
671+
pub span: Span,
672+
}
673+
665674
#[derive(Diagnostic)]
666675
#[diag(passes_rustc_std_internal_symbol)]
667676
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)