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:
commit
ed64b97d61
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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() {
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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() {
|
||||
|
Loading…
Reference in New Issue
Block a user