]> git.lizzy.rs Git - rust.git/commitdiff
feature error span on attr. for fn_must_use, SIMD/align, macro reƫxport
authorZack M. Davis <code@zackmdavis.net>
Sun, 27 Aug 2017 01:00:33 +0000 (18:00 -0700)
committerZack M. Davis <code@zackmdavis.net>
Mon, 28 Aug 2017 07:58:41 +0000 (00:58 -0700)
There were several feature-gated attributes for which the
feature-not-available error spans would point to the item annotated with
the gated attribute, when it would make more sense for the span to point
to the attribute itself: if the attribute is removed, the
function/struct/&c. likely still makes sense and the program will
compile. (Note that we decline to make the analogous change for the
`main`, `start`, and `plugin_registrar` features, for in those cases it
makes sense for the span to implicate the entire function, of which
there is little hope of using without the gated attribute.)

src/libsyntax/attr.rs
src/libsyntax/feature_gate.rs
src/test/compile-fail-fulldeps/gated-macro-reexports.rs
src/test/compile-fail/feature-gate-fn_must_use.rs
src/test/compile-fail/feature-gate-repr-simd.rs
src/test/compile-fail/feature-gate-repr_align.rs
src/test/compile-fail/feature-gate-simd.rs
src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs
src/test/ui/span/gated-features-attr-spans.rs [new file with mode: 0644]
src/test/ui/span/gated-features-attr-spans.stderr [new file with mode: 0644]

index ca87c807103fd95c32a105e7122dab6cf95221b2..f97a8f67e2243f09565be16277c56aeda9e4e34b 100644 (file)
@@ -490,6 +490,10 @@ pub fn contains_name(attrs: &[Attribute], name: &str) -> bool {
     })
 }
 
