Make meta-item API compatible with LocalInternedString::get
soundness fix
This commit is contained in:
parent
7cf074a1e6
commit
db74efce69
17 changed files with 84 additions and 97 deletions
|
@ -177,16 +177,8 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
|
||||||
let mut is_transparent = false;
|
let mut is_transparent = false;
|
||||||
|
|
||||||
for hint in &hints {
|
for hint in &hints {
|
||||||
let name = if let Some(name) = hint.ident_str() {
|
let (article, allowed_targets) = match hint.name_or_empty().get() {
|
||||||
name
|
name @ "C" | name @ "align" => {
|
||||||
} else {
|
|
||||||
// Invalid repr hint like repr(42). We don't check for unrecognized hints here
|
|
||||||
// (libsyntax does that), so just ignore it.
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
|
|
||||||
let (article, allowed_targets) = match name {
|
|
||||||
"C" | "align" => {
|
|
||||||
is_c |= name == "C";
|
is_c |= name == "C";
|
||||||
if target != Target::Struct &&
|
if target != Target::Struct &&
|
||||||
target != Target::Union &&
|
target != Target::Union &&
|
||||||
|
|
|
@ -194,7 +194,7 @@ impl<'a> LintLevelsBuilder<'a> {
|
||||||
struct_span_err!(sess, span, E0452, "malformed lint attribute")
|
struct_span_err!(sess, span, E0452, "malformed lint attribute")
|
||||||
};
|
};
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
let level = match attr.ident_str().and_then(|name| Level::from_str(name)) {
|
let level = match Level::from_str(&attr.name_or_empty()) {
|
||||||
None => continue,
|
None => continue,
|
||||||
Some(lvl) => lvl,
|
Some(lvl) => lvl,
|
||||||
};
|
};
|
||||||
|
|
|
@ -723,12 +723,7 @@ pub fn struct_lint_level<'a>(sess: &'a Session,
|
||||||
|
|
||||||
pub fn maybe_lint_level_root(tcx: TyCtxt<'_, '_, '_>, id: hir::HirId) -> bool {
|
pub fn maybe_lint_level_root(tcx: TyCtxt<'_, '_, '_>, id: hir::HirId) -> bool {
|
||||||
let attrs = tcx.hir().attrs_by_hir_id(id);
|
let attrs = tcx.hir().attrs_by_hir_id(id);
|
||||||
for attr in attrs {
|
attrs.iter().any(|attr| Level::from_str(&attr.name_or_empty()).is_some())
|
||||||
if attr.ident_str().and_then(Level::from_str).is_some() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lint_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum)
|
fn lint_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum)
|
||||||
|
|
|
@ -65,9 +65,9 @@ impl<'a, 'tcx> LibFeatureCollector<'a, 'tcx> {
|
||||||
for meta in metas {
|
for meta in metas {
|
||||||
if let Some(mi) = meta.meta_item() {
|
if let Some(mi) = meta.meta_item() {
|
||||||
// Find the `feature = ".."` meta-item.
|
// Find the `feature = ".."` meta-item.
|
||||||
match (mi.ident_str(), mi.value_str()) {
|
match (mi.name_or_empty().get(), mi.value_str()) {
|
||||||
(Some("feature"), val) => feature = val,
|
("feature", val) => feature = val,
|
||||||
(Some("since"), val) => since = val,
|
("since", val) => since = val,
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,12 +194,11 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
|
||||||
} else {
|
} else {
|
||||||
// Emit errors for non-staged-api crates.
|
// Emit errors for non-staged-api crates.
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
if let Some(tag) = attr.ident_str() {
|
let name = attr.name_or_empty();
|
||||||
if tag == "unstable" || tag == "stable" || tag == "rustc_deprecated" {
|
if ["unstable", "stable", "rustc_deprecated"].contains(&name.get()) {
|
||||||
attr::mark_used(attr);
|
attr::mark_used(attr);
|
||||||
self.tcx.sess.span_err(attr.span, "stability attributes may not be used \
|
self.tcx.sess.span_err(attr.span, "stability attributes may not be used \
|
||||||
outside of the standard library");
|
outside of the standard library");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -177,9 +177,9 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
|
||||||
for command in self.subcommands.iter().chain(Some(self)).rev() {
|
for command in self.subcommands.iter().chain(Some(self)).rev() {
|
||||||
if let Some(ref condition) = command.condition {
|
if let Some(ref condition) = command.condition {
|
||||||
if !attr::eval_condition(condition, &tcx.sess.parse_sess, &mut |c| {
|
if !attr::eval_condition(condition, &tcx.sess.parse_sess, &mut |c| {
|
||||||
c.ident_str().map_or(false, |name| {
|
c.ident().map_or(false, |ident| {
|
||||||
options.contains(&(
|
options.contains(&(
|
||||||
name.to_string(),
|
ident.to_string(),
|
||||||
c.value_str().map(|s| s.as_str().to_string())
|
c.value_str().map(|s| s.as_str().to_string())
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
|
|
|
@ -576,8 +576,8 @@ fn expect_associated_value(tcx: TyCtxt<'_, '_, '_>, item: &NestedMetaItem) -> as
|
||||||
if let Some(value) = item.value_str() {
|
if let Some(value) = item.value_str() {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
let msg = if let Some(name) = item.ident_str() {
|
let msg = if let Some(ident) = item.ident() {
|
||||||
format!("associated value expected for `{}`", name)
|
format!("associated value expected for `{}`", ident)
|
||||||
} else {
|
} else {
|
||||||
"expected an associated value".to_string()
|
"expected an associated value".to_string()
|
||||||
};
|
};
|
||||||
|
|
|
@ -759,8 +759,9 @@ impl LintPass for DeprecatedAttr {
|
||||||
|
|
||||||
impl EarlyLintPass for DeprecatedAttr {
|
impl EarlyLintPass for DeprecatedAttr {
|
||||||
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
|
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
|
||||||
|
let name = attr.name_or_empty();
|
||||||
for &&(n, _, _, ref g) in &self.depr_attrs {
|
for &&(n, _, _, ref g) in &self.depr_attrs {
|
||||||
if attr.ident_str() == Some(n) {
|
if name == n {
|
||||||
if let &AttributeGate::Gated(Stability::Deprecated(link, suggestion),
|
if let &AttributeGate::Gated(Stability::Deprecated(link, suggestion),
|
||||||
ref name,
|
ref name,
|
||||||
ref reason,
|
ref reason,
|
||||||
|
|
|
@ -267,21 +267,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = attr.ident_str();
|
let name = attr.name_or_empty();
|
||||||
if !attr::is_used(attr) {
|
if !attr::is_used(attr) {
|
||||||
debug!("Emitting warning for: {:?}", attr);
|
debug!("Emitting warning for: {:?}", attr);
|
||||||
cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute");
|
cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute");
|
||||||
// Is it a builtin attribute that must be used at the crate level?
|
// Is it a builtin attribute that must be used at the crate level?
|
||||||
let known_crate = BUILTIN_ATTRIBUTES.iter()
|
let known_crate = BUILTIN_ATTRIBUTES.iter()
|
||||||
.find(|&&(builtin, ty, ..)| {
|
.find(|&&(builtin, ty, ..)| {
|
||||||
name == Some(builtin) && ty == AttributeType::CrateLevel
|
name == builtin && ty == AttributeType::CrateLevel
|
||||||
})
|
})
|
||||||
.is_some();
|
.is_some();
|
||||||
|
|
||||||
// Has a plugin registered this attribute as one that must be used at
|
// Has a plugin registered this attribute as one that must be used at
|
||||||
// the crate level?
|
// the crate level?
|
||||||
let plugin_crate = plugin_attributes.iter()
|
let plugin_crate = plugin_attributes.iter()
|
||||||
.find(|&&(ref x, t)| name == Some(x) && AttributeType::CrateLevel == t)
|
.find(|&&(ref x, t)| name == x.as_str() && AttributeType::CrateLevel == t)
|
||||||
.is_some();
|
.is_some();
|
||||||
if known_crate || plugin_crate {
|
if known_crate || plugin_crate {
|
||||||
let msg = match attr.style {
|
let msg = match attr.style {
|
||||||
|
|
|
@ -53,8 +53,7 @@ impl<'a, 'tcx> VarianceTest<'a, 'tcx> {
|
||||||
// The `..` are the names of fields to dump.
|
// The `..` are the names of fields to dump.
|
||||||
let meta_items = attr.meta_item_list().unwrap_or_default();
|
let meta_items = attr.meta_item_list().unwrap_or_default();
|
||||||
for meta_item in meta_items {
|
for meta_item in meta_items {
|
||||||
let name = meta_item.ident_str().unwrap_or("");
|
match meta_item.name_or_empty().get() {
|
||||||
match name {
|
|
||||||
"abi" => {
|
"abi" => {
|
||||||
self.tcx
|
self.tcx
|
||||||
.sess
|
.sess
|
||||||
|
@ -84,7 +83,7 @@ impl<'a, 'tcx> VarianceTest<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
name => {
|
||||||
self.tcx.sess.span_err(
|
self.tcx.sess.span_err(
|
||||||
meta_item.span(),
|
meta_item.span(),
|
||||||
&format!("unrecognized field name `{}`", name),
|
&format!("unrecognized field name `{}`", name),
|
||||||
|
|
|
@ -56,12 +56,12 @@ pub fn load_plugins(sess: &Session,
|
||||||
|
|
||||||
for plugin in plugins {
|
for plugin in plugins {
|
||||||
// plugins must have a name and can't be key = value
|
// plugins must have a name and can't be key = value
|
||||||
match plugin.ident_str() {
|
let name = plugin.name_or_empty();
|
||||||
Some(name) if !plugin.is_value_str() => {
|
if !name.is_empty() && !plugin.is_value_str() {
|
||||||
let args = plugin.meta_item_list().map(ToOwned::to_owned);
|
let args = plugin.meta_item_list().map(ToOwned::to_owned);
|
||||||
loader.load_plugin(plugin.span(), name, args.unwrap_or_default());
|
loader.load_plugin(plugin.span(), &name, args.unwrap_or_default());
|
||||||
},
|
} else {
|
||||||
_ => call_malformed_plugin_attribute(sess, attr.span),
|
call_malformed_plugin_attribute(sess, attr.span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -521,21 +521,21 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
|
||||||
for attr in krate.module.as_ref().unwrap().attrs.lists("doc") {
|
for attr in krate.module.as_ref().unwrap().attrs.lists("doc") {
|
||||||
let diag = ctxt.sess().diagnostic();
|
let diag = ctxt.sess().diagnostic();
|
||||||
|
|
||||||
let name = attr.ident_str();
|
let name = attr.name_or_empty();
|
||||||
if attr.is_word() {
|
if attr.is_word() {
|
||||||
if name == Some("no_default_passes") {
|
if name == "no_default_passes" {
|
||||||
report_deprecated_attr("no_default_passes", diag);
|
report_deprecated_attr("no_default_passes", diag);
|
||||||
if default_passes == passes::DefaultPassOption::Default {
|
if default_passes == passes::DefaultPassOption::Default {
|
||||||
default_passes = passes::DefaultPassOption::None;
|
default_passes = passes::DefaultPassOption::None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if let Some(value) = attr.value_str() {
|
} else if let Some(value) = attr.value_str() {
|
||||||
let sink = match name {
|
let sink = match name.get() {
|
||||||
Some("passes") => {
|
"passes" => {
|
||||||
report_deprecated_attr("passes = \"...\"", diag);
|
report_deprecated_attr("passes = \"...\"", diag);
|
||||||
&mut manual_passes
|
&mut manual_passes
|
||||||
},
|
},
|
||||||
Some("plugins") => {
|
"plugins" => {
|
||||||
report_deprecated_attr("plugins = \"...\"", diag);
|
report_deprecated_attr("plugins = \"...\"", diag);
|
||||||
eprintln!("WARNING: #![doc(plugins = \"...\")] no longer functions; \
|
eprintln!("WARNING: #![doc(plugins = \"...\")] no longer functions; \
|
||||||
see CVE-2018-1000622");
|
see CVE-2018-1000622");
|
||||||
|
@ -548,7 +548,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if attr.is_word() && name == Some("document_private_items") {
|
if attr.is_word() && name == "document_private_items" {
|
||||||
if default_passes == passes::DefaultPassOption::Default {
|
if default_passes == passes::DefaultPassOption::Default {
|
||||||
default_passes = passes::DefaultPassOption::Private;
|
default_passes = passes::DefaultPassOption::Private;
|
||||||
}
|
}
|
||||||
|
|
|
@ -562,23 +562,23 @@ pub fn run(mut krate: clean::Crate,
|
||||||
// going to emit HTML
|
// going to emit HTML
|
||||||
if let Some(attrs) = krate.module.as_ref().map(|m| &m.attrs) {
|
if let Some(attrs) = krate.module.as_ref().map(|m| &m.attrs) {
|
||||||
for attr in attrs.lists("doc") {
|
for attr in attrs.lists("doc") {
|
||||||
match (attr.ident_str(), attr.value_str()) {
|
match (attr.name_or_empty().get(), attr.value_str()) {
|
||||||
(Some("html_favicon_url"), Some(s)) => {
|
("html_favicon_url", Some(s)) => {
|
||||||
scx.layout.favicon = s.to_string();
|
scx.layout.favicon = s.to_string();
|
||||||
}
|
}
|
||||||
(Some("html_logo_url"), Some(s)) => {
|
("html_logo_url", Some(s)) => {
|
||||||
scx.layout.logo = s.to_string();
|
scx.layout.logo = s.to_string();
|
||||||
}
|
}
|
||||||
(Some("html_playground_url"), Some(s)) => {
|
("html_playground_url", Some(s)) => {
|
||||||
markdown::PLAYGROUND.with(|slot| {
|
markdown::PLAYGROUND.with(|slot| {
|
||||||
let name = krate.name.clone();
|
let name = krate.name.clone();
|
||||||
*slot.borrow_mut() = Some((Some(name), s.to_string()));
|
*slot.borrow_mut() = Some((Some(name), s.to_string()));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
(Some("issue_tracker_base_url"), Some(s)) => {
|
("issue_tracker_base_url", Some(s)) => {
|
||||||
scx.issue_tracker_base_url = Some(s.to_string());
|
scx.issue_tracker_base_url = Some(s.to_string());
|
||||||
}
|
}
|
||||||
(Some("html_no_source"), None) if attr.is_word() => {
|
("html_no_source", None) if attr.is_word() => {
|
||||||
scx.include_sources = false;
|
scx.include_sources = false;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -3749,7 +3749,7 @@ fn render_attributes(w: &mut fmt::Formatter<'_>, it: &clean::Item) -> fmt::Resul
|
||||||
let mut attrs = String::new();
|
let mut attrs = String::new();
|
||||||
|
|
||||||
for attr in &it.attrs.other_attrs {
|
for attr in &it.attrs.other_attrs {
|
||||||
if !attr.ident_str().map_or(false, |name| ATTRIBUTE_WHITELIST.contains(&name)) {
|
if !ATTRIBUTE_WHITELIST.contains(&attr.name_or_empty().get()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Some(s) = render_attribute(&attr.meta().unwrap()) {
|
if let Some(s) = render_attribute(&attr.meta().unwrap()) {
|
||||||
|
|
|
@ -222,9 +222,9 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
|
||||||
)+
|
)+
|
||||||
for meta in metas {
|
for meta in metas {
|
||||||
if let Some(mi) = meta.meta_item() {
|
if let Some(mi) = meta.meta_item() {
|
||||||
match mi.ident_str() {
|
match mi.name_or_empty().get() {
|
||||||
$(
|
$(
|
||||||
Some(stringify!($name))
|
stringify!($name)
|
||||||
=> if !get(mi, &mut $name) { continue 'outer },
|
=> if !get(mi, &mut $name) { continue 'outer },
|
||||||
)+
|
)+
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -252,7 +252,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match meta.ident_str().expect("not a stability level") {
|
match meta.name_or_empty().get() {
|
||||||
"rustc_deprecated" => {
|
"rustc_deprecated" => {
|
||||||
if rustc_depr.is_some() {
|
if rustc_depr.is_some() {
|
||||||
span_err!(diagnostic, item_sp, E0540,
|
span_err!(diagnostic, item_sp, E0540,
|
||||||
|
@ -306,10 +306,10 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
|
||||||
let mut issue = None;
|
let mut issue = None;
|
||||||
for meta in metas {
|
for meta in metas {
|
||||||
if let Some(mi) = meta.meta_item() {
|
if let Some(mi) = meta.meta_item() {
|
||||||
match mi.ident_str() {
|
match mi.name_or_empty().get() {
|
||||||
Some("feature") => if !get(mi, &mut feature) { continue 'outer },
|
"feature" => if !get(mi, &mut feature) { continue 'outer },
|
||||||
Some("reason") => if !get(mi, &mut reason) { continue 'outer },
|
"reason" => if !get(mi, &mut reason) { continue 'outer },
|
||||||
Some("issue") => if !get(mi, &mut issue) { continue 'outer },
|
"issue" => if !get(mi, &mut issue) { continue 'outer },
|
||||||
_ => {
|
_ => {
|
||||||
handle_errors(
|
handle_errors(
|
||||||
sess,
|
sess,
|
||||||
|
@ -377,10 +377,10 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
|
||||||
for meta in metas {
|
for meta in metas {
|
||||||
match meta {
|
match meta {
|
||||||
NestedMetaItem::MetaItem(mi) => {
|
NestedMetaItem::MetaItem(mi) => {
|
||||||
match mi.ident_str() {
|
match mi.name_or_empty().get() {
|
||||||
Some("feature") =>
|
"feature" =>
|
||||||
if !get(mi, &mut feature) { continue 'outer },
|
if !get(mi, &mut feature) { continue 'outer },
|
||||||
Some("since") =>
|
"since" =>
|
||||||
if !get(mi, &mut since) { continue 'outer },
|
if !get(mi, &mut since) { continue 'outer },
|
||||||
_ => {
|
_ => {
|
||||||
handle_errors(
|
handle_errors(
|
||||||
|
@ -532,14 +532,14 @@ pub fn eval_condition<F>(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F)
|
||||||
|
|
||||||
// The unwraps below may look dangerous, but we've already asserted
|
// The unwraps below may look dangerous, but we've already asserted
|
||||||
// that they won't fail with the loop above.
|
// that they won't fail with the loop above.
|
||||||
match cfg.ident_str() {
|
match cfg.name_or_empty().get() {
|
||||||
Some("any") => mis.iter().any(|mi| {
|
"any" => mis.iter().any(|mi| {
|
||||||
eval_condition(mi.meta_item().unwrap(), sess, eval)
|
eval_condition(mi.meta_item().unwrap(), sess, eval)
|
||||||
}),
|
}),
|
||||||
Some("all") => mis.iter().all(|mi| {
|
"all" => mis.iter().all(|mi| {
|
||||||
eval_condition(mi.meta_item().unwrap(), sess, eval)
|
eval_condition(mi.meta_item().unwrap(), sess, eval)
|
||||||
}),
|
}),
|
||||||
Some("not") => {
|
"not" => {
|
||||||
if mis.len() != 1 {
|
if mis.len() != 1 {
|
||||||
span_err!(sess.span_diagnostic, cfg.span, E0536, "expected 1 cfg-pattern");
|
span_err!(sess.span_diagnostic, cfg.span, E0536, "expected 1 cfg-pattern");
|
||||||
return false;
|
return false;
|
||||||
|
@ -635,9 +635,9 @@ fn find_deprecation_generic<'a, I>(sess: &ParseSess,
|
||||||
for meta in list {
|
for meta in list {
|
||||||
match meta {
|
match meta {
|
||||||
NestedMetaItem::MetaItem(mi) => {
|
NestedMetaItem::MetaItem(mi) => {
|
||||||
match mi.ident_str() {
|
match mi.name_or_empty().get() {
|
||||||
Some("since") => if !get(mi, &mut since) { continue 'outer },
|
"since" => if !get(mi, &mut since) { continue 'outer },
|
||||||
Some("note") => if !get(mi, &mut note) { continue 'outer },
|
"note" => if !get(mi, &mut note) { continue 'outer },
|
||||||
_ => {
|
_ => {
|
||||||
handle_errors(
|
handle_errors(
|
||||||
sess,
|
sess,
|
||||||
|
@ -729,12 +729,12 @@ pub fn find_repr_attrs(sess: &ParseSess, attr: &Attribute) -> Vec<ReprAttr> {
|
||||||
|
|
||||||
let mut recognised = false;
|
let mut recognised = false;
|
||||||
if item.is_word() {
|
if item.is_word() {
|
||||||
let hint = match item.ident_str() {
|
let hint = match item.name_or_empty().get() {
|
||||||
Some("C") => Some(ReprC),
|
"C" => Some(ReprC),
|
||||||
Some("packed") => Some(ReprPacked(1)),
|
"packed" => Some(ReprPacked(1)),
|
||||||
Some("simd") => Some(ReprSimd),
|
"simd" => Some(ReprSimd),
|
||||||
Some("transparent") => Some(ReprTransparent),
|
"transparent" => Some(ReprTransparent),
|
||||||
name => name.and_then(|name| int_type_of_word(name)).map(ReprInt),
|
name => int_type_of_word(name).map(ReprInt),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(h) = hint {
|
if let Some(h) = hint {
|
||||||
|
|
|
@ -22,7 +22,7 @@ use crate::parse::parser::Parser;
|
||||||
use crate::parse::{self, ParseSess, PResult};
|
use crate::parse::{self, ParseSess, PResult};
|
||||||
use crate::parse::token::{self, Token};
|
use crate::parse::token::{self, Token};
|
||||||
use crate::ptr::P;
|
use crate::ptr::P;
|
||||||
use crate::symbol::Symbol;
|
use crate::symbol::{keywords, LocalInternedString, Symbol};
|
||||||
use crate::ThinVec;
|
use crate::ThinVec;
|
||||||
use crate::tokenstream::{TokenStream, TokenTree, DelimSpan};
|
use crate::tokenstream::{TokenStream, TokenTree, DelimSpan};
|
||||||
use crate::GLOBALS;
|
use crate::GLOBALS;
|
||||||
|
@ -89,8 +89,8 @@ impl NestedMetaItem {
|
||||||
pub fn ident(&self) -> Option<Ident> {
|
pub fn ident(&self) -> Option<Ident> {
|
||||||
self.meta_item().and_then(|meta_item| meta_item.ident())
|
self.meta_item().and_then(|meta_item| meta_item.ident())
|
||||||
}
|
}
|
||||||
pub fn ident_str(&self) -> Option<&str> {
|
pub fn name_or_empty(&self) -> LocalInternedString {
|
||||||
self.ident().map(|name| name.as_str().get())
|
self.ident().unwrap_or(keywords::Invalid.ident()).name.as_str()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the string value if self is a MetaItem and the MetaItem is a
|
/// Gets the string value if self is a MetaItem and the MetaItem is a
|
||||||
|
@ -167,8 +167,8 @@ impl Attribute {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn ident_str(&self) -> Option<&str> {
|
pub fn name_or_empty(&self) -> LocalInternedString {
|
||||||
self.ident().map(|name| name.as_str().get())
|
self.ident().unwrap_or(keywords::Invalid.ident()).name.as_str()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn value_str(&self) -> Option<Symbol> {
|
pub fn value_str(&self) -> Option<Symbol> {
|
||||||
|
@ -205,8 +205,8 @@ impl MetaItem {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn ident_str(&self) -> Option<&str> {
|
pub fn name_or_empty(&self) -> LocalInternedString {
|
||||||
self.ident().map(|name| name.as_str().get())
|
self.ident().unwrap_or(keywords::Invalid.ident()).name.as_str()
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[attribute(name = "value")]
|
// #[attribute(name = "value")]
|
||||||
|
|
|
@ -1341,9 +1341,9 @@ macro_rules! gate_feature {
|
||||||
impl<'a> Context<'a> {
|
impl<'a> Context<'a> {
|
||||||
fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
|
fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
|
||||||
debug!("check_attribute(attr = {:?})", attr);
|
debug!("check_attribute(attr = {:?})", attr);
|
||||||
let name = attr.ident_str();
|
let name = attr.name_or_empty();
|
||||||
for &(n, ty, _template, ref gateage) in BUILTIN_ATTRIBUTES {
|
for &(n, ty, _template, ref gateage) in BUILTIN_ATTRIBUTES {
|
||||||
if name == Some(n) {
|
if name == n {
|
||||||
if let Gated(_, name, desc, ref has_feature) = *gateage {
|
if let Gated(_, name, desc, ref has_feature) = *gateage {
|
||||||
if !attr.span.allows_unstable(name) {
|
if !attr.span.allows_unstable(name) {
|
||||||
gate_feature_fn!(
|
gate_feature_fn!(
|
||||||
|
@ -1373,7 +1373,7 @@ impl<'a> Context<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !attr::is_known(attr) {
|
if !attr::is_known(attr) {
|
||||||
if name.map_or(false, |name| name.starts_with("rustc_")) {
|
if name.starts_with("rustc_") {
|
||||||
let msg = "unless otherwise specified, attributes with the prefix `rustc_` \
|
let msg = "unless otherwise specified, attributes with the prefix `rustc_` \
|
||||||
are reserved for internal compiler diagnostics";
|
are reserved for internal compiler diagnostics";
|
||||||
gate_feature!(self, rustc_attrs, attr.span, msg);
|
gate_feature!(self, rustc_attrs, attr.span, msg);
|
||||||
|
@ -2054,12 +2054,12 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
|
||||||
};
|
};
|
||||||
|
|
||||||
for mi in list {
|
for mi in list {
|
||||||
let name = match mi.ident_str() {
|
if !mi.is_word() {
|
||||||
Some(name) if mi.is_word() => name,
|
continue;
|
||||||
_ => continue,
|
}
|
||||||
};
|
|
||||||
|
|
||||||
if incomplete_features.iter().any(|f| *f == name) {
|
let name = mi.name_or_empty();
|
||||||
|
if incomplete_features.iter().any(|f| name == *f) {
|
||||||
span_handler.struct_span_warn(
|
span_handler.struct_span_warn(
|
||||||
mi.span(),
|
mi.span(),
|
||||||
&format!(
|
&format!(
|
||||||
|
|
|
@ -463,9 +463,10 @@ impl<'a> TraitDef<'a> {
|
||||||
let mut attrs = newitem.attrs.clone();
|
let mut attrs = newitem.attrs.clone();
|
||||||
attrs.extend(item.attrs
|
attrs.extend(item.attrs
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|a| a.ident_str().map_or(false, |name| {
|
.filter(|a| {
|
||||||
["allow", "warn", "deny", "forbid", "stable", "unstable"].contains(&name)
|
["allow", "warn", "deny", "forbid", "stable", "unstable"]
|
||||||
}))
|
.contains(&a.name_or_empty().get())
|
||||||
|
})
|
||||||
.cloned());
|
.cloned());
|
||||||
push(Annotatable::Item(P(ast::Item { attrs: attrs, ..(*newitem).clone() })))
|
push(Annotatable::Item(P(ast::Item { attrs: attrs, ..(*newitem).clone() })))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue