Skip to content

Commit 23f3fb0

Browse files
committed
Setup unstable feature bound attribute
1 parent 64b185e commit 23f3fb0

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
@@ -386,6 +386,9 @@ pub enum AttributeKind {
386386
/// Represents `#[rustc_unsafe_specialization_marker]`.
387387
UnsafeSpecializationMarker(Span),
388388

389+
/// Represents `#[unstable_feature_bound]`.
390+
UnstableFeatureBound(ThinVec<(Symbol, Span)>),
391+
389392
/// Represents `#[used]`
390393
Used { used_by: UsedBy, span: Span },
391394
// 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
@@ -663,6 +663,10 @@ passes_rustc_std_internal_symbol =
663663
attribute should be applied to functions or statics
664664
.label = not a function or static
665665
666+
passes_rustc_unstable_feature_bound =
667+
attribute should be applied to `impl` or free function outside of any `impl` or trait
668+
.label = not an `impl` or free function
669+
666670
passes_should_be_applied_to_fn =
667671
attribute should be applied to a function definition
668672
.label = {$on_crate ->

compiler/rustc_passes/src/check_attr.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
246246
&Attribute::Parsed(AttributeKind::FfiPure(attr_span)) => {
247247
self.check_ffi_pure(attr_span, attrs, target)
248248
}
249+
Attribute::Parsed(AttributeKind::UnstableFeatureBound(syms)) => {
250+
self.check_unstable_feature_bound(syms.first().unwrap().1, span, target)
251+
}
249252
Attribute::Parsed(
250253
AttributeKind::BodyStability { .. }
251254
| AttributeKind::ConstStabilityIndirect
@@ -2247,6 +2250,47 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
22472250
}
22482251
}
22492252

2253+
fn check_unstable_feature_bound(&self, attr_span: Span, span: Span, target: Target) {
2254+
match target {
2255+
// FIXME(staged_api): There's no reason we can't support more targets here. We're just
2256+
// being conservative to begin with.
2257+
Target::Fn | Target::Impl => {}
2258+
Target::ExternCrate
2259+
| Target::Use
2260+
| Target::Static
2261+
| Target::Const
2262+
| Target::Closure
2263+
| Target::Mod
2264+
| Target::ForeignMod
2265+
| Target::GlobalAsm
2266+
| Target::TyAlias
2267+
| Target::Enum
2268+
| Target::Variant
2269+
| Target::Struct
2270+
| Target::Field
2271+
| Target::Union
2272+
| Target::Trait
2273+
| Target::TraitAlias
2274+
| Target::Expression
2275+
| Target::Statement
2276+
| Target::Arm
2277+
| Target::AssocConst
2278+
| Target::Method(_)
2279+
| Target::AssocTy
2280+
| Target::ForeignFn
2281+
| Target::ForeignStatic
2282+
| Target::ForeignTy
2283+
| Target::GenericParam(_)
2284+
| Target::MacroDef
2285+
| Target::Param
2286+
| Target::PatField
2287+
| Target::ExprField
2288+
| Target::WherePredicate => {
2289+
self.tcx.dcx().emit_err(errors::RustcUnstableFeatureBound { attr_span, span });
2290+
}
2291+
}
2292+
}
2293+
22502294
fn check_rustc_std_internal_symbol(&self, attr_span: Span, span: Span, target: Target) {
22512295
match target {
22522296
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
@@ -678,6 +678,15 @@ pub(crate) struct RustcAllowConstFnUnstable {
678678
pub span: Span,
679679
}
680680

681+
#[derive(Diagnostic)]
682+
#[diag(passes_rustc_unstable_feature_bound)]
683+
pub(crate) struct RustcUnstableFeatureBound {
684+
#[primary_span]
685+
pub attr_span: Span,
686+
#[label]
687+
pub span: Span,
688+
}
689+
681690
#[derive(Diagnostic)]
682691
#[diag(passes_rustc_std_internal_symbol)]
683692
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)