Skip to content

Commit f923942

Browse files
committed
resolve: Divide macro path resolution into speculative and error reporting parts
Also move macro stability checking closer to other checks performed on obtained resolutions. Tighten the stability spans as well, it is an error to *refer* to and unstable entity in any way, not only "call" it.
1 parent 8bc187d commit f923942

17 files changed

+77
-82
lines changed

src/librustc_resolve/build_reduced_graph.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -755,11 +755,7 @@ impl<'a> Resolver<'a> {
755755
}
756756
}
757757

758-
pub fn get_macro(&mut self, res: Res) -> Lrc<SyntaxExtension> {
759-
self.opt_get_macro(res).expect("expected `DefKind::Macro` or `Res::NonMacroAttr`")
760-
}
761-
762-
crate fn opt_get_macro(&mut self, res: Res) -> Option<Lrc<SyntaxExtension>> {
758+
pub fn get_macro(&mut self, res: Res) -> Option<Lrc<SyntaxExtension>> {
763759
let def_id = match res {
764760
Res::Def(DefKind::Macro(..), def_id) => def_id,
765761
Res::NonMacroAttr(attr_kind) =>

src/librustc_resolve/macros.rs

Lines changed: 50 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -229,13 +229,10 @@ impl<'a> base::Resolver for Resolver<'a> {
229229
};
230230

231231
let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope);
232-
let (res, ext) = self.resolve_macro_to_res(path, kind, &parent_scope, true, force)?;
232+
let (ext, res) = self.smart_resolve_macro_path(path, kind, &parent_scope, true, force)?;
233233

234234
let span = invoc.span();
235-
let descr = fast_print_path(path);
236-
invoc.expansion_data.mark.set_expn_info(ext.expn_info(span, descr));
237-
238-
self.check_stability_and_deprecation(&ext, descr, span);
235+
invoc.expansion_data.mark.set_expn_info(ext.expn_info(span, fast_print_path(path)));
239236

240237
if let Res::Def(_, def_id) = res {
241238
if after_derive {
@@ -275,47 +272,42 @@ impl<'a> Resolver<'a> {
275272
}
276273
}
277274

278-
fn resolve_macro_to_res(
275+
/// Resolve macro path with error reporting and recovery.
276+
fn smart_resolve_macro_path(
279277
&mut self,
280278
path: &ast::Path,
281279
kind: MacroKind,
282280
parent_scope: &ParentScope<'a>,
283281
trace: bool,
284282
force: bool,
285-
) -> Result<(Res, Lrc<SyntaxExtension>), Indeterminate> {
286-
let res = self.resolve_macro_to_res_inner(path, kind, parent_scope, trace, force);
283+
) -> Result<(Lrc<SyntaxExtension>, Res), Indeterminate> {
284+
let (ext, res) = match self.resolve_macro_path(path, kind, parent_scope, trace, force) {
285+
Ok((Some(ext), res)) => (ext, res),
286+
// Use dummy syntax extensions for unresolved macros for better recovery.
287+
Ok((None, res)) => (self.dummy_ext(kind), res),
288+
Err(Determinacy::Determined) => (self.dummy_ext(kind), Res::Err),
289+
Err(Determinacy::Undetermined) => return Err(Indeterminate),
290+
};
287291

288292
// Report errors and enforce feature gates for the resolved macro.
289293
let features = self.session.features_untracked();
290-
if res != Err(Determinacy::Undetermined) {
291-
// Do not report duplicated errors on every undetermined resolution.
292-
for segment in &path.segments {
293-
if let Some(args) = &segment.args {
294-
self.session.span_err(args.span(), "generic arguments in macro path");
295-
}
296-
if kind == MacroKind::Attr && !features.rustc_attrs &&
297-
segment.ident.as_str().starts_with("rustc") {
298-
let msg = "attributes starting with `rustc` are \
299-
reserved for use by the `rustc` compiler";
300-
emit_feature_err(
301-
&self.session.parse_sess,
302-
sym::rustc_attrs,
303-
segment.ident.span,
304-
GateIssue::Language,
305-
msg,
306-
);
307-
}
294+
for segment in &path.segments {
295+
if let Some(args) = &segment.args {
296+
self.session.span_err(args.span(), "generic arguments in macro path");
308297
}
309-
}
310-
311-
let res = match res {
312-
Err(Determinacy::Undetermined) => return Err(Indeterminate),
313-
Ok(Res::Err) | Err(Determinacy::Determined) => {
314-
// Return dummy syntax extensions for unresolved macros for better recovery.
315-
return Ok((Res::Err, self.dummy_ext(kind)));
298+
if kind == MacroKind::Attr && !features.rustc_attrs &&
299+
segment.ident.as_str().starts_with("rustc") {
300+
let msg =
301+
"attributes starting with `rustc` are reserved for use by the `rustc` compiler";
302+
emit_feature_err(
303+
&self.session.parse_sess,
304+
sym::rustc_attrs,
305+
segment.ident.span,
306+
GateIssue::Language,
307+
msg,
308+
);
316309
}
317-
Ok(res) => res,
318-
};
310+
}
319311

320312
match res {
321313
Res::Def(DefKind::Macro(_), def_id) => {
@@ -345,20 +337,22 @@ impl<'a> Resolver<'a> {
345337
}
346338
}
347339
}
340+
Res::Err => {}
348341
_ => panic!("expected `DefKind::Macro` or `Res::NonMacroAttr`"),
349342
};
350343

351-
let ext = self.get_macro(res);
344+
self.check_stability_and_deprecation(&ext, path);
345+
352346
Ok(if ext.macro_kind() != kind {
353347
let expected = if kind == MacroKind::Attr { "attribute" } else { kind.descr() };
354348
let msg = format!("expected {}, found {} `{}`", expected, res.descr(), path);
355349
self.session.struct_span_err(path.span, &msg)
356350
.span_label(path.span, format!("not {} {}", kind.article(), expected))
357351
.emit();
358-
// Return dummy syntax extensions for unexpected macro kinds for better recovery.
359-
(Res::Err, self.dummy_ext(kind))
352+
// Use dummy syntax extensions for unexpected macro kinds for better recovery.
353+
(self.dummy_ext(kind), Res::Err)
360354
} else {
361-
(res, ext)
355+
(ext, res)
362356
})
363357
}
364358

@@ -416,14 +410,14 @@ impl<'a> Resolver<'a> {
416410
err.emit();
417411
}
418412

419-
pub fn resolve_macro_to_res_inner(
413+
pub fn resolve_macro_path(
420414
&mut self,
421415
path: &ast::Path,
422416
kind: MacroKind,
423417
parent_scope: &ParentScope<'a>,
424418
trace: bool,
425419
force: bool,
426-
) -> Result<Res, Determinacy> {
420+
) -> Result<(Option<Lrc<SyntaxExtension>>, Res), Determinacy> {
427421
let path_span = path.span;
428422
let mut path = Segment::from_path(path);
429423

@@ -435,7 +429,7 @@ impl<'a> Resolver<'a> {
435429
path.insert(0, Segment::from_ident(root));
436430
}
437431

438-
if path.len() > 1 {
432+
let res = if path.len() > 1 {
439433
let res = match self.resolve_path(&path, Some(MacroNS), parent_scope,
440434
false, path_span, CrateLint::No) {
441435
PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => {
@@ -471,7 +465,9 @@ impl<'a> Resolver<'a> {
471465
let res = binding.map(|binding| binding.res());
472466
self.prohibit_imported_non_macro_attrs(binding.ok(), res.ok(), path_span);
473467
res
474-
}
468+
};
469+
470+
res.map(|res| (self.get_macro(res), res))
475471
}
476472

477473
// Resolve an identifier in lexical scope.
@@ -600,16 +596,18 @@ impl<'a> Resolver<'a> {
600596
let mut result = Err(Determinacy::Determined);
601597
for derive in &parent_scope.derives {
602598
let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope };
603-
match self.resolve_macro_to_res(derive, MacroKind::Derive,
604-
&parent_scope, true, force) {
605-
Ok((_, ext)) => if ext.helper_attrs.contains(&ident.name) {
599+
match self.resolve_macro_path(derive, MacroKind::Derive,
600+
&parent_scope, true, force) {
601+
Ok((Some(ext), _)) => if ext.helper_attrs.contains(&ident.name) {
606602
let binding = (Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
607603
ty::Visibility::Public, derive.span, Mark::root())
608604
.to_name_binding(self.arenas);
609605
result = Ok((binding, Flags::empty()));
610606
break;
611607
}
612-
Err(Indeterminate) => result = Err(Determinacy::Undetermined),
608+
Ok(_) | Err(Determinacy::Determined) => {}
609+
Err(Determinacy::Undetermined) =>
610+
result = Err(Determinacy::Undetermined),
613611
}
614612
}
615613
result
@@ -1004,7 +1002,8 @@ impl<'a> Resolver<'a> {
10041002
}
10051003
}
10061004

1007-
fn check_stability_and_deprecation(&self, ext: &SyntaxExtension, descr: Symbol, span: Span) {
1005+
fn check_stability_and_deprecation(&self, ext: &SyntaxExtension, path: &ast::Path) {
1006+
let span = path.span;
10081007
if let Some(stability) = &ext.stability {
10091008
if let StabilityLevel::Unstable { reason, issue } = stability.level {
10101009
let feature = stability.feature;
@@ -1013,14 +1012,14 @@ impl<'a> Resolver<'a> {
10131012
}
10141013
}
10151014
if let Some(depr) = &stability.rustc_depr {
1016-
let (message, lint) = stability::rustc_deprecation_message(depr, &descr.as_str());
1015+
let (message, lint) = stability::rustc_deprecation_message(depr, &path.to_string());
10171016
stability::early_report_deprecation(
10181017
self.session, &message, depr.suggestion, lint, span
10191018
);
10201019
}
10211020
}
10221021
if let Some(depr) = &ext.deprecation {
1023-
let (message, lint) = stability::deprecation_message(depr, &descr.as_str());
1022+
let (message, lint) = stability::deprecation_message(depr, &path.to_string());
10241023
stability::early_report_deprecation(self.session, &message, None, lint, span);
10251024
}
10261025
}
@@ -1101,7 +1100,7 @@ impl<'a> Resolver<'a> {
11011100
// Reserve some names that are not quite covered by the general check
11021101
// performed on `Resolver::builtin_attrs`.
11031102
if ident.name == sym::cfg || ident.name == sym::cfg_attr || ident.name == sym::derive {
1104-
let macro_kind = self.opt_get_macro(res).map(|ext| ext.macro_kind());
1103+
let macro_kind = self.get_macro(res).map(|ext| ext.macro_kind());
11051104
if macro_kind.is_some() && sub_namespace_match(macro_kind, Some(MacroKind::Attr)) {
11061105
self.session.span_err(
11071106
ident.span, &format!("name `{}` is reserved in attribute namespace", ident)

src/librustdoc/passes/collect_intra_doc_links.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -429,10 +429,10 @@ fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option<Res> {
429429
let segment = ast::PathSegment::from_ident(Ident::from_str(path_str));
430430
let path = ast::Path { segments: vec![segment], span: DUMMY_SP };
431431
cx.enter_resolver(|resolver| {
432-
if let Ok(res @ Res::Def(DefKind::Macro(_), _)) = resolver.resolve_macro_to_res_inner(
432+
if let Ok((Some(ext), res)) = resolver.resolve_macro_path(
433433
&path, MacroKind::Bang, &resolver.dummy_parent_scope(), false, false
434434
) {
435-
if let SyntaxExtensionKind::LegacyBang { .. } = resolver.get_macro(res).kind {
435+
if let SyntaxExtensionKind::LegacyBang { .. } = ext.kind {
436436
return Some(res.map_id(|_| panic!("unexpected id")));
437437
}
438438
}

src/test/ui/feature-gates/feature-gate-asm.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'asm': inline assembly is not stab
22
--> $DIR/feature-gate-asm.rs:3:9
33
|
44
LL | asm!("");
5-
| ^^^^^^^^^
5+
| ^^^
66
|
77
= note: for more information, see https://github.com/rust-lang/rust/issues/29722
88
= help: add `#![feature(asm)]` to the crate attributes to enable

src/test/ui/feature-gates/feature-gate-asm2.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'asm': inline assembly is not stab
22
--> $DIR/feature-gate-asm2.rs:5:26
33
|
44
LL | println!("{:?}", asm!(""));
5-
| ^^^^^^^^
5+
| ^^^
66
|
77
= note: for more information, see https://github.com/rust-lang/rust/issues/29722
88
= help: add `#![feature(asm)]` to the crate attributes to enable

src/test/ui/feature-gates/feature-gate-concat_idents.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` i
22
--> $DIR/feature-gate-concat_idents.rs:5:13
33
|
44
LL | let a = concat_idents!(X, Y_1);
5-
| ^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^
66
|
77
= note: for more information, see https://github.com/rust-lang/rust/issues/29599
88
= help: add `#![feature(concat_idents)]` to the crate attributes to enable
@@ -11,7 +11,7 @@ error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` i
1111
--> $DIR/feature-gate-concat_idents.rs:6:13
1212
|
1313
LL | let b = concat_idents!(X, Y_2);
14-
| ^^^^^^^^^^^^^^^^^^^^^^
14+
| ^^^^^^^^^^^^^
1515
|
1616
= note: for more information, see https://github.com/rust-lang/rust/issues/29599
1717
= help: add `#![feature(concat_idents)]` to the crate attributes to enable

src/test/ui/feature-gates/feature-gate-concat_idents2.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` i
22
--> $DIR/feature-gate-concat_idents2.rs:4:5
33
|
44
LL | concat_idents!(a, b);
5-
| ^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^
66
|
77
= note: for more information, see https://github.com/rust-lang/rust/issues/29599
88
= help: add `#![feature(concat_idents)]` to the crate attributes to enable

src/test/ui/feature-gates/feature-gate-concat_idents3.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` i
22
--> $DIR/feature-gate-concat_idents3.rs:7:20
33
|
44
LL | assert_eq!(10, concat_idents!(X, Y_1));
5-
| ^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^
66
|
77
= note: for more information, see https://github.com/rust-lang/rust/issues/29599
88
= help: add `#![feature(concat_idents)]` to the crate attributes to enable
@@ -11,7 +11,7 @@ error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` i
1111
--> $DIR/feature-gate-concat_idents3.rs:8:20
1212
|
1313
LL | assert_eq!(20, concat_idents!(X, Y_2));
14-
| ^^^^^^^^^^^^^^^^^^^^^^
14+
| ^^^^^^^^^^^^^
1515
|
1616
= note: for more information, see https://github.com/rust-lang/rust/issues/29599
1717
= help: add `#![feature(concat_idents)]` to the crate attributes to enable

src/test/ui/feature-gates/feature-gate-format_args_nl.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'format_args_nl': `format_args_nl`
22
--> $DIR/feature-gate-format_args_nl.rs:2:5
33
|
44
LL | format_args_nl!("");
5-
| ^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^
66
|
77
= help: add `#![feature(format_args_nl)]` to the crate attributes to enable
88

src/test/ui/feature-gates/feature-gate-global_asm.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'global_asm': `global_asm!` is not
22
--> $DIR/feature-gate-global_asm.rs:1:1
33
|
44
LL | global_asm!("");
5-
| ^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^
66
|
77
= note: for more information, see https://github.com/rust-lang/rust/issues/35119
88
= help: add `#![feature(global_asm)]` to the crate attributes to enable

src/test/ui/feature-gates/feature-gate-log_syntax.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'log_syntax': `log_syntax!` is not
22
--> $DIR/feature-gate-log_syntax.rs:2:5
33
|
44
LL | log_syntax!()
5-
| ^^^^^^^^^^^^^
5+
| ^^^^^^^^^^
66
|
77
= note: for more information, see https://github.com/rust-lang/rust/issues/29598
88
= help: add `#![feature(log_syntax)]` to the crate attributes to enable

src/test/ui/feature-gates/feature-gate-log_syntax2.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'log_syntax': `log_syntax!` is not
22
--> $DIR/feature-gate-log_syntax2.rs:4:22
33
|
44
LL | println!("{:?}", log_syntax!());
5-
| ^^^^^^^^^^^^^
5+
| ^^^^^^^^^^
66
|
77
= note: for more information, see https://github.com/rust-lang/rust/issues/29598
88
= help: add `#![feature(log_syntax)]` to the crate attributes to enable

src/test/ui/feature-gates/feature-gate-trace_macros.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is
22
--> $DIR/feature-gate-trace_macros.rs:2:5
33
|
44
LL | trace_macros!(true);
5-
| ^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^
66
|
77
= note: for more information, see https://github.com/rust-lang/rust/issues/29598
88
= help: add `#![feature(trace_macros)]` to the crate attributes to enable

src/test/ui/macros/macro-deprecation.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ warning: use of deprecated item 'local_deprecated': local deprecation note
22
--> $DIR/macro-deprecation.rs:11:5
33
|
44
LL | local_deprecated!();
5-
| ^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^^^
66
|
77
= note: #[warn(deprecated)] on by default
88

99
warning: use of deprecated item 'deprecated_macro': deprecation note
1010
--> $DIR/macro-deprecation.rs:12:5
1111
|
1212
LL | deprecated_macro!();
13-
| ^^^^^^^^^^^^^^^^^^^^
13+
| ^^^^^^^^^^^^^^^^
1414

0 commit comments

Comments
 (0)