Skip to content

Commit 8371caf

Browse files
committed
syntax: Do not accidentally treat multi-segment meta-items as single-segment
1 parent e2009ea commit 8371caf

File tree

29 files changed

+236
-213
lines changed

29 files changed

+236
-213
lines changed

src/librustc/hir/check_attr.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
166166
// ```
167167
let hints: Vec<_> = item.attrs
168168
.iter()
169-
.filter(|attr| attr.name() == "repr")
169+
.filter(|attr| attr.check_name("repr"))
170170
.filter_map(|attr| attr.meta_item_list())
171171
.flatten()
172172
.collect();
@@ -177,15 +177,15 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
177177
let mut is_transparent = false;
178178

179179
for hint in &hints {
180-
let name = if let Some(name) = hint.name() {
180+
let name = if let Some(name) = hint.ident_str() {
181181
name
182182
} else {
183183
// Invalid repr hint like repr(42). We don't check for unrecognized hints here
184184
// (libsyntax does that), so just ignore it.
185185
continue;
186186
};
187187

188-
let (article, allowed_targets) = match &*name.as_str() {
188+
let (article, allowed_targets) = match name {
189189
"C" | "align" => {
190190
is_c |= name == "C";
191191
if target != Target::Struct &&
@@ -313,7 +313,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
313313

314314
fn check_used(&self, item: &hir::Item, target: Target) {
315315
for attr in &item.attrs {
316-
if attr.name() == "used" && target != Target::Static {
316+
if attr.check_name("used") && target != Target::Static {
317317
self.tcx.sess
318318
.span_err(attr.span, "attribute must be applied to a `static` variable");
319319
}

src/librustc/ich/impls_syntax.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,8 @@ impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
197197
let filtered: SmallVec<[&ast::Attribute; 8]> = self
198198
.iter()
199199
.filter(|attr| {
200-
!attr.is_sugared_doc && !hcx.is_ignored_attr(attr.name())
200+
!attr.is_sugared_doc &&
201+
!attr.ident().map_or(false, |ident| hcx.is_ignored_attr(ident.name))
201202
})
202203
.collect();
203204

@@ -224,7 +225,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for ast::Attribute {
224225
hcx: &mut StableHashingContext<'a>,
225226
hasher: &mut StableHasher<W>) {
226227
// Make sure that these have been filtered out.
227-
debug_assert!(!hcx.is_ignored_attr(self.name()));
228+
debug_assert!(!self.ident().map_or(false, |ident| hcx.is_ignored_attr(ident.name)));
228229
debug_assert!(!self.is_sugared_doc);
229230

230231
let ast::Attribute {

src/librustc/lint/levels.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ impl<'a> LintLevelsBuilder<'a> {
194194
struct_span_err!(sess, span, E0452, "malformed lint attribute")
195195
};
196196
for attr in attrs {
197-
let level = match Level::from_str(&attr.name().as_str()) {
197+
let level = match attr.ident_str().and_then(|name| Level::from_str(name)) {
198198
None => continue,
199199
Some(lvl) => lvl,
200200
};
@@ -255,9 +255,9 @@ impl<'a> LintLevelsBuilder<'a> {
255255
}
256256

257257
for li in metas {
258-
let word = match li.word() {
259-
Some(word) => word,
260-
None => {
258+
let meta_item = match li.meta_item() {
259+
Some(meta_item) if meta_item.is_word() => meta_item,
260+
_ => {
261261
let mut err = bad_attr(li.span);
262262
if let Some(item) = li.meta_item() {
263263
if let ast::MetaItemKind::NameValue(_) = item.node {
@@ -270,23 +270,24 @@ impl<'a> LintLevelsBuilder<'a> {
270270
continue;
271271
}
272272
};
273-
let tool_name = if let Some(lint_tool) = word.is_scoped() {
274-
if !attr::is_known_lint_tool(lint_tool) {
273+
let tool_name = if meta_item.ident.segments.len() > 1 {
274+
let tool_ident = meta_item.ident.segments[0].ident;
275+
if !attr::is_known_lint_tool(tool_ident) {
275276
span_err!(
276277
sess,
277-
lint_tool.span,
278+
tool_ident.span,
278279
E0710,
279280
"an unknown tool name found in scoped lint: `{}`",
280-
word.ident
281+
meta_item.ident
281282
);
282283
continue;
283284
}
284285

285-
Some(lint_tool.as_str())
286+
Some(tool_ident.as_str())
286287
} else {
287288
None
288289
};
289-
let name = word.name();
290+
let name = meta_item.ident.segments.last().expect("empty lint name").ident.name;
290291
match store.check_lint_name(&name.as_str(), tool_name) {
291292
CheckLintNameResult::Ok(ids) => {
292293
let src = LintSource::Node(name, li.span, reason);

src/librustc/middle/lib_features.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,9 @@ impl<'a, 'tcx> LibFeatureCollector<'a, 'tcx> {
6565
for meta in metas {
6666
if let Some(mi) = meta.meta_item() {
6767
// Find the `feature = ".."` meta-item.
68-
match (&*mi.name().as_str(), mi.value_str()) {
69-
("feature", val) => feature = val,
70-
("since", val) => since = val,
68+
match (mi.ident_str(), mi.value_str()) {
69+
(Some("feature"), val) => feature = val,
70+
(Some("since"), val) => since = val,
7171
_ => {}
7272
}
7373
}

src/librustc/middle/stability.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -194,11 +194,12 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
194194
} else {
195195
// Emit errors for non-staged-api crates.
196196
for attr in attrs {
197-
let tag = attr.name();
198-
if tag == "unstable" || tag == "stable" || tag == "rustc_deprecated" {
199-
attr::mark_used(attr);
200-
self.tcx.sess.span_err(attr.span(), "stability attributes may not be used \
201-
outside of the standard library");
197+
if let Some(tag) = attr.ident_str() {
198+
if tag == "unstable" || tag == "stable" || tag == "rustc_deprecated" {
199+
attr::mark_used(attr);
200+
self.tcx.sess.span_err(attr.span, "stability attributes may not be used \
201+
outside of the standard library");
202+
}
202203
}
203204
}
204205

src/librustc/session/config.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1850,7 +1850,8 @@ pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> FxHashSet<(String, Option<String
18501850
error!("argument value must be a string");
18511851
}
18521852
MetaItemKind::NameValue(..) | MetaItemKind::Word => {
1853-
return (meta_item.name(), meta_item.value_str());
1853+
let ident = meta_item.ident().expect("multi-segment cfg key");
1854+
return (ident.name, meta_item.value_str());
18541855
}
18551856
}
18561857
}

src/librustc/traits/on_unimplemented.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,10 +177,12 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
177177
for command in self.subcommands.iter().chain(Some(self)).rev() {
178178
if let Some(ref condition) = command.condition {
179179
if !attr::eval_condition(condition, &tcx.sess.parse_sess, &mut |c| {
180-
options.contains(&(
181-
c.name().as_str().to_string(),
182-
c.value_str().map(|s| s.as_str().to_string())
183-
))
180+
c.ident_str().map_or(false, |name| {
181+
options.contains(&(
182+
name.to_string(),
183+
c.value_str().map(|s| s.as_str().to_string())
184+
))
185+
})
184186
}) {
185187
debug!("evaluate: skipping {:?} due to condition", command);
186188
continue

src/librustc_incremental/assert_dep_graph.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,9 @@ impl<'a, 'tcx> IfThisChanged<'a, 'tcx> {
9999
fn argument(&self, attr: &ast::Attribute) -> Option<ast::Name> {
100100
let mut value = None;
101101
for list_item in attr.meta_item_list().unwrap_or_default() {
102-
match list_item.word() {
103-
Some(word) if value.is_none() =>
104-
value = Some(word.name()),
102+
match list_item.ident() {
103+
Some(ident) if list_item.is_word() && value.is_none() =>
104+
value = Some(ident.name),
105105
_ =>
106106
// FIXME better-encapsulate meta_item (don't directly access `node`)
107107
span_bug!(list_item.span(), "unexpected meta-item {:?}", list_item.node),

src/librustc_incremental/persist/dirty_clean.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ fn expect_associated_value(tcx: TyCtxt<'_, '_, '_>, item: &NestedMetaItem) -> as
576576
if let Some(value) = item.value_str() {
577577
value
578578
} else {
579-
let msg = if let Some(name) = item.name() {
579+
let msg = if let Some(name) = item.ident_str() {
580580
format!("associated value expected for `{}`", name)
581581
} else {
582582
"expected an associated value".to_string()

src/librustc_lint/builtin.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,7 @@ impl LintPass for DeprecatedAttr {
760760
impl EarlyLintPass for DeprecatedAttr {
761761
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
762762
for &&(n, _, _, ref g) in &self.depr_attrs {
763-
if attr.name() == n {
763+
if attr.ident_str() == Some(n) {
764764
if let &AttributeGate::Gated(Stability::Deprecated(link, suggestion),
765765
ref name,
766766
ref reason,

src/librustc_lint/unused.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -267,19 +267,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes {
267267
}
268268
}
269269

270-
let name = attr.name();
270+
let name = attr.ident_str();
271271
if !attr::is_used(attr) {
272272
debug!("Emitting warning for: {:?}", attr);
273273
cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute");
274274
// Is it a builtin attribute that must be used at the crate level?
275275
let known_crate = BUILTIN_ATTRIBUTES.iter()
276-
.find(|&&(builtin, ty, ..)| name == builtin && ty == AttributeType::CrateLevel)
276+
.find(|&&(builtin, ty, ..)| {
277+
name == Some(builtin) && ty == AttributeType::CrateLevel
278+
})
277279
.is_some();
278280

279281
// Has a plugin registered this attribute as one that must be used at
280282
// the crate level?
281283
let plugin_crate = plugin_attributes.iter()
282-
.find(|&&(ref x, t)| name == &**x && AttributeType::CrateLevel == t)
284+
.find(|&&(ref x, t)| name == Some(x) && AttributeType::CrateLevel == t)
283285
.is_some();
284286
if known_crate || plugin_crate {
285287
let msg = match attr.style {

src/librustc_passes/layout_test.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,7 @@ impl<'a, 'tcx> VarianceTest<'a, 'tcx> {
5353
// The `..` are the names of fields to dump.
5454
let meta_items = attr.meta_item_list().unwrap_or_default();
5555
for meta_item in meta_items {
56-
let name = meta_item.word().map(|mi| mi.name().as_str());
57-
let name = name.as_ref().map(|s| &s[..]).unwrap_or("");
58-
56+
let name = meta_item.ident_str().unwrap_or("");
5957
match name {
6058
"abi" => {
6159
self.tcx

src/librustc_plugin/load.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ pub fn load_plugins(sess: &Session,
5656

5757
for plugin in plugins {
5858
// plugins must have a name and can't be key = value
59-
match plugin.name() {
59+
match plugin.ident_str() {
6060
Some(name) if !plugin.is_value_str() => {
6161
let args = plugin.meta_item_list().map(ToOwned::to_owned);
62-
loader.load_plugin(plugin.span, &name.as_str(), args.unwrap_or_default());
62+
loader.load_plugin(plugin.span, name, args.unwrap_or_default());
6363
},
6464
_ => call_malformed_plugin_attribute(sess, attr.span),
6565
}

src/librustc_resolve/build_reduced_graph.rs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -463,10 +463,9 @@ impl<'a> Resolver<'a> {
463463
if let Some(attr) = attr::find_by_name(&item.attrs, "proc_macro_derive") {
464464
if let Some(trait_attr) =
465465
attr.meta_item_list().and_then(|list| list.get(0).cloned()) {
466-
if let Some(ident) = trait_attr.name().map(Ident::with_empty_ctxt) {
467-
let sp = trait_attr.span;
466+
if let Some(ident) = trait_attr.ident() {
468467
let def = Def::Macro(def.def_id(), MacroKind::ProcMacroStub);
469-
self.define(parent, ident, MacroNS, (def, vis, sp, expansion));
468+
self.define(parent, ident, MacroNS, (def, vis, ident.span, expansion));
470469
}
471470
}
472471
}
@@ -812,9 +811,9 @@ impl<'a> Resolver<'a> {
812811
break;
813812
}
814813
MetaItemKind::List(nested_metas) => for nested_meta in nested_metas {
815-
match nested_meta.word() {
816-
Some(word) => single_imports.push((word.name(), word.span)),
817-
None => ill_formed(nested_meta.span),
814+
match nested_meta.ident() {
815+
Some(ident) if nested_meta.is_word() => single_imports.push(ident),
816+
_ => ill_formed(nested_meta.span),
818817
}
819818
}
820819
MetaItemKind::NameValue(..) => ill_formed(meta.span),
@@ -850,23 +849,23 @@ impl<'a> Resolver<'a> {
850849
self.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing);
851850
});
852851
} else {
853-
for (name, span) in single_imports.iter().cloned() {
854-
let ident = Ident::with_empty_ctxt(name);
852+
for ident in single_imports.iter().cloned() {
855853
let result = self.resolve_ident_in_module(
856854
ModuleOrUniformRoot::Module(module),
857855
ident,
858856
MacroNS,
859857
None,
860858
false,
861-
span,
859+
ident.span,
862860
);
863861
if let Ok(binding) = result {
864-
let directive = macro_use_directive(span);
862+
let directive = macro_use_directive(ident.span);
865863
self.potentially_unused_imports.push(directive);
866864
let imported_binding = self.import(binding, directive);
867-
self.legacy_import_macro(name, imported_binding, span, allow_shadowing);
865+
self.legacy_import_macro(ident.name, imported_binding,
866+
ident.span, allow_shadowing);
868867
} else {
869-
span_err!(self.session, span, E0469, "imported macro not found");
868+
span_err!(self.session, ident.span, E0469, "imported macro not found");
870869
}
871870
}
872871
}

src/librustdoc/clean/cfg.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,13 @@ impl Cfg {
5858
/// If the content is not properly formatted, it will return an error indicating what and where
5959
/// the error is.
6060
pub fn parse(cfg: &MetaItem) -> Result<Cfg, InvalidCfgError> {
61-
let name = cfg.name();
61+
let name = match cfg.ident() {
62+
Some(ident) => ident.name,
63+
None => return Err(InvalidCfgError {
64+
msg: "expected a single identifier",
65+
span: cfg.span
66+
}),
67+
};
6268
match cfg.node {
6369
MetaItemKind::Word => Ok(Cfg::Cfg(name, None)),
6470
MetaItemKind::NameValue(ref lit) => match lit.node {

src/librustdoc/clean/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ impl Item {
492492

493493
pub fn is_non_exhaustive(&self) -> bool {
494494
self.attrs.other_attrs.iter()
495-
.any(|a| a.name().as_str() == "non_exhaustive")
495+
.any(|a| a.check_name("non_exhaustive"))
496496
}
497497

498498
/// Returns a documentation-level item type from the item.
@@ -3683,7 +3683,7 @@ impl Clean<Vec<Item>> for doctree::ExternCrate {
36833683
fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
36843684

36853685
let please_inline = self.vis.node.is_pub() && self.attrs.iter().any(|a| {
3686-
a.name() == "doc" && match a.meta_item_list() {
3686+
a.check_name("doc") && match a.meta_item_list() {
36873687
Some(l) => attr::list_contains_name(&l, "inline"),
36883688
None => false,
36893689
}
@@ -3722,7 +3722,7 @@ impl Clean<Vec<Item>> for doctree::Import {
37223722
// #[doc(no_inline)] attribute is present.
37233723
// Don't inline doc(hidden) imports so they can be stripped at a later stage.
37243724
let mut denied = !self.vis.node.is_pub() || self.attrs.iter().any(|a| {
3725-
a.name() == "doc" && match a.meta_item_list() {
3725+
a.check_name("doc") && match a.meta_item_list() {
37263726
Some(l) => attr::list_contains_name(&l, "no_inline") ||
37273727
attr::list_contains_name(&l, "hidden"),
37283728
None => false,

src/librustdoc/core.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -521,8 +521,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
521521
for attr in krate.module.as_ref().unwrap().attrs.lists("doc") {
522522
let diag = ctxt.sess().diagnostic();
523523

524-
let name = attr.name().map(|s| s.as_str());
525-
let name = name.as_ref().map(|s| &s[..]);
524+
let name = attr.ident_str();
526525
if attr.is_word() {
527526
if name == Some("no_default_passes") {
528527
report_deprecated_attr("no_default_passes", diag);

src/librustdoc/html/render.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -562,8 +562,7 @@ pub fn run(mut krate: clean::Crate,
562562
// going to emit HTML
563563
if let Some(attrs) = krate.module.as_ref().map(|m| &m.attrs) {
564564
for attr in attrs.lists("doc") {
565-
let name = attr.name().map(|s| s.as_str());
566-
match (name.as_ref().map(|s| &s[..]), attr.value_str()) {
565+
match (attr.ident_str(), attr.value_str()) {
567566
(Some("html_favicon_url"), Some(s)) => {
568567
scx.layout.favicon = s.to_string();
569568
}
@@ -3714,19 +3713,19 @@ fn item_enum(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item,
37143713
}
37153714

37163715
fn render_attribute(attr: &ast::MetaItem) -> Option<String> {
3717-
let name = attr.name();
3716+
let path = attr.ident.to_string();
37183717

37193718
if attr.is_word() {
3720-
Some(name.to_string())
3719+
Some(path)
37213720
} else if let Some(v) = attr.value_str() {
3722-
Some(format!("{} = {:?}", name, v.as_str()))
3721+
Some(format!("{} = {:?}", path, v.as_str()))
37233722
} else if let Some(values) = attr.meta_item_list() {
37243723
let display: Vec<_> = values.iter().filter_map(|attr| {
37253724
attr.meta_item().and_then(|mi| render_attribute(mi))
37263725
}).collect();
37273726

37283727
if display.len() > 0 {
3729-
Some(format!("{}({})", name, display.join(", ")))
3728+
Some(format!("{}({})", path, display.join(", ")))
37303729
} else {
37313730
None
37323731
}
@@ -3750,8 +3749,7 @@ fn render_attributes(w: &mut fmt::Formatter<'_>, it: &clean::Item) -> fmt::Resul
37503749
let mut attrs = String::new();
37513750

37523751
for attr in &it.attrs.other_attrs {
3753-
let name = attr.name();
3754-
if !ATTRIBUTE_WHITELIST.contains(&&*name.as_str()) {
3752+
if !attr.ident_str().map_or(false, |name| ATTRIBUTE_WHITELIST.contains(&name)) {
37553753
continue;
37563754
}
37573755
if let Some(s) = render_attribute(&attr.meta().unwrap()) {

0 commit comments

Comments
 (0)