Skip to content

Commit 7ac74c5

Browse files
committed
Setup unstable feature bound attribute
1 parent d51b6f9 commit 7ac74c5

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
@@ -285,5 +285,8 @@ pub enum AttributeKind {
285285

286286
/// Represents `#[track_caller]`
287287
TrackCaller(Span),
288+
289+
/// Represents `#[unstable_feature_bound]`.
290+
UnstableFeatureBound(ThinVec<(Symbol, Span)>),
288291
// tidy-alphabetical-end
289292
}

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
@@ -662,6 +662,10 @@ passes_rustc_std_internal_symbol =
662662
attribute should be applied to functions or statics
663663
.label = not a function or static
664664
665+
passes_rustc_unstable_feature_bound =
666+
attribute should be applied to `impl` or free function outside of any `impl` or trait
667+
.label = not an `impl` or free function
668+
665669
passes_should_be_applied_to_fn =
666670
attribute should be applied to a function definition
667671
.label = {$on_crate ->

compiler/rustc_passes/src/check_attr.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
183183
Attribute::Parsed(AttributeKind::TrackCaller(attr_span)) => {
184184
self.check_track_caller(hir_id, *attr_span, attrs, span, target)
185185
}
186+
Attribute::Parsed(AttributeKind::UnstableFeatureBound(syms)) => {
187+
self.check_unstable_feature_bound(syms.first().unwrap().1, span, target)
188+
}
186189
Attribute::Parsed(
187190
AttributeKind::BodyStability { .. }
188191
| AttributeKind::ConstStabilityIndirect
@@ -2234,6 +2237,46 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
22342237
}
22352238
}
22362239

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

695+
#[derive(Diagnostic)]
696+
#[diag(passes_rustc_unstable_feature_bound)]
697+
pub(crate) struct RustcUnstableFeatureBound {
698+
#[primary_span]
699+
pub attr_span: Span,
700+
#[label]
701+
pub span: Span,
702+
}
703+
695704
#[derive(Diagnostic)]
696705
#[diag(passes_rustc_std_internal_symbol)]
697706
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)