Skip to content

Commit 6149a83

Browse files
committed
Parse, feature-gate, and validate the #[marker] attribute
1 parent 62c6e4e commit 6149a83

File tree

6 files changed

+97
-2
lines changed

6 files changed

+97
-2
lines changed

src/librustc/diagnostics.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2116,6 +2116,34 @@ struct Foo;
21162116
```
21172117
"##,
21182118

2119+
E0713: r##"
2120+
This error indicates that a `#[marker]` attribute was incorrectly placed
2121+
on something other than a trait.
2122+
2123+
Examples of erroneous code:
2124+
2125+
```compile_fail,E0713
2126+
# #![feature(marker_trait_attr)]
2127+
2128+
#[marker]
2129+
struct Foo { }
2130+
```
2131+
"##,
2132+
2133+
E0714: r##"
2134+
This error indicates that a `#[marker]` attribute had a value. The
2135+
`#[marker]` should be empty.
2136+
2137+
Examples of erroneous code:
2138+
2139+
```compile_fail,E0714
2140+
# #![feature(marker_trait_attr)]
2141+
2142+
#[marker(anything)]
2143+
trait Foo {}
2144+
```
2145+
"##,
2146+
21192147
}
21202148

21212149

src/librustc/hir/check_attr.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ enum Target {
3232
Statement,
3333
Closure,
3434
Static,
35+
Trait,
3536
Other,
3637
}
3738

@@ -45,6 +46,7 @@ impl Target {
4546
hir::ItemKind::Const(..) => Target::Const,
4647
hir::ItemKind::ForeignMod(..) => Target::ForeignMod,
4748
hir::ItemKind::Static(..) => Target::Static,
49+
hir::ItemKind::Trait(..) => Target::Trait,
4850
_ => Target::Other,
4951
}
5052
}
@@ -70,6 +72,8 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
7072
self.check_inline(attr, &item.span, target)
7173
} else if attr.check_name("non_exhaustive") {
7274
self.check_non_exhaustive(attr, item, target)
75+
} else if attr.check_name("marker") {
76+
self.check_marker(attr, item, target)
7377
}
7478
}
7579

@@ -114,6 +118,31 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
114118
}
115119
}
116120

121+
/// Check if the `#[marker]` attribute on an `item` is valid.
122+
fn check_marker(&self, attr: &hir::Attribute, item: &hir::Item, target: Target) {
123+
match target {
124+
Target::Trait => { /* Valid */ },
125+
_ => {
126+
struct_span_err!(self.tcx.sess,
127+
attr.span,
128+
E0713,
129+
"attribute can only be applied to a trait")
130+
.span_label(item.span, "not a trait")
131+
.emit();
132+
return;
133+
}
134+
}
135+
136+
if attr.meta_item_list().is_some() || attr.value_str().is_some() {
137+
struct_span_err!(self.tcx.sess,
138+
attr.span,
139+
E0714,
140+
"attribute should be empty")
141+
.span_label(item.span, "not empty")
142+
.emit();
143+
}
144+
}
145+
117146
/// Check if the `#[repr]` attributes on `item` are valid.
118147
fn check_repr(&self, item: &hir::Item, target: Target) {
119148
// Extract the names of all repr hints, e.g., [foo, bar, align] for:

src/librustc_typeck/collect.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -735,8 +735,7 @@ fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::
735735
err.emit();
736736
}
737737

738-
let is_marker = false; // FIXME (scottmcm)
739-
738+
let is_marker = tcx.has_attr(def_id, "marker");
740739
let def_path_hash = tcx.def_path_hash(def_id);
741740
let def = ty::TraitDef::new(def_id, unsafety, paren_sugar, is_auto, is_marker, def_path_hash);
742741
tcx.alloc_trait_def(def)

src/libsyntax/feature_gate.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,9 @@ declare_features! (
355355
// Allows overlapping impls of marker traits
356356
(active, overlapping_marker_traits, "1.18.0", Some(29864), None),
357357

358+
// Trait attribute to allow overlapping impls
359+
(active, marker_trait_attr, "1.30.0", Some(29864), None),
360+
358361
// rustc internal
359362
(active, abi_thiscall, "1.19.0", None, None),
360363

@@ -805,6 +808,12 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
805808
"non exhaustive is an experimental feature",
806809
cfg_fn!(non_exhaustive))),
807810

811+
// RFC #1268
812+
("marker", Normal, Gated(Stability::Unstable,
813+
"marker_trait_attr",
814+
"marker traits is an experimental feature",
815+
cfg_fn!(marker_trait_attr))),
816+
808817
("plugin", CrateLevel, Gated(Stability::Unstable,
809818
"plugin",
810819
"compiler plugins are experimental \
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use std::fmt::{Debug, Display};
12+
13+
#[marker] trait ExplicitMarker {}
14+
//~^ ERROR marker traits is an experimental feature (see issue #29864)
15+
16+
impl<T: Display> ExplicitMarker for T {}
17+
impl<T: Debug> ExplicitMarker for T {}
18+
19+
fn main() {}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0658]: marker traits is an experimental feature (see issue #29864)
2+
--> $DIR/feature-gate-marker_trait_attr.rs:13:1
3+
|
4+
LL | #[marker] trait ExplicitMarker {}
5+
| ^^^^^^^^^
6+
|
7+
= help: add #![feature(marker_trait_attr)] to the crate attributes to enable
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)