Add context to E0084, E00517, E0518

Show both the attribute and the item
This commit is contained in:
Michael Lamparski 2017-11-13 20:13:26 -05:00
parent 24840dab0b
commit dcbedf78a0
8 changed files with 49 additions and 42 deletions

View File

@ -47,27 +47,27 @@ struct CheckAttrVisitor<'a> {
impl<'a> CheckAttrVisitor<'a> { impl<'a> CheckAttrVisitor<'a> {
/// Check any attribute. /// Check any attribute.
fn check_attribute(&self, attr: &ast::Attribute, target: Target) { fn check_attribute(&self, attr: &ast::Attribute, item: &ast::Item, target: Target) {
if let Some(name) = attr.name() { if let Some(name) = attr.name() {
match &*name.as_str() { match &*name.as_str() {
"inline" => self.check_inline(attr, target), "inline" => self.check_inline(attr, item, target),
"repr" => self.check_repr(attr, target), "repr" => self.check_repr(attr, item, target),
_ => (), _ => (),
} }
} }
} }
/// Check if an `#[inline]` is applied to a function. /// Check if an `#[inline]` is applied to a function.
fn check_inline(&self, attr: &ast::Attribute, target: Target) { fn check_inline(&self, attr: &ast::Attribute, item: &ast::Item, target: Target) {
if target != Target::Fn { if target != Target::Fn {
struct_span_err!(self.sess, attr.span, E0518, "attribute should be applied to function") struct_span_err!(self.sess, attr.span, E0518, "attribute should be applied to function")
.span_label(attr.span, "requires a function") .span_label(item.span, "not a function")
.emit(); .emit();
} }
} }
/// Check if an `#[repr]` attr is valid. /// Check if an `#[repr]` attr is valid.
fn check_repr(&self, attr: &ast::Attribute, target: Target) { fn check_repr(&self, attr: &ast::Attribute, item: &ast::Item, target: Target) {
let words = match attr.meta_item_list() { let words = match attr.meta_item_list() {
Some(words) => words, Some(words) => words,
None => { None => {
@ -139,7 +139,7 @@ impl<'a> CheckAttrVisitor<'a> {
_ => continue, _ => continue,
}; };
struct_span_err!(self.sess, attr.span, E0517, "{}", message) struct_span_err!(self.sess, attr.span, E0517, "{}", message)
.span_label(attr.span, format!("requires {}", label)) .span_label(item.span, format!("not {}", label))
.emit(); .emit();
} }
if conflicting_reprs > 1 { if conflicting_reprs > 1 {
@ -153,7 +153,7 @@ impl<'a> Visitor<'a> for CheckAttrVisitor<'a> {
fn visit_item(&mut self, item: &'a ast::Item) { fn visit_item(&mut self, item: &'a ast::Item) {
let target = Target::from_item(item); let target = Target::from_item(item);
for attr in &item.attrs { for attr in &item.attrs {
self.check_attribute(attr, target); self.check_attribute(attr, item, target);
} }
visit::walk_item(self, item); visit::walk_item(self, item);
} }

View File

@ -117,6 +117,7 @@ use std::mem::replace;
use std::ops::{self, Deref}; use std::ops::{self, Deref};
use syntax::abi::Abi; use syntax::abi::Abi;
use syntax::ast; use syntax::ast;
use syntax::attr;
use syntax::codemap::{self, original_sp, Spanned}; use syntax::codemap::{self, original_sp, Spanned};
use syntax::feature_gate::{GateIssue, emit_feature_err}; use syntax::feature_gate::{GateIssue, emit_feature_err};
use syntax::ptr::P; use syntax::ptr::P;
@ -1561,12 +1562,15 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let def = tcx.adt_def(def_id); let def = tcx.adt_def(def_id);
def.destructor(tcx); // force the destructor to be evaluated def.destructor(tcx); // force the destructor to be evaluated
if vs.is_empty() && tcx.has_attr(def_id, "repr") { if vs.is_empty() {
struct_span_err!( let attributes = tcx.get_attrs(def_id);
tcx.sess, sp, E0084, if let Some(attr) = attr::find_by_name(&attributes, "repr") {
"unsupported representation for zero-variant enum") struct_span_err!(
.span_label(sp, "unsupported enum representation") tcx.sess, attr.span, E0084,
.emit(); "unsupported representation for zero-variant enum")
.span_label(sp, "zero-variant enum")
.emit();
}
} }
let repr_type_ty = def.repr.discr_type().to_ty(tcx); let repr_type_ty = def.repr.discr_type().to_ty(tcx);

View File

@ -8,10 +8,8 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
#[repr(i32)] #[repr(i32)] //~ ERROR E0084
enum Foo {} enum Foo {} //~ zero-variant enum
//~^ ERROR E0084
//~| unsupported enum representation
fn main() { fn main() {
} }

View File

@ -9,20 +9,16 @@
// except according to those terms. // except according to those terms.
#[repr(C)] //~ ERROR E0517 #[repr(C)] //~ ERROR E0517
//~| requires a struct, enum or union type Foo = u8; //~ not a struct, enum or union
type Foo = u8;
#[repr(packed)] //~ ERROR E0517 #[repr(packed)] //~ ERROR E0517
//~| requires a struct enum Foo2 {Bar, Baz} //~ not a struct
enum Foo2 {Bar, Baz}
#[repr(u8)] //~ ERROR E0517 #[repr(u8)] //~ ERROR E0517
//~| requires an enum struct Foo3 {bar: bool, baz: bool} //~ not an enum
struct Foo3 {bar: bool, baz: bool}
#[repr(C)] //~ ERROR E0517 #[repr(C)] //~ ERROR E0517
//~| requires a struct, enum or union impl Foo3 { //~ not a struct, enum or union
impl Foo3 {
} }
fn main() { fn main() {

View File

@ -9,12 +9,10 @@
// except according to those terms. // except according to those terms.
#[inline(always)] //~ ERROR E0518 #[inline(always)] //~ ERROR E0518
//~| requires a function struct Foo; //~ not a function
struct Foo;
#[inline(never)] //~ ERROR E0518 #[inline(never)] //~ ERROR E0518
//~| requires a function impl Foo { //~ not a function
impl Foo {
} }
fn main() { fn main() {

View File

@ -14,6 +14,6 @@
fn f() {} fn f() {}
#[inline] //~ ERROR: attribute should be applied to function #[inline] //~ ERROR: attribute should be applied to function
struct S; struct S; //~ not a function
fn main() {} fn main() {}

View File

@ -13,7 +13,7 @@
#![feature(repr_simd)] #![feature(repr_simd)]
#[repr(C)] //~ ERROR: attribute should be applied to struct, enum or union #[repr(C)] //~ ERROR: attribute should be applied to struct, enum or union
fn f() {} fn f() {} //~ not a struct, enum or union
#[repr(C)] #[repr(C)]
struct SExtern(f64, f64); struct SExtern(f64, f64);
@ -25,19 +25,19 @@ struct SPacked(f64, f64);
struct SSimd(f64, f64); struct SSimd(f64, f64);
#[repr(i8)] //~ ERROR: attribute should be applied to enum #[repr(i8)] //~ ERROR: attribute should be applied to enum
struct SInt(f64, f64); struct SInt(f64, f64); //~ not an enum
#[repr(C)] #[repr(C)]
enum EExtern { A, B } enum EExtern { A, B }
#[repr(align(8))] //~ ERROR: attribute should be applied to struct #[repr(align(8))] //~ ERROR: attribute should be applied to struct
enum EAlign { A, B } enum EAlign { A, B } // not a struct
#[repr(packed)] //~ ERROR: attribute should be applied to struct #[repr(packed)] //~ ERROR: attribute should be applied to struct
enum EPacked { A, B } enum EPacked { A, B } // not a struct
#[repr(simd)] //~ ERROR: attribute should be applied to struct #[repr(simd)] //~ ERROR: attribute should be applied to struct
enum ESimd { A, B } enum ESimd { A, B } // not a struct
#[repr(i8)] #[repr(i8)]
enum EInt { A, B } enum EInt { A, B }

View File

@ -21,17 +21,28 @@
#[inline = "2100"] #[inline = "2100"]
//~^ ERROR attribute should be applied to function //~^ ERROR attribute should be applied to function
mod inline { mod inline {
mod inner { #![inline="2100"] } //~^ not a function
//~^ ERROR attribute should be applied to function mod inner {
//~^ not a function
#![inline="2100"]
//~^ ERROR attribute should be applied to function
}
#[inline = "2100"] fn f() { } #[inline = "2100"]
fn f() { }
#[inline = "2100"] struct S; #[inline = "2100"]
//~^ ERROR attribute should be applied to function //~^ ERROR attribute should be applied to function
struct S;
//~^ not a function
#[inline = "2100"] type T = S; #[inline = "2100"]
//~^ ERROR attribute should be applied to function //~^ ERROR attribute should be applied to function
type T = S;
//~^ not a function
#[inline = "2100"] impl S { } #[inline = "2100"]
//~^ ERROR attribute should be applied to function //~^ ERROR attribute should be applied to function
impl S { }
//~^ not a function
} }