Skip to content

Commit

Permalink
Expand output and suggestions, fix tests
Browse files Browse the repository at this point in the history
  • Loading branch information
estebank committed Jun 6, 2018
1 parent 36381fa commit 2c7099b
Show file tree
Hide file tree
Showing 6 changed files with 292 additions and 154 deletions.
1 change: 0 additions & 1 deletion src/librustc/diagnostics.rs
Expand Up @@ -2139,7 +2139,6 @@ register_diagnostics! {
E0657, // `impl Trait` can only capture lifetimes bound at the fn level
E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax
E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders
E0689, // `#[repr]` must have a hint

E0906, // closures cannot be static
}
59 changes: 48 additions & 11 deletions src/librustc/hir/check_attr.rs
Expand Up @@ -14,7 +14,7 @@
//! conflicts between multiple such attributes attached to the same
//! item.

use syntax_pos::Span;
use syntax_pos::{BytePos, Span};
use ty::TyCtxt;

use hir;
Expand Down Expand Up @@ -156,17 +156,54 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
.filter(|attr| attr.name() == "repr")
.filter_map(|attr| {
let list = attr.meta_item_list();
let mut has_hints = false;
if let Some(ref list) = list {
has_hints = !list.is_empty();
}

// Emit warnings with `repr` either has a literal assignment (`#[repr = "C"]`) or
// no hints (``#[repr]`)
let has_hints = list.as_ref().map(|ref list| !list.is_empty()).unwrap_or(false);
if !has_hints {
span_warn!(
self.tcx.sess,
item.span,
E0689,
"`repr` attribute cannot be empty",
);
let mut suggested = false;
let mut warn = if let Some(ref lit) = attr.value_str() {
// avoid warning about empty `repr` on `#[repr = "foo"]`
let sp = match format!("{}", lit).as_ref() {
"C" | "packed" | "rust" | "u*" | "i*" => {
let lo = attr.span.lo() + BytePos(2);
let hi = attr.span.hi() - BytePos(1);
suggested = true;
attr.span.with_lo(lo).with_hi(hi)
}
_ => attr.span, // the literal wasn't a valid `repr` arg
};
let mut warn = self.tcx.sess.struct_span_warn(
sp,
"`repr` attribute isn't configurable with a literal",
);
if suggested {
// if the literal could have been a valid `repr` arg,
// suggest the correct syntax
warn.span_suggestion(
sp,
"give `repr` a hint",
format!("repr({})", lit),
);
} else {
warn.span_label(attr.span, "needs a hint");
}
warn
} else {
let mut warn = self.tcx.sess.struct_span_warn(
attr.span,
"`repr` attribute must have a hint",
);
warn.span_label(attr.span, "needs a hint");
warn
};
if !suggested {
warn.help("valid hints include `#[repr(C)]`, `#[repr(packed)]` and \
`#[repr(rust)]`");
warn.note("for more information, visit \
<https://doc.rust-lang.org/nomicon/other-reprs.html>");
}
warn.emit();
}
list
})
Expand Down
Expand Up @@ -309,20 +309,25 @@ mod bench {

#[repr = "3900"]
//~^ WARN unused attribute
//~| WARN `repr` attribute isn't configurable with a literal
mod repr {
mod inner { #![repr="3900"] }
//~^ WARN unused attribute
//~| WARN `repr` attribute isn't configurable with a literal

#[repr = "3900"] fn f() { }
//~^ WARN unused attribute
//~| WARN `repr` attribute isn't configurable with a literal

struct S;

#[repr = "3900"] type T = S;
//~^ WARN unused attribute
//~| WARN `repr` attribute isn't configurable with a literal

#[repr = "3900"] impl S { }
//~^ WARN unused attribute
//~| WARN `repr` attribute isn't configurable with a literal
}

#[path = "3800"]
Expand Down

0 comments on commit 2c7099b

Please sign in to comment.