Skip to content

Commit 68f94e9

Browse files
committed
resolve: Centralize some error reporting for unexpected macro resolutions
1 parent 69894ce commit 68f94e9

14 files changed

+278
-253
lines changed

compiler/rustc_expand/src/expand.rs

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,28 @@ impl AstFragmentKind {
209209
self.make_from(DummyResult::any(span)).expect("couldn't create a dummy AST fragment")
210210
}
211211

212+
/// Fragment supports macro expansion and not just inert attributes, `cfg` and `cfg_attr`.
213+
pub fn supports_macro_expansion(self) -> bool {
214+
match self {
215+
AstFragmentKind::OptExpr
216+
| AstFragmentKind::Expr
217+
| AstFragmentKind::Pat
218+
| AstFragmentKind::Ty
219+
| AstFragmentKind::Stmts
220+
| AstFragmentKind::Items
221+
| AstFragmentKind::TraitItems
222+
| AstFragmentKind::ImplItems
223+
| AstFragmentKind::ForeignItems => true,
224+
AstFragmentKind::Arms
225+
| AstFragmentKind::Fields
226+
| AstFragmentKind::FieldPats
227+
| AstFragmentKind::GenericParams
228+
| AstFragmentKind::Params
229+
| AstFragmentKind::StructFields
230+
| AstFragmentKind::Variants => false,
231+
}
232+
}
233+
212234
fn expect_from_annotatables<I: IntoIterator<Item = Annotatable>>(
213235
self,
214236
items: I,
@@ -1014,30 +1036,15 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
10141036
attrs: &mut Vec<ast::Attribute>,
10151037
after_derive: &mut bool,
10161038
) -> Option<ast::Attribute> {
1017-
let attr = attrs
1039+
attrs
10181040
.iter()
10191041
.position(|a| {
10201042
if a.has_name(sym::derive) {
10211043
*after_derive = true;
10221044
}
10231045
!self.cx.sess.is_attr_known(a) && !is_builtin_attr(a)
10241046
})
1025-
.map(|i| attrs.remove(i));
1026-
if let Some(attr) = &attr {
1027-
if !self.cx.ecfg.custom_inner_attributes()
1028-
&& attr.style == ast::AttrStyle::Inner
1029-
&& !attr.has_name(sym::test)
1030-
{
1031-
feature_err(
1032-
&self.cx.sess.parse_sess,
1033-
sym::custom_inner_attributes,
1034-
attr.span,
1035-
"non-builtin inner attributes are unstable",
1036-
)
1037-
.emit();
1038-
}
1039-
}
1040-
attr
1047+
.map(|i| attrs.remove(i))
10411048
}
10421049

10431050
/// If `item` is an attr invocation, remove and return the macro attribute and derive traits.

compiler/rustc_resolve/src/macros.rs

Lines changed: 58 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,24 @@ use rustc_ast_pretty::pprust;
1212
use rustc_attr::StabilityLevel;
1313
use rustc_data_structures::fx::FxHashSet;
1414
use rustc_data_structures::ptr_key::PtrKey;
15+
use rustc_data_structures::sync::Lrc;
1516
use rustc_errors::struct_span_err;
1617
use rustc_expand::base::{Indeterminate, InvocationRes, ResolverExpand, SyntaxExtension};
1718
use rustc_expand::compile_declarative_macro;
18-
use rustc_expand::expand::{AstFragment, AstFragmentKind, Invocation, InvocationKind};
19+
use rustc_expand::expand::{AstFragment, Invocation, InvocationKind};
1920
use rustc_feature::is_builtin_attr_name;
2021
use rustc_hir::def::{self, DefKind, NonMacroAttrKind};
2122
use rustc_hir::def_id;
2223
use rustc_middle::middle::stability;
2324
use rustc_middle::ty;
2425
use rustc_session::lint::builtin::UNUSED_MACROS;
26+
use rustc_session::parse::feature_err;
2527
use rustc_session::Session;
2628
use rustc_span::edition::Edition;
2729
use rustc_span::hygiene::{self, ExpnData, ExpnId, ExpnKind};
30+
use rustc_span::hygiene::{AstPass, MacroKind};
2831
use rustc_span::symbol::{kw, sym, Ident, Symbol};
2932
use rustc_span::{Span, DUMMY_SP};
30-
31-
use rustc_data_structures::sync::Lrc;
32-
use rustc_span::hygiene::{AstPass, MacroKind};
3333
use std::cell::Cell;
3434
use std::{mem, ptr};
3535

