about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/diagnostics.rs28
-rw-r--r--src/librustc/hir/check_attr.rs29
-rw-r--r--src/librustc_typeck/collect.rs3
-rw-r--r--src/libsyntax/feature_gate.rs9
-rw-r--r--src/test/ui/feature-gates/feature-gate-marker_trait_attr.rs19
-rw-r--r--src/test/ui/feature-gates/feature-gate-marker_trait_attr.stderr11
6 files changed, 97 insertions, 2 deletions
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index 3318bbd8c87..c82e2111b77 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -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 {}
+```
+"##,
+
 }
 
 
diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs
index 298ef67923a..57fc561a2f4 100644
--- a/src/librustc/hir/check_attr.rs
+++ b/src/librustc/hir/check_attr.rs
@@ -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:
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 5892296102c..507ed594789 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -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)
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 7266d807d3b..8f7f9cac447 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -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 \
diff --git a/src/test/ui/feature-gates/feature-gate-marker_trait_attr.rs b/src/test/ui/feature-gates/feature-gate-marker_trait_attr.rs
new file mode 100644
index 00000000000..508ffe3845b
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-marker_trait_attr.rs
@@ -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() {}
diff --git a/src/test/ui/feature-gates/feature-gate-marker_trait_attr.stderr b/src/test/ui/feature-gates/feature-gate-marker_trait_attr.stderr
new file mode 100644
index 00000000000..4023a04000a
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-marker_trait_attr.stderr
@@ -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`.