Skip to content

Commit fc51170

Browse files
authored
Rollup merge of rust-lang#69057 - Centril:clean-expand, r=petrochenkov
expand: misc cleanups and simplifications Some work I did while trying to understand expand for the purposes of rust-lang#64197. r? @petrochenkov
2 parents 998daf3 + ec43450 commit fc51170

File tree

2 files changed

+94
-114
lines changed

2 files changed

+94
-114
lines changed

src/librustc_expand/expand.rs

+60-59
Original file line numberDiff line numberDiff line change
@@ -451,28 +451,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
451451
_ => unreachable!(),
452452
};
453453
if !item.derive_allowed() {
454-
let attr = attr::find_by_name(item.attrs(), sym::derive)
455-
.expect("`derive` attribute should exist");
456-
let span = attr.span;
457-
let mut err = self.cx.struct_span_err(
458-
span,
459-
"`derive` may only be applied to structs, enums and unions",
460-
);
461-
if let ast::AttrStyle::Inner = attr.style {
462-
let trait_list = derives
463-
.iter()
464-
.map(|t| pprust::path_to_string(t))
465-
.collect::<Vec<_>>();
466-
let suggestion = format!("#[derive({})]", trait_list.join(", "));
467-
err.span_suggestion(
468-
span,
469-
"try an outer attribute",
470-
suggestion,
471-
// We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT
472-
Applicability::MaybeIncorrect,
473-
);
474-
}
475-
err.emit();
454+
self.error_derive_forbidden_on_non_adt(&derives, &item);
476455
}
477456

478457
let mut item = self.fully_configure(item);
@@ -521,6 +500,27 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
521500
fragment_with_placeholders
522501
}
523502

503+
fn error_derive_forbidden_on_non_adt(&self, derives: &[Path], item: &Annotatable) {
504+
let attr =
505+
attr::find_by_name(item.attrs(), sym::derive).expect("`derive` attribute should exist");
506+
let span = attr.span;
507+
let mut err = self
508+
.cx
509+
.struct_span_err(span, "`derive` may only be applied to structs, enums and unions");
510+
if let ast::AttrStyle::Inner = attr.style {
511+
let trait_list = derives.iter().map(|t| pprust::path_to_string(t)).collect::<Vec<_>>();
512+
let suggestion = format!("#[derive({})]", trait_list.join(", "));
513+
err.span_suggestion(
514+
span,
515+
"try an outer attribute",
516+
suggestion,
517+
// We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT
518+
Applicability::MaybeIncorrect,
519+
);
520+
}
521+
err.emit();
522+
}
523+
524524
fn resolve_imports(&mut self) {
525525
if self.monotonic {
526526
self.cx.resolver.resolve_imports();
@@ -606,21 +606,38 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
606606
}
607607
}
608608

