Parse, feature-gate, and validate the #[marker] attribute
This commit is contained in:
parent
62c6e4e145
commit
6149a83c0b
@ -2116,6 +2116,34 @@ struct Foo;
|
||||
```
|
||||
"##,
|
||||
|
||||
E0713: r##"
|
||||
This error indicates that a `#[marker]` attribute was incorrectly placed
|
||||
on something other than a trait.
|
||||
|
||||
Examples of erroneous code:
|
||||
|
||||
```compile_fail,E0713
|
||||
# #![feature(marker_trait_attr)]
|
||||
|
||||
#[marker]
|
||||
struct Foo { }
|
||||
```
|
||||
"##,
|
||||
|
||||
E0714: r##"
|
||||
This error indicates that a `#[marker]` attribute had a value. The
|
||||
`#[marker]` should be empty.
|
||||
|
||||
Examples of erroneous code:
|
||||
|
||||
```compile_fail,E0714
|
||||
# #![feature(marker_trait_attr)]
|
||||
|
||||
#[marker(anything)]
|
||||
trait Foo {}
|
||||
```
|
||||
"##,
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -32,6 +32,7 @@ enum Target {
|
||||
Statement,
|
||||
Closure,
|
||||
Static,
|
||||
Trait,
|
||||
Other,
|
||||
}
|
||||
|
||||
@ -45,6 +46,7 @@ impl Target {
|
||||
hir::ItemKind::Const(..) => Target::Const,
|
||||
hir::ItemKind::ForeignMod(..) => Target::ForeignMod,
|
||||
hir::ItemKind::Static(..) => Target::Static,
|
||||
hir::ItemKind::Trait(..) => Target::Trait,
|
||||
_ => Target::Other,
|
||||
}
|
||||
}
|
||||
@ -70,6 +72,8 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
|
||||
self.check_inline(attr, &item.span, target)
|
||||
} else if attr.check_name("non_exhaustive") {
|
||||
self.check_non_exhaustive(attr, item, target)
|
||||
} else if attr.check_name("marker") {
|
||||
self.check_marker(attr, item, target)
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,6 +118,31 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if the `#[marker]` attribute on an `item` is valid.
|
||||
fn check_marker(&self, attr: &hir::Attribute, item: &hir::Item, target: Target) {
|
||||
match target {
|
||||
Target::Trait => { /* Valid */ },
|
||||
_ => {
|
||||
struct_span_err!(self.tcx.sess,
|
||||
attr.span,
|
||||
E0713,
|
||||
"attribute can only be applied to a trait")
|
||||
.span_label(item.span, "not a trait")
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if attr.meta_item_list().is_some() || attr.value_str().is_some() {
|
||||
struct_span_err!(self.tcx.sess,
|
||||
attr.span,
|
||||
E0714,
|
||||
"attribute should be empty")
|
||||
.span_label(item.span, "not empty")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if the `#[repr]` attributes on `item` are valid.
|
||||
fn check_repr(&self, item: &hir::Item, target: Target) {
|
||||
// Extract the names of all repr hints, e.g., [foo, bar, align] for:
|
||||
|
@ -735,8 +735,7 @@ fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::
|
||||
err.emit();
|
||||
}
|
||||
|
||||
let is_marker = false; // FIXME (scottmcm)
|
||||
|
||||
let is_marker = tcx.has_attr(def_id, "marker");
|
||||
let def_path_hash = tcx.def_path_hash(def_id);
|
||||
let def = ty::TraitDef::new(def_id, unsafety, paren_sugar, is_auto, is_marker, def_path_hash);
|
||||
tcx.alloc_trait_def(def)
|
||||
|
@ -355,6 +355,9 @@ declare_features! (
|
||||
// Allows overlapping impls of marker traits
|
||||
(active, overlapping_marker_traits, "1.18.0", Some(29864), None),
|
||||
|
||||
// Trait attribute to allow overlapping impls
|
||||
(active, marker_trait_attr, "1.30.0", Some(29864), None),
|
||||
|
||||
// rustc internal
|
||||
(active, abi_thiscall, "1.19.0", None, None),
|
||||
|
||||
@ -805,6 +808,12 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
|
||||
"non exhaustive is an experimental feature",
|
||||
cfg_fn!(non_exhaustive))),
|
||||
|
||||
// RFC #1268
|
||||
("marker", Normal, Gated(Stability::Unstable,
|
||||
"marker_trait_attr",
|
||||
"marker traits is an experimental feature",
|
||||
cfg_fn!(marker_trait_attr))),
|
||||
|
||||
("plugin", CrateLevel, Gated(Stability::Unstable,
|
||||
"plugin",
|
||||
"compiler plugins are experimental \
|
||||
|
19
src/test/ui/feature-gates/feature-gate-marker_trait_attr.rs
Normal file
19
src/test/ui/feature-gates/feature-gate-marker_trait_attr.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::fmt::{Debug, Display};
|
||||
|
||||
#[marker] trait ExplicitMarker {}
|
||||
//~^ ERROR marker traits is an experimental feature (see issue #29864)
|
||||
|
||||
impl<T: Display> ExplicitMarker for T {}
|
||||
impl<T: Debug> ExplicitMarker for T {}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,11 @@
|
||||
error[E0658]: marker traits is an experimental feature (see issue #29864)
|
||||
--> $DIR/feature-gate-marker_trait_attr.rs:13:1
|
||||
|
|
||||
LL | #[marker] trait ExplicitMarker {}
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: add #![feature(marker_trait_attr)] to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
Loading…
x
Reference in New Issue
Block a user