+pub fn find_by_name<'a>(attrs: &'a [Attribute], name: &str) -> Option<&'a Attribute> {
+    attrs.iter().find(|attr| attr.check_name(name))
+}
+
 pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: &str) -> Option<Symbol> {
     attrs.iter()
         .find(|at| at.check_name(name))
index 09574d5ba129e80282dea9f6ff850371507d1166..2526ac3021a69dfeb57a6ebd13278212eddfe34e 100644 (file)
@@ -1248,8 +1248,8 @@ fn visit_name(&mut self, sp: Span, name: ast::Name) {
     fn visit_item(&mut self, i: &'a ast::Item) {
         match i.node {
             ast::ItemKind::ExternCrate(_) => {
-                if attr::contains_name(&i.attrs[..], "macro_reexport") {
-                    gate_feature_post!(&self, macro_reexport, i.span,
+                if let Some(attr) = attr::find_by_name(&i.attrs[..], "macro_reexport") {
+                    gate_feature_post!(&self, macro_reexport, attr.span,
                                        "macros reexports are experimental \
                                         and possibly buggy");
                 }
@@ -1276,36 +1276,32 @@ fn visit_item(&mut self, i: &'a ast::Item) {
                                         function may change over time, for now \
                                         a top-level `fn main()` is required");
                 }
-                if attr::contains_name(&i.attrs[..], "must_use") {
-                    gate_feature_post!(&self, fn_must_use, i.span,
+                if let Some(attr) = attr::find_by_name(&i.attrs[..], "must_use") {
+                    gate_feature_post!(&self, fn_must_use, attr.span,
                                        "`#[must_use]` on functions is experimental",
                                        GateStrength::Soft);
                 }
             }
 
             ast::ItemKind::Struct(..) => {
-                if attr::contains_name(&i.attrs[..], "simd") {
-                    gate_feature_post!(&self, simd, i.span,
+                if let Some(attr) = attr::find_by_name(&i.attrs[..], "simd") {
+                    gate_feature_post!(&self, simd, attr.span,
                                        "SIMD types are experimental and possibly buggy");
-                    self.context.parse_sess.span_diagnostic.span_warn(i.span,
+                    self.context.parse_sess.span_diagnostic.span_warn(attr.span,
                                                                       "the `#[simd]` attribute \
                                                                        is deprecated, use \
                                                                        `#[repr(simd)]` instead");
                 }
-                for attr in &i.attrs {
-                    if attr.path == "repr" {
-                        for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
-                            if item.check_name("simd") {
-                                gate_feature_post!(&self, repr_simd, i.span,
-                                                   "SIMD types are experimental \
-                                                    and possibly buggy");
-
-                            }
-                            if item.check_name("align") {
-                                gate_feature_post!(&self, repr_align, i.span,
-                                                   "the struct `#[repr(align(u16))]` attribute \
-                                                    is experimental");
-                            }
+                if let Some(attr) = attr::find_by_name(&i.attrs[..], "repr") {
+                    for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
+                        if item.check_name("simd") {
+                            gate_feature_post!(&self, repr_simd, attr.span,
+                                               "SIMD types are experimental and possibly buggy");
+                        }
+                        if item.check_name("align") {
+                            gate_feature_post!(&self, repr_align, attr.span,
+                                               "the struct `#[repr(align(u16))]` attribute \
+                                                is experimental");
                         }
                     }
                 }
@@ -1334,8 +1330,8 @@ fn visit_item(&mut self, i: &'a ast::Item) {
 
                 for impl_item in impl_items {
                     if let ast::ImplItemKind::Method(..) = impl_item.node {
-                        if attr::contains_name(&impl_item.attrs[..], "must_use") {
-                            gate_feature_post!(&self, fn_must_use, impl_item.span,
+                        if let Some(attr) = attr::find_by_name(&impl_item.attrs[..], "must_use") {
+                            gate_feature_post!(&self, fn_must_use, attr.span,
                                                "`#[must_use]` on methods is experimental",
                                                GateStrength::Soft);
                         }
index 22c92623e1c1944b9168b0ba2d7747eab2a00583..2a20c28cfb871f5abac1973d6edbfc906647a7ed 100644 (file)
@@ -16,6 +16,6 @@
 #![crate_type = "dylib"]
 
 #[macro_reexport(reexported)]
+//~^ ERROR macros reexports are experimental and possibly buggy
 #[macro_use] #[no_link]
 extern crate macro_reexport_1;
-//~^ ERROR macros reexports are experimental and possibly buggy
index 2dd6b904072676243b72b9ef882460c0b00b6633..72fdcc76cf4f62a236e2453290f31db54a12f9df 100644 (file)
 struct MyStruct;
 
 impl MyStruct {
-    #[must_use]
-    fn need_to_use_method() -> bool { true } //~ WARN `#[must_use]` on methods is experimental
+    #[must_use] //~ WARN `#[must_use]` on methods is experimental
+    fn need_to_use_method() -> bool { true }
 }
 
-#[must_use]
-fn need_to_use_it() -> bool { true } //~ WARN `#[must_use]` on functions is experimental
+#[must_use] //~ WARN `#[must_use]` on functions is experimental
+fn need_to_use_it() -> bool { true }
 
 
 // Feature gates are tidy-required to have a specially named (or
index fdafb2ad950c9bc037c2bc3c6e69cca80bf60529..429cec7ec90d05076456f82abf144c65f2624e0c 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[repr(simd)]
-struct Foo(u64, u64); //~ error: SIMD types are experimental
+#[repr(simd)] //~ error: SIMD types are experimental
+struct Foo(u64, u64);
 
 fn main() {}
index 8e986e197f2694d9113949cac7046f6117c5d880..9591d367a2d191ef99a2e92476c602dc28184a10 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 #![feature(attr_literals)]
 
-#[repr(align(64))]
-struct Foo(u64, u64); //~ error: the struct `#[repr(align(u16))]` attribute is experimental
+#[repr(align(64))] //~ error: the struct `#[repr(align(u16))]` attribute is experimental
+struct Foo(u64, u64);
 
 fn main() {}
index 168e84aa128c021447ef7add69a4740ac2b823ba..025eaca5533362321cbf767b0ef7f7af67305c54 100644 (file)
 
 // pretty-expanded FIXME #23616
 
-#[repr(simd)]
+#[repr(simd)] //~ ERROR SIMD types are experimental
 struct RGBA {
     r: f32,
     g: f32,
     b: f32,
     a: f32
 }
-//~^^^^^^ ERROR SIMD types are experimental and possibly buggy (see issue #27731)
 
 pub fn main() {}
index 204190d64acc1f61a33a02b7e02a510c52ce464d..6eec1779a2d87d689e5370e1ad3597af3f4ee022 100644 (file)
@@ -354,8 +354,7 @@ mod inner { #![repr="3900"] }
     #[repr = "3900"] fn f() { }
     //~^ WARN unused attribute
 
-    #[repr = "3900"] struct S;
-    //~^ WARN unused attribute
+    struct S;
 
     #[repr = "3900"] type T = S;
     //~^ WARN unused attribute
diff --git a/src/test/ui/span/gated-features-attr-spans.rs b/src/test/ui/span/gated-features-attr-spans.rs
new file mode 100644 (file)
index 0000000..d5ccd2e
--- /dev/null
@@ -0,0 +1,39 @@
+// 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.
+
+#![feature(attr_literals)]
+
+#[repr(align(16))]
+struct Gem {
+    mohs_hardness: u8,
+    poofed: bool,
+    weapon: Weapon,
+}
+
+#[repr(simd)]
+struct Weapon {
+    name: String,
+    damage: u32
+}
+
+impl Gem {
+    #[must_use] fn summon_weapon(&self) -> Weapon { self.weapon }
+}
+
+#[must_use]
+fn bubble(gem: Gem) -> Result<Gem, ()> {
+    if gem.poofed {
+        Ok(gem)
+    } else {
+        Err(())
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/span/gated-features-attr-spans.stderr b/src/test/ui/span/gated-features-attr-spans.stderr
new file mode 100644 (file)
index 0000000..66b2567
--- /dev/null
@@ -0,0 +1,34 @@
+error: the struct `#[repr(align(u16))]` attribute is experimental (see issue #33626)
+  --> $DIR/gated-features-attr-spans.rs:13:1
+   |
+13 | #[repr(align(16))]
+   | ^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(repr_align)] to the crate attributes to enable
+
+error: SIMD types are experimental and possibly buggy (see issue #27731)
+  --> $DIR/gated-features-attr-spans.rs:20:1
+   |
+20 | #[repr(simd)]
+   | ^^^^^^^^^^^^^
+   |
+   = help: add #![feature(repr_simd)] to the crate attributes to enable
+
+warning: `#[must_use]` on methods is experimental (see issue #43302)
+  --> $DIR/gated-features-attr-spans.rs:27:5
+   |
+27 |     #[must_use] fn summon_weapon(&self) -> Weapon { self.weapon }
+   |     ^^^^^^^^^^^
+   |
+   = help: add #![feature(fn_must_use)] to the crate attributes to enable
+
+warning: `#[must_use]` on functions is experimental (see issue #43302)
+  --> $DIR/gated-features-attr-spans.rs:30:1
+   |
+30 | #[must_use]
+   | ^^^^^^^^^^^
+   |
+   = help: add #![feature(fn_must_use)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+