Rollup merge of #45984 - ExpHP:attr-error-context, r=estebank

Add context to E0084, E0517, E0518

A small diagnostic enhancement to get my feet wet.  Please scrutinize!

This modifies errors E0084, E0517, and E0518 to include both the annotation and the annotated item.  All of these errors already had labels; I moved the label to the other span, and rephrased it as necessary.

Fixes #45886
This commit is contained in:
Guillaume Gomez 2017-11-16 10:05:04 +01:00 committed by GitHub
commit ed64b97d61
5 changed files with 32 additions and 36 deletions

View File

@ -47,27 +47,27 @@ struct CheckAttrVisitor<'a> {
impl<'a> CheckAttrVisitor<'a> {
/// 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() {
match &*name.as_str() {
"inline" => self.check_inline(attr, target),
"repr" => self.check_repr(attr, target),
"inline" => self.check_inline(attr, item, target),
"repr" => self.check_repr(attr, item, target),
_ => (),
}
}
}
/// 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 {
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();
}
}
/// 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() {
Some(words) => words,
None => {
@ -139,7 +139,7 @@ impl<'a> CheckAttrVisitor<'a> {
_ => continue,
};
struct_span_err!(self.sess, attr.span, E0517, "{}", message)
.span_label(attr.span, format!("requires {}", label))
.span_label(item.span, format!("not {}", label))
.emit();
}
if conflicting_reprs > 1 {
@ -153,7 +153,7 @@ impl<'a> Visitor<'a> for CheckAttrVisitor<'a> {
fn visit_item(&mut self, item: &'a ast::Item) {
let target = Target::from_item(item);
for attr in &item.attrs {
self.check_attribute(attr, target);
self.check_attribute(attr, item, target);
}
visit::walk_item(self, item);
}

View File

@ -117,6 +117,7 @@ use std::mem::replace;
use std::ops::{self, Deref};
use syntax::abi::Abi;
use syntax::ast;
use syntax::attr;
use syntax::codemap::{self, original_sp, Spanned};
use syntax::feature_gate::{GateIssue, emit_feature_err};
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);
def.destructor(tcx); // force the destructor to be evaluated
if vs.is_empty() && tcx.has_attr(def_id, "repr") {
struct_span_err!(
tcx.sess, sp, E0084,
"unsupported representation for zero-variant enum")
.span_label(sp, "unsupported enum representation")
.emit();
if vs.is_empty() {
let attributes = tcx.get_attrs(def_id);
if let Some(attr) = attr::find_by_name(&attributes, "repr") {
struct_span_err!(
tcx.sess, attr.span, E0084,
"unsupported representation for zero-variant enum")
.span_label(sp, "zero-variant enum")
.emit();
}
}
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
// except according to those terms.
#[repr(i32)]
enum Foo {}
//~^ ERROR E0084
//~| unsupported enum representation
#[repr(i32)] //~ ERROR: E0084
enum Foo {} //~ NOTE: zero-variant enum
fn main() {
}

View File

@ -8,21 +8,17 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[repr(C)] //~ ERROR E0517
//~| requires a struct, enum or union
type Foo = u8;
#[repr(C)] //~ ERROR: E0517
type Foo = u8; //~ NOTE: not a struct, enum or union
#[repr(packed)] //~ ERROR E0517
//~| requires a struct
enum Foo2 {Bar, Baz}
#[repr(packed)] //~ ERROR: E0517
enum Foo2 {Bar, Baz} //~ NOTE: not a struct
#[repr(u8)] //~ ERROR E0517
//~| requires an enum
struct Foo3 {bar: bool, baz: bool}
#[repr(u8)] //~ ERROR: E0517
struct Foo3 {bar: bool, baz: bool} //~ NOTE: not an enum
#[repr(C)] //~ ERROR E0517
//~| requires a struct, enum or union
impl Foo3 {
#[repr(C)] //~ ERROR: E0517
impl Foo3 { //~ NOTE: not a struct, enum or union
}
fn main() {

View File

@ -8,13 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[inline(always)] //~ ERROR E0518
//~| requires a function
struct Foo;
#[inline(always)] //~ ERROR: E0518
struct Foo; //~ NOTE: not a function
#[inline(never)] //~ ERROR E0518
//~| requires a function
impl Foo {
#[inline(never)] //~ ERROR: E0518
impl Foo { //~ NOTE: not a function
}
fn main() {