Skip to content

Commit 7cf074a

Browse files
committed
Auto merge of #58899 - petrochenkov:derval2, r=estebank
Do not accidentally treat multi-segment meta-items as single-segment Fixes #55168 and many other regressions from #50030 Basically, attributes like `#[any::prefix::foo]` were commonly interpreted as `#[foo]` due to `name()` successfully returning the last segment (this applies to nested things as well `#[attr(any::prefix::foo)]`).
2 parents 2c8bbf5 + 2fd4cbb commit 7cf074a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+565
-511
lines changed

src/librustc/hir/check_attr.rs

+6-6
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 &&
@@ -233,7 +233,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
233233
_ => continue,
234234
};
235235
self.emit_repr_error(
236-
hint.span,
236+
hint.span(),
237237
item.span,
238238
&format!("attribute should be applied to {}", allowed_targets),
239239
&format!("not {} {}", article, allowed_targets),
@@ -242,7 +242,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
242242

243243
// Just point at all repr hints if there are any incompatibilities.
244244
// This is not ideal, but tracking precisely which ones are at fault is a huge hassle.
245-
let hint_spans = hints.iter().map(|hint| hint.span);
245+
let hint_spans = hints.iter().map(|hint| hint.span());
246246

247247
// Error on repr(transparent, <anything else>).
248248
if is_transparent && hints.len() > 1 {
@@ -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

+5-6
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 {
@@ -359,15 +360,13 @@ fn hash_token<'a, 'gcx, W: StableHasherResult>(
359360
}
360361
}
361362

362-
impl_stable_hash_for_spanned!(::syntax::ast::NestedMetaItemKind);
363-
364-
impl_stable_hash_for!(enum ::syntax::ast::NestedMetaItemKind {
363+
impl_stable_hash_for!(enum ::syntax::ast::NestedMetaItem {
365364
MetaItem(meta_item),
366365
Literal(lit)
367366
});
368367

369368
impl_stable_hash_for!(struct ::syntax::ast::MetaItem {
370-
ident,
369+
path,
371370
node,
372371
span
373372
});

src/librustc/lint/levels.rs

+23-22
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
};
@@ -221,7 +221,7 @@ impl<'a> LintLevelsBuilder<'a> {
221221
match item.node {
222222
ast::MetaItemKind::Word => {} // actual lint names handled later
223223
ast::MetaItemKind::NameValue(ref name_value) => {
224-
if item.ident == "reason" {
224+
if item.path == "reason" {
225225
// found reason, reslice meta list to exclude it
226226
metas = &metas[0..metas.len()-1];
227227
// FIXME (#55112): issue unused-attributes lint if we thereby
@@ -255,13 +255,13 @@ impl<'a> LintLevelsBuilder<'a> {
255255
}
256256

257257
for li in metas {
258-
let word = match li.word() {
259-
Some(word) => word,
260-
None => {
261-
let mut err = bad_attr(li.span);
258+
let meta_item = match li.meta_item() {
259+
Some(meta_item) if meta_item.is_word() => meta_item,
260+
_ => {
261+
let mut err = bad_attr(li.span());
262262
if let Some(item) = li.meta_item() {
263263
if let ast::MetaItemKind::NameValue(_) = item.node {
264-
if item.ident == "reason" {
264+
if item.path == "reason" {
265265
err.help("reason in lint attribute must come last");
266266
}
267267
}
@@ -270,26 +270,27 @@ 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.path.segments.len() > 1 {
274+
let tool_ident = meta_item.path.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.path
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.path.segments.last().expect("empty lint name").ident.name;
290291
match store.check_lint_name(&name.as_str(), tool_name) {
291292
CheckLintNameResult::Ok(ids) => {
292-
let src = LintSource::Node(name, li.span, reason);
293+
let src = LintSource::Node(name, li.span(), reason);
293294
for id in ids {
294295
specs.insert(*id, (level, src));
295296
}
@@ -300,7 +301,7 @@ impl<'a> LintLevelsBuilder<'a> {
300301
Ok(ids) => {
301302
let complete_name = &format!("{}::{}", tool_name.unwrap(), name);
302303
let src = LintSource::Node(
303-
Symbol::intern(complete_name), li.span, reason
304+
Symbol::intern(complete_name), li.span(), reason
304305
);
305306
for id in ids {
306307
specs.insert(*id, (level, src));
@@ -322,18 +323,18 @@ impl<'a> LintLevelsBuilder<'a> {
322323
lint,
323324
lvl,
324325
src,
325-
Some(li.span.into()),
326+
Some(li.span().into()),
326327
&msg,
327328
);
328329
err.span_suggestion(
329-
li.span,
330+
li.span(),
330331
"change it to",
331332
new_lint_name.to_string(),
332333
Applicability::MachineApplicable,
333334
).emit();
334335

335336
let src = LintSource::Node(
336-
Symbol::intern(&new_lint_name), li.span, reason
337+
Symbol::intern(&new_lint_name), li.span(), reason
337338
);
338339
for id in ids {
339340
specs.insert(*id, (level, src));
@@ -360,11 +361,11 @@ impl<'a> LintLevelsBuilder<'a> {
360361
lint,
361362
level,
362363
src,
363-
Some(li.span.into()),
364+
Some(li.span().into()),
364365
&msg);
365366
if let Some(new_name) = renamed {
366367
err.span_suggestion(
367-
li.span,
368+
li.span(),
368369
"use the new name",
369370
new_name,
370371
Applicability::MachineApplicable
@@ -383,12 +384,12 @@ impl<'a> LintLevelsBuilder<'a> {
383384
lint,
384385
level,
385386
src,
386-
Some(li.span.into()),
387+
Some(li.span().into()),
387388
&msg);
388389

389390
if let Some(suggestion) = suggestion {
390391
db.span_suggestion(
391-
li.span,
392+
li.span(),
392393
"did you mean",
393394
suggestion.to_string(),
394395
Applicability::MachineApplicable,

src/librustc/lint/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,7 @@ pub fn struct_lint_level<'a>(sess: &'a Session,
724724
pub fn maybe_lint_level_root(tcx: TyCtxt<'_, '_, '_>, id: hir::HirId) -> bool {
725725
let attrs = tcx.hir().attrs_by_hir_id(id);
726726
for attr in attrs {
727-
if Level::from_str(&attr.name().as_str()).is_some() {
727+
if attr.ident_str().and_then(Level::from_str).is_some() {
728728
return true;
729729
}
730730
}

src/librustc/middle/lib_features.rs

+3-3
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

+6-5
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

+3-2
Original file line numberDiff line numberDiff line change
@@ -1839,7 +1839,7 @@ pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> FxHashSet<(String, Option<String
18391839

18401840
match &mut parser.parse_meta_item() {
18411841
Ok(meta_item) if parser.token == token::Eof => {
1842-
if meta_item.ident.segments.len() != 1 {
1842+
if meta_item.path.segments.len() != 1 {
18431843
error!("argument key must be an identifier");
18441844
}
18451845
match &meta_item.node {
@@ -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

+8-6
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
107107
{
108108
if let Some(items) = item.meta_item_list() {
109109
if let Ok(subcommand) =
110-
Self::parse(tcx, trait_def_id, &items, item.span, false)
110+
Self::parse(tcx, trait_def_id, &items, item.span(), false)
111111
{
112112
subcommands.push(subcommand);
113113
} else {
@@ -118,7 +118,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
118118
}
119119

120120
// nothing found
121-
parse_error(tcx, item.span,
121+
parse_error(tcx, item.span(),
122122
"this attribute must have a valid value",
123123
"expected value here",
124124
Some(r#"eg `#[rustc_on_unimplemented(message="foo")]`"#));
@@ -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_driver/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -683,7 +683,7 @@ impl RustcDefaultCalls {
683683

684684
let mut cfgs = sess.parse_sess.config.iter().filter_map(|&(name, ref value)| {
685685
let gated_cfg = GatedCfg::gate(&ast::MetaItem {
686-
ident: ast::Path::from_ident(ast::Ident::with_empty_ctxt(name)),
686+
path: ast::Path::from_ident(ast::Ident::with_empty_ctxt(name)),
687687
node: ast::MetaItemKind::Word,
688688
span: DUMMY_SP,
689689
});

src/librustc_incremental/assert_dep_graph.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,12 @@ 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`)
107-
span_bug!(list_item.span(), "unexpected meta-item {:?}", list_item.node),
107+
span_bug!(list_item.span(), "unexpected meta-item {:?}", list_item),
108108
}
109109
}
110110
value

src/librustc_incremental/assert_module_sources.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> {
153153
return value;
154154
} else {
155155
self.tcx.sess.span_fatal(
156-
item.span,
156+
item.span(),
157157
&format!("associated value expected for `{}`", name));
158158
}
159159
}

src/librustc_incremental/persist/dirty_clean.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -430,13 +430,13 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
430430
if DepNode::has_label_string(label) {
431431
if out.contains(label) {
432432
self.tcx.sess.span_fatal(
433-
item.span,
433+
item.span(),
434434
&format!("dep-node label `{}` is repeated", label));
435435
}
436436
out.insert(label.to_string());
437437
} else {
438438
self.tcx.sess.span_fatal(
439-
item.span,
439+
item.span(),
440440
&format!("dep-node label `{}` not recognized", label));
441441
}
442442
}
@@ -576,13 +576,13 @@ 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()
583583
};
584584

585-
tcx.sess.span_fatal(item.span, &msg);
585+
tcx.sess.span_fatal(item.span(), &msg);
586586
}
587587
}
588588

0 commit comments

Comments
 (0)