@@ -241,15 +241,20 @@ impl<'a> ResolverExpand for Resolver<'a> {
241241
}
242242
};
243243

244-
let (path, kind, derives, after_derive) = match invoc.kind {
244+
let (path, kind, inner_attr, derives, after_derive) = match invoc.kind {
245245
InvocationKind::Attr { ref attr, ref derives, after_derive, .. } => (
246246
&attr.get_normal_item().path,
247247
MacroKind::Attr,
248+
attr.style == ast::AttrStyle::Inner,
248249
self.arenas.alloc_ast_paths(derives),
249250
after_derive,
250251
),
251-
InvocationKind::Bang { ref mac, .. } => (&mac.path, MacroKind::Bang, &[][..], false),
252-
InvocationKind::Derive { ref path, .. } => (path, MacroKind::Derive, &[][..], false),
252+
InvocationKind::Bang { ref mac, .. } => {
253+
(&mac.path, MacroKind::Bang, false, &[][..], false)
254+
}
255+
InvocationKind::Derive { ref path, .. } => {
256+
(path, MacroKind::Derive, false, &[][..], false)
257+
}
253258
InvocationKind::DeriveContainer { ref derives, .. } => {
254259
// Block expansion of the container until we resolve all derives in it.
255260
// This is required for two reasons:
@@ -299,8 +304,17 @@ impl<'a> ResolverExpand for Resolver<'a> {
299304

300305
// Derives are not included when `invocations` are collected, so we have to add them here.
301306
let parent_scope = &ParentScope { derives, ..parent_scope };
307+
let require_inert = !invoc.fragment_kind.supports_macro_expansion();
302308
let node_id = self.lint_node_id(eager_expansion_root);
303-
let (ext, res) = self.smart_resolve_macro_path(path, kind, parent_scope, node_id, force)?;
309+
let (ext, res) = self.smart_resolve_macro_path(
310+
path,
311+
kind,
312+
require_inert,
313+
inner_attr,
314+
parent_scope,
315+
node_id,
316+
force,
317+
)?;
304318

305319
let span = invoc.span();
306320
invoc_id.set_expn_data(ext.expn_data(
@@ -318,29 +332,6 @@ impl<'a> ResolverExpand for Resolver<'a> {
318332
self.definitions.add_parent_module_of_macro_def(invoc_id, normal_module_def_id);
319333
}
320334

321-
match invoc.fragment_kind {
322-
AstFragmentKind::Arms
323-
| AstFragmentKind::Fields
324-
| AstFragmentKind::FieldPats
325-
| AstFragmentKind::GenericParams
326-
| AstFragmentKind::Params
327-
| AstFragmentKind::StructFields
328-
| AstFragmentKind::Variants => {
329-
if let Res::Def(..) = res {
330-
self.session.span_err(
331-
span,
332-
&format!(
333-
"expected an inert attribute, found {} {}",
334-
res.article(),
335-
res.descr()
336-
),
337-
);
338-
return Ok(InvocationRes::Single(self.dummy_ext(kind)));
339-
}
340-
}
341-
_ => {}
342-
}
343-
344335
Ok(InvocationRes::Single(ext))
345336
}
346337

@@ -403,18 +394,21 @@ impl<'a> ResolverExpand for Resolver<'a> {
403394

404395
impl<'a> Resolver<'a> {
405396
/// Resolve macro path with error reporting and recovery.
397+
/// Uses dummy syntax extensions for unresolved macros or macros with unexpected resolutions
398+
/// for better error recovery.
406399
fn smart_resolve_macro_path(
407400
&mut self,
408401
path: &ast::Path,
409402
kind: MacroKind,
403+
require_inert: bool,
404+
inner_attr: bool,
410405
parent_scope: &ParentScope<'a>,
411406
node_id: NodeId,
412407
force: bool,
413408
) -> Result<(Lrc<SyntaxExtension>, Res), Indeterminate> {
414409
let (ext, res) = match self.resolve_macro_path(path, Some(kind), parent_scope, true, force)
415410
{
416411
Ok((Some(ext), res)) => (ext, res),
417-
// Use dummy syntax extensions for unresolved macros for better recovery.
418412
Ok((None, res)) => (self.dummy_ext(kind), res),
419413
Err(Determinacy::Determined) => (self.dummy_ext(kind), Res::Err),
420414
Err(Determinacy::Undetermined) => return Err(Indeterminate),
@@ -451,19 +445,43 @@ impl<'a> Resolver<'a> {
451445

452446
self.check_stability_and_deprecation(&ext, path, node_id);
453447

454-
Ok(if ext.macro_kind() != kind {
455-
let expected = kind.descr_expected();
448+
let unexpected_res = if ext.macro_kind() != kind {
449+
Some((kind.article(), kind.descr_expected()))
450+
} else if require_inert && matches!(res, Res::Def(..)) {
451+
Some(("a", "non-macro attribute"))
452+
} else {
453+
None
454+
};
455+
if let Some((article, expected)) = unexpected_res {
456456
let path_str = pprust::path_to_string(path);
457457
let msg = format!("expected {}, found {} `{}`", expected, res.descr(), path_str);
458458
self.session
459459
.struct_span_err(path.span, &msg)
460-
.span_label(path.span, format!("not {} {}", kind.article(), expected))
460+
.span_label(path.span, format!("not {} {}", article, expected))
461461
.emit();
462-
// Use dummy syntax extensions for unexpected macro kinds for better recovery.
463-
(self.dummy_ext(kind), Res::Err)
464-
} else {
465-
(ext, res)
466-
})
462+
return Ok((self.dummy_ext(kind), Res::Err));
463+
}
464+
465+
// We are trying to avoid reporting this error if other related errors were reported.
466+
if inner_attr
467+
&& !self.session.features_untracked().custom_inner_attributes
468+
&& path != &sym::test
469+
&& res != Res::Err
470+
{
471+
feature_err(
472+
&self.session.parse_sess,
473+
sym::custom_inner_attributes,
474+
path.span,
475+
match res {
476+
Res::Def(..) => "inner macro attributes are unstable",
477+
Res::NonMacroAttr(..) => "custom inner attributes are unstable",
478+
_ => unreachable!(),
479+
},
480+
)
481+
.emit();
482+
}
483+
484+
Ok((ext, res))
467485
}
468486

469487
pub fn resolve_macro_path(

src/test/ui/attrs-resolution-errors.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
enum FooEnum {
22
#[test]
3-
//~^ ERROR expected an inert attribute, found an attribute macro
3+
//~^ ERROR expected non-macro attribute, found attribute macro
44
Bar(i32),
55
}
66

77
struct FooStruct {
88
#[test]
9-
//~^ ERROR expected an inert attribute, found an attribute macro
9+
//~^ ERROR expected non-macro attribute, found attribute macro
1010
bar: i32,
1111
}
1212

@@ -21,20 +21,20 @@ fn main() {
2121
match foo_struct {
2222
FooStruct {
2323
#[test] bar
24-
//~^ ERROR expected an inert attribute, found an attribute macro
24+
//~^ ERROR expected non-macro attribute, found attribute macro
2525
} => {}
2626
}
2727

2828
match 1 {
2929
0 => {}
3030
#[test]
31-
//~^ ERROR expected an inert attribute, found an attribute macro
31+
//~^ ERROR expected non-macro attribute, found attribute macro
3232
_ => {}
3333
}
3434

3535
let _another_foo_strunct = FooStruct {
3636
#[test]
37-
//~^ ERROR expected an inert attribute, found an attribute macro
37+
//~^ ERROR expected non-macro attribute, found attribute macro
3838
bar: 1,
3939
};
4040
}
Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,32 @@
1-
error: expected an inert attribute, found an attribute macro
2-
--> $DIR/attrs-resolution-errors.rs:2:5
1+
error: expected non-macro attribute, found attribute macro `test`
2+
--> $DIR/attrs-resolution-errors.rs:2:7
33
|
44
LL | #[test]
5-
| ^^^^^^^
5+
| ^^^^ not a non-macro attribute
66

7-
error: expected an inert attribute, found an attribute macro
8-
--> $DIR/attrs-resolution-errors.rs:8:5
7+
error: expected non-macro attribute, found attribute macro `test`
8+
--> $DIR/attrs-resolution-errors.rs:8:7
99
|
1010
LL | #[test]
11-
| ^^^^^^^
11+
| ^^^^ not a non-macro attribute
1212

13-
error: expected an inert attribute, found an attribute macro
14-
--> $DIR/attrs-resolution-errors.rs:23:13
13+
error: expected non-macro attribute, found attribute macro `test`
14+
--> $DIR/attrs-resolution-errors.rs:23:15
1515
|
1616
LL | #[test] bar
17-
| ^^^^^^^
17+
| ^^^^ not a non-macro attribute
1818

19-
error: expected an inert attribute, found an attribute macro
20-
--> $DIR/attrs-resolution-errors.rs:30:9
19+
error: expected non-macro attribute, found attribute macro `test`
20+
--> $DIR/attrs-resolution-errors.rs:30:11
2121
|
2222
LL | #[test]
23-
| ^^^^^^^
23+
| ^^^^ not a non-macro attribute
2424

25-
error: expected an inert attribute, found an attribute macro
26-
--> $DIR/attrs-resolution-errors.rs:36:9
25+
error: expected non-macro attribute, found attribute macro `test`
26+
--> $DIR/attrs-resolution-errors.rs:36:11
2727
|
2828
LL | #[test]
29-
| ^^^^^^^
29+
| ^^^^ not a non-macro attribute
3030

3131
error: aborting due to 5 previous errors
3232

src/test/ui/proc-macro/proc-macro-gates.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77
extern crate test_macros;
88

99
fn _test_inner() {
10-
#![empty_attr] //~ ERROR: non-builtin inner attributes are unstable
10+
#![empty_attr] //~ ERROR: inner macro attributes are unstable
1111
}
1212

1313
mod _test2_inner {
14-
#![empty_attr] //~ ERROR: non-builtin inner attributes are unstable
14+
#![empty_attr] //~ ERROR: inner macro attributes are unstable
1515
}
1616

1717
#[empty_attr = "y"] //~ ERROR: key-value macro attributes are not supported

src/test/ui/proc-macro/proc-macro-gates.stderr

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
error[E0658]: non-builtin inner attributes are unstable
2-
--> $DIR/proc-macro-gates.rs:10:5
1+
error[E0658]: inner macro attributes are unstable
2+
--> $DIR/proc-macro-gates.rs:10:8
33
|
44
LL | #![empty_attr]
5-
| ^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^
66
|
77
= note: see issue #54726 <https://github.com/rust-lang/rust/issues/54726> for more information
88
= help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable
99

10-
error[E0658]: non-builtin inner attributes are unstable
11-
--> $DIR/proc-macro-gates.rs:14:5
10+
error[E0658]: inner macro attributes are unstable
11+
--> $DIR/proc-macro-gates.rs:14:8
1212
|
1313
LL | #![empty_attr]
14-
| ^^^^^^^^^^^^^^
14+
| ^^^^^^^^^^
1515
|
1616
= note: see issue #54726 <https://github.com/rust-lang/rust/issues/54726> for more information
1717
= help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable

src/test/ui/proc-macro/proc-macro-gates2.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ extern crate test_macros;
1010
// should either require a feature gate or not be allowed on stable.
1111

1212
fn _test6<#[empty_attr] T>() {}
13-
//~^ ERROR: expected an inert attribute, found an attribute macro
13+
//~^ ERROR: expected non-macro attribute, found attribute macro
1414

1515
fn _test7() {
1616
match 1 {
17-
#[empty_attr] //~ ERROR: expected an inert attribute, found an attribute macro
17+
#[empty_attr] //~ ERROR: expected non-macro attribute, found attribute macro
1818
0 => {}
1919
_ => {}
2020
}
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
error: expected an inert attribute, found an attribute macro
2-
--> $DIR/proc-macro-gates2.rs:12:11
1+
error: expected non-macro attribute, found attribute macro `empty_attr`
2+
--> $DIR/proc-macro-gates2.rs:12:13
33
|
44
LL | fn _test6<#[empty_attr] T>() {}
5-
| ^^^^^^^^^^^^^
5+
| ^^^^^^^^^^ not a non-macro attribute
66

7-
error: expected an inert attribute, found an attribute macro
8-
--> $DIR/proc-macro-gates2.rs:17:9
7+
error: expected non-macro attribute, found attribute macro `empty_attr`
8+
--> $DIR/proc-macro-gates2.rs:17:11
99
|
1010
LL | #[empty_attr]
11-
| ^^^^^^^^^^^^^
11+
| ^^^^^^^^^^ not a non-macro attribute
1212

1313
error: aborting due to 2 previous errors
1414

0 commit comments

Comments
 (0)