609-
fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstFragment {
610-
if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit {
611-
let expn_data = self.cx.current_expansion.id.expn_data();
612-
let suggested_limit = self.cx.ecfg.recursion_limit * 2;
613-
let mut err = self.cx.struct_span_err(
609+
fn error_recursion_limit_reached(&mut self) {
610+
let expn_data = self.cx.current_expansion.id.expn_data();
611+
let suggested_limit = self.cx.ecfg.recursion_limit * 2;
612+
self.cx
613+
.struct_span_err(
614614
expn_data.call_site,
615615
&format!("recursion limit reached while expanding `{}`", expn_data.kind.descr()),
616-
);
617-
err.help(&format!(
616+
)
617+
.help(&format!(
618618
"consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
619619
suggested_limit, self.cx.ecfg.crate_name,
620-
));
621-
err.emit();
622-
self.cx.trace_macros_diag();
623-
FatalError.raise();
620+
))
621+
.emit();
622+
self.cx.trace_macros_diag();
623+
FatalError.raise();
624+
}
625+
626+
/// A macro's expansion does not fit in this fragment kind.
627+
/// For example, a non-type macro in a type position.
628+
fn error_wrong_fragment_kind(&mut self, kind: AstFragmentKind, mac: &ast::Mac, span: Span) {
629+
let msg = format!(
630+
"non-{kind} macro in {kind} position: {path}",
631+
kind = kind.name(),
632+
path = pprust::path_to_string(&mac.path),
633+
);
634+
self.cx.span_err(span, &msg);
635+
self.cx.trace_macros_diag();
636+
}
637+
638+
fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstFragment {
639+
if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit {
640+
self.error_recursion_limit_reached();
624641
}
625642

626643
let (fragment_kind, span) = (invoc.fragment_kind, invoc.span());
@@ -638,13 +655,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
638655
let result = if let Some(result) = fragment_kind.make_from(tok_result) {
639656
result
640657
} else {
641-
let msg = format!(
642-
"non-{kind} macro in {kind} position: {path}",
643-
kind = fragment_kind.name(),
644-
path = pprust::path_to_string(&mac.path),
645-
);
646-
self.cx.span_err(span, &msg);
647-
self.cx.trace_macros_diag();
658+
self.error_wrong_fragment_kind(fragment_kind, &mac, span);
648659
fragment_kind.dummy(span)
649660
};
650661
self.cx.current_expansion.prior_type_ascription = prev;
@@ -1030,13 +1041,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
10301041
}
10311042

10321043
/// If `item` is an attr invocation, remove and return the macro attribute and derive traits.
1033-
fn classify_item<T>(
1044+
fn classify_item(
10341045
&mut self,
1035-
item: &mut T,
1036-
) -> (Option<ast::Attribute>, Vec<Path>, /* after_derive */ bool)
1037-
where
1038-
T: HasAttrs,
1039-
{
1046+
item: &mut impl HasAttrs,
1047+
) -> (Option<ast::Attribute>, Vec<Path>, /* after_derive */ bool) {
10401048
let (mut attr, mut traits, mut after_derive) = (None, Vec::new(), false);
10411049

10421050
item.visit_attrs(|mut attrs| {
@@ -1050,9 +1058,9 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
10501058
/// Alternative to `classify_item()` that ignores `#[derive]` so invocations fallthrough
10511059
/// to the unused-attributes lint (making it an error on statements and expressions
10521060
/// is a breaking change)
1053-
fn classify_nonitem<T: HasAttrs>(
1061+
fn classify_nonitem(
10541062
&mut self,
1055-
nonitem: &mut T,
1063+
nonitem: &mut impl HasAttrs,
10561064
) -> (Option<ast::Attribute>, /* after_derive */ bool) {
10571065
let (mut attr, mut after_derive) = (None, false);
10581066

@@ -1375,21 +1383,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
13751383
_ => unreachable!(),
13761384
})
13771385
}
1378-
ast::ItemKind::Mod(ast::Mod { inner, .. }) => {
1379-
if item.ident == Ident::invalid() {
1380-
return noop_flat_map_item(item, self);
1381-
}
1382-
1386+
ast::ItemKind::Mod(ast::Mod { inner, inline, .. })
1387+
if item.ident != Ident::invalid() =>
1388+
{
13831389
let orig_directory_ownership = self.cx.current_expansion.directory_ownership;
13841390
let mut module = (*self.cx.current_expansion.module).clone();
13851391
module.mod_path.push(item.ident);
13861392

1387-
// Detect if this is an inline module (`mod m { ... }` as opposed to `mod m;`).
1388-
// In the non-inline case, `inner` is never the dummy span (cf. `parse_item_mod`).
1389-
// Thus, if `inner` is the dummy span, we know the module is inline.
1390-
let inline_module = item.span.contains(inner) || inner.is_dummy();
1391-
1392-
if inline_module {
1393+
if inline {
13931394
if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, sym::path) {
13941395
self.cx.current_expansion.directory_ownership =
13951396
DirectoryOwnership::Owned { relative: None };

src/librustc_parse/config.rs

+34-55
Original file line numberDiff line numberDiff line change
@@ -207,30 +207,29 @@ pub fn features(
207207
edition: Edition,
208208
allow_features: &Option<Vec<String>>,
209209
) -> (ast::Crate, Features) {
210-
let features;
211-
{
212-
let mut strip_unconfigured = StripUnconfigured { sess, features: None };
210+
let mut strip_unconfigured = StripUnconfigured { sess, features: None };
213211

214-
let unconfigured_attrs = krate.attrs.clone();
215-
let err_count = sess.span_diagnostic.err_count();
216-
if let Some(attrs) = strip_unconfigured.configure(krate.attrs) {
217-
krate.attrs = attrs;
218-
} else {
219-
// the entire crate is unconfigured
212+
let unconfigured_attrs = krate.attrs.clone();
213+
let diag = &sess.span_diagnostic;
214+
let err_count = diag.err_count();
215+
let features = match strip_unconfigured.configure(krate.attrs) {
216+
None => {
217+
// The entire crate is unconfigured.
220218
krate.attrs = Vec::new();
221219
krate.module.items = Vec::new();
222-
return (krate, Features::default());
220+
Features::default()
223221
}
224-
225-
features = get_features(&sess.span_diagnostic, &krate.attrs, edition, allow_features);
226-
227-
// Avoid reconfiguring malformed `cfg_attr`s
228-
if err_count == sess.span_diagnostic.err_count() {
229-
strip_unconfigured.features = Some(&features);
230-
strip_unconfigured.configure(unconfigured_attrs);
222+
Some(attrs) => {
223+
krate.attrs = attrs;
224+
let features = get_features(diag, &krate.attrs, edition, allow_features);
225+
if err_count == diag.err_count() {
226+
// Avoid reconfiguring malformed `cfg_attr`s.
227+
strip_unconfigured.features = Some(&features);
228+
strip_unconfigured.configure(unconfigured_attrs);
229+
}
230+
features
231231
}
232-
}
233-
232+
};
234233
(krate, features)
235234
}
236235

@@ -347,7 +346,13 @@ impl<'a> StripUnconfigured<'a> {
347346
if !is_cfg(attr) {
348347
return true;
349348
}
350-
349+
let meta_item = match validate_attr::parse_meta(self.sess, attr) {
350+
Ok(meta_item) => meta_item,
351+
Err(mut err) => {
352+
err.emit();
353+
return true;
354+
}
355+
};
351356
let error = |span, msg, suggestion: &str| {
352357
let mut err = self.sess.span_diagnostic.struct_span_err(span, msg);
353358
if !suggestion.is_empty() {
@@ -361,41 +366,15 @@ impl<'a> StripUnconfigured<'a> {
361366
err.emit();
362367
true
363368
};
364-
365-
let meta_item = match validate_attr::parse_meta(self.sess, attr) {
366-
Ok(meta_item) => meta_item,
367-
Err(mut err) => {
368-
err.emit();
369-
return true;
370-
}
371-
};
372-
let nested_meta_items = if let Some(nested_meta_items) = meta_item.meta_item_list() {
373-
nested_meta_items
374-
} else {
375-
return error(
376-
meta_item.span,
377-
"`cfg` is not followed by parentheses",
378-
"cfg(/* predicate */)",
379-
);
380-
};
381-
382-
if nested_meta_items.is_empty() {
383-
return error(meta_item.span, "`cfg` predicate is not specified", "");
384-
} else if nested_meta_items.len() > 1 {
385-
return error(
386-
nested_meta_items.last().unwrap().span(),
387-
"multiple `cfg` predicates are specified",
388-
"",
389-
);
390-
}
391-
392-
match nested_meta_items[0].meta_item() {
393-
Some(meta_item) => attr::cfg_matches(meta_item, self.sess, self.features),
394-
None => error(
395-
nested_meta_items[0].span(),
396-
"`cfg` predicate key cannot be a literal",
397-
"",
398-
),
369+
let span = meta_item.span;
370+
match meta_item.meta_item_list() {
371+
None => error(span, "`cfg` is not followed by parentheses", "cfg(/* predicate */)"),
372+
Some([]) => error(span, "`cfg` predicate is not specified", ""),
373+
Some([_, .., l]) => error(l.span(), "multiple `cfg` predicates are specified", ""),
374+
Some([single]) => match single.meta_item() {
375+
Some(meta_item) => attr::cfg_matches(meta_item, self.sess, self.features),
376+
None => error(single.span(), "`cfg` predicate key cannot be a literal", ""),
377+
},
399378
}
400379
})
401380
}

0 commit comments

Comments
 (0)