Skip to content

Commit dd90874

Browse files
committed
fix: Error reporting for expand_legacy_bang (passes tests/ui)
1 parent fb9dd74 commit dd90874

File tree

9 files changed

+64
-62
lines changed

9 files changed

+64
-62
lines changed

compiler/rustc_expand/src/base.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc_data_structures::sync::{self, Lrc};
1515
use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, PResult};
1616
use rustc_feature::Features;
1717
use rustc_lint_defs::{BufferedEarlyLint, RegisteredTools};
18-
use rustc_middle::expand::{CanRetry, TcxMacroExpander};
18+
use rustc_middle::expand::TcxMacroExpander;
1919
use rustc_parse::parser::Parser;
2020
use rustc_parse::MACRO_ARGUMENTS;
2121
use rustc_session::config::CollapseMacroDebuginfo;
@@ -1084,7 +1084,7 @@ pub trait ResolverExpand {
10841084
&self,
10851085
invoc_id: LocalExpnId,
10861086
current_expansion: LocalExpnId,
1087-
) -> Result<(TokenStream, usize), CanRetry>;
1087+
) -> Result<(TokenStream, usize), (Span, ErrorGuaranteed)>;
10881088
}
10891089

10901090
pub trait LintStoreExpand {

compiler/rustc_expand/src/expand.rs

+3-9
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
1919
use rustc_data_structures::sync::Lrc;
2020
use rustc_errors::PResult;
2121
use rustc_feature::Features;
22-
use rustc_middle::expand::CanRetry;
2322
use rustc_middle::ty::TyCtxt;
2423
use rustc_parse::parser::{
2524
AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, RecoverColon, RecoverComma,
@@ -33,7 +32,6 @@ use rustc_span::hygiene::SyntaxContext;
3332
use rustc_span::symbol::{sym, Ident};
3433
use rustc_span::{ErrorGuaranteed, FileName, LocalExpnId, Span};
3534
use smallvec::SmallVec;
36-
use tracing::debug;
3735

3836
use crate::base::*;
3937
use crate::config::StripUnconfigured;
@@ -401,7 +399,7 @@ pub struct MacroExpander<'a, 'b> {
401399
pub fn expand_legacy_bang<'tcx>(
402400
tcx: TyCtxt<'tcx>,
403401
key: (LocalExpnId, LocalExpnId),
404-
) -> Result<(&'tcx TokenStream, usize), CanRetry> {
402+
) -> Result<(&'tcx TokenStream, usize), (Span, ErrorGuaranteed)> {
405403
let (invoc_id, current_expansion) = key;
406404
let map = tcx.macro_map.borrow();
407405
let (arg, span, expander) = map.get(&invoc_id).as_ref().unwrap();
@@ -739,14 +737,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
739737
is_local,
740738
))
741739
}
742-
Err(CanRetry::No(guar)) => {
743-
debug!("Will not retry matching as an error was emitted already");
740+
Err((span, guar)) => {
741+
self.cx.trace_macros_diag();
744742
DummyResult::any(span, guar)
745743
}
746-
Err(CanRetry::Yes) => {
747-
// Retry and emit a better error.
748-
DummyResult::any_valid(span)
749-
}
750744
};
751745
let result = if let Some(result) = fragment_kind.make_from(tok_result) {
752746
result

compiler/rustc_expand/src/mbe/diagnostics.rs

+24-27
Original file line numberDiff line numberDiff line change
@@ -3,42 +3,40 @@ use std::borrow::Cow;
33
use rustc_ast::token::{self, Token, TokenKind};
44
use rustc_ast::tokenstream::TokenStream;
55
use rustc_ast_pretty::pprust;
6-
use rustc_errors::{Applicability, Diag, DiagMessage};
6+
use rustc_errors::{Applicability, Diag, DiagCtxtHandle, DiagMessage};
77
use rustc_macros::Subdiagnostic;
88
use rustc_parse::parser::{Parser, Recovery};
9+
use rustc_session::parse::ParseSess;
910
use rustc_span::source_map::SourceMap;
1011
use rustc_span::symbol::Ident;
1112
use rustc_span::{ErrorGuaranteed, Span};
1213
use tracing::debug;
1314

1415
use super::macro_rules::{parser_from_cx, NoopTracker};
15-
use crate::base::{DummyResult, ExtCtxt, MacResult};
1616
use crate::expand::{parse_ast_fragment, AstFragmentKind};
1717
use crate::mbe::macro_parser::ParseResult::*;
1818
use crate::mbe::macro_parser::{MatcherLoc, NamedParseResult, TtParser};
1919
use crate::mbe::macro_rules::{try_match_macro, Tracker};
2020

21-
pub(crate) fn failed_to_match_macro<'cx>(
22-
cx: &'cx mut ExtCtxt<'_>,
21+
pub(crate) fn failed_to_match_macro(
22+
psess: &ParseSess,
2323
sp: Span,
2424
def_span: Span,
2525
name: Ident,
2626
arg: TokenStream,
2727
lhses: &[Vec<MatcherLoc>],
28-
) -> Box<dyn MacResult + 'cx> {
29-
let psess = &cx.sess.psess;
30-
28+
) -> (Span, ErrorGuaranteed) {
3129
// An error occurred, try the expansion again, tracking the expansion closely for better
3230
// diagnostics.
33-
let mut tracker = CollectTrackerAndEmitter::new(cx, sp);
31+
let mut tracker = CollectTrackerAndEmitter::new(psess.dcx(), sp);
3432

3533
let try_success_result = try_match_macro(psess, name, &arg, lhses, &mut tracker);
3634

3735
if try_success_result.is_ok() {
3836
// Nonterminal parser recovery might turn failed matches into successful ones,
3937
// but for that it must have emitted an error already
4038
assert!(
41-
tracker.cx.dcx().has_errors().is_some(),
39+
tracker.dcx.has_errors().is_some(),
4240
"Macro matching returned a success on the second try"
4341
);
4442
}
@@ -50,15 +48,15 @@ pub(crate) fn failed_to_match_macro<'cx>(
5048

5149
let Some(BestFailure { token, msg: label, remaining_matcher, .. }) = tracker.best_failure
5250
else {
53-
return DummyResult::any(sp, cx.dcx().span_delayed_bug(sp, "failed to match a macro"));
51+
return (sp, psess.dcx().span_delayed_bug(sp, "failed to match a macro"));
5452
};
5553

5654
let span = token.span.substitute_dummy(sp);
5755

58-
let mut err = cx.dcx().struct_span_err(span, parse_failure_msg(&token, None));
56+
let mut err = psess.dcx().struct_span_err(span, parse_failure_msg(&token, None));
5957
err.span_label(span, label);
60-
if !def_span.is_dummy() && !cx.source_map().is_imported(def_span) {
61-
err.span_label(cx.source_map().guess_head_span(def_span), "when calling this macro");
58+
if !def_span.is_dummy() && !psess.source_map().is_imported(def_span) {
59+
err.span_label(psess.source_map().guess_head_span(def_span), "when calling this macro");
6260
}
6361

6462
annotate_doc_comment(&mut err, psess.source_map(), span);
@@ -76,7 +74,7 @@ pub(crate) fn failed_to_match_macro<'cx>(
7674
err.note("captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens");
7775
err.note("see <https://doc.rust-lang.org/nightly/reference/macros-by-example.html#forwarding-a-matched-fragment> for more information");
7876

79-
if !def_span.is_dummy() && !cx.source_map().is_imported(def_span) {
77+
if !def_span.is_dummy() && !psess.source_map().is_imported(def_span) {
8078
err.help("try using `:tt` instead in the macro definition");
8179
}
8280
}
@@ -104,18 +102,17 @@ pub(crate) fn failed_to_match_macro<'cx>(
104102
}
105103
}
106104
let guar = err.emit();
107-
cx.trace_macros_diag();
108-
DummyResult::any(sp, guar)
105+
(sp, guar)
109106
}
110107

111108
/// The tracker used for the slow error path that collects useful info for diagnostics.
112-
struct CollectTrackerAndEmitter<'a, 'cx, 'matcher> {
113-
cx: &'a mut ExtCtxt<'cx>,
109+
struct CollectTrackerAndEmitter<'dcx, 'matcher> {
110+
dcx: DiagCtxtHandle<'dcx>,
114111
remaining_matcher: Option<&'matcher MatcherLoc>,
115112
/// Which arm's failure should we report? (the one furthest along)
116113
best_failure: Option<BestFailure>,
117114
root_span: Span,
118-
result: Option<Box<dyn MacResult + 'cx>>,
115+
result: Option<(Span, ErrorGuaranteed)>,
119116
}
120117

121118
struct BestFailure {
@@ -131,7 +128,7 @@ impl BestFailure {
131128
}
132129
}
133130

134-
impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, 'matcher> {
131+
impl<'dcx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'dcx, 'matcher> {
135132
type Failure = (Token, u32, &'static str);
136133

137134
fn build_failure(tok: Token, position: u32, msg: &'static str) -> Self::Failure {
@@ -151,7 +148,7 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx,
151148
Success(_) => {
152149
// Nonterminal parser recovery might turn failed matches into successful ones,
153150
// but for that it must have emitted an error already
154-
self.cx.dcx().span_delayed_bug(
151+
self.dcx.span_delayed_bug(
155152
self.root_span,
156153
"should not collect detailed info for successful macro match",
157154
);
@@ -177,10 +174,10 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx,
177174
}
178175
Error(err_sp, msg) => {
179176
let span = err_sp.substitute_dummy(self.root_span);
180-
let guar = self.cx.dcx().span_err(span, msg.clone());
181-
self.result = Some(DummyResult::any(span, guar));
177+
let guar = self.dcx.span_err(span, msg.clone());
178+
self.result = Some((span, guar));
182179
}
183-
ErrorReported(guar) => self.result = Some(DummyResult::any(self.root_span, *guar)),
180+
ErrorReported(guar) => self.result = Some((self.root_span, *guar)),
184181
}
185182
}
186183

@@ -193,9 +190,9 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx,
193190
}
194191
}
195192

196-
impl<'a, 'cx> CollectTrackerAndEmitter<'a, 'cx, '_> {
197-
fn new(cx: &'a mut ExtCtxt<'cx>, root_span: Span) -> Self {
198-
Self { cx, remaining_matcher: None, best_failure: None, root_span, result: None }
193+
impl<'dcx> CollectTrackerAndEmitter<'dcx, '_> {
194+
fn new(dcx: DiagCtxtHandle<'dcx>, root_span: Span) -> Self {
195+
Self { dcx, remaining_matcher: None, best_failure: None, root_span, result: None }
199196
}
200197
}
201198

compiler/rustc_expand/src/mbe/macro_rules.rs

+28-5
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc_lint_defs::builtin::{
1818
RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
1919
};
2020
use rustc_lint_defs::BuiltinLintDiag;
21-
use rustc_middle::expand::{CanRetry, TcxMacroExpander};
21+
use rustc_middle::expand::TcxMacroExpander;
2222
use rustc_parse::parser::{ParseNtResult, Parser, Recovery};
2323
use rustc_session::parse::ParseSess;
2424
use rustc_session::Session;
@@ -149,7 +149,7 @@ impl TcxMacroExpander for MacroRulesMacroExpander {
149149
sp: Span,
150150
input: TokenStream,
151151
expand_id: LocalExpnId,
152-
) -> Result<(TokenStream, usize), CanRetry> {
152+
) -> Result<(TokenStream, usize), (Span, ErrorGuaranteed)> {
153153
// Track nothing for the best performance.
154154
let try_success_result =
155155
try_match_macro(&sess.psess, self.name, &input, &self.lhses, &mut NoopTracker);
@@ -171,10 +171,24 @@ impl TcxMacroExpander for MacroRulesMacroExpander {
171171
expand_id,
172172
) {
173173
Ok(tts) => Ok((tts, i)),
174-
Err(err) => Err(CanRetry::No(err.emit())),
174+
Err(err) => {
175+
let arm_span = self.rhses[i].span();
176+
Err((arm_span, err.emit()))
177+
}
175178
}
176179
}
177-
Err(e) => Err(e),
180+
Err(CanRetry::No(guar)) => Err((sp, guar)),
181+
Err(CanRetry::Yes) => {
182+
// Retry and emit a better error.
183+
Err(crate::mbe::diagnostics::failed_to_match_macro(
184+
&sess.psess,
185+
sp,
186+
self.span,
187+
self.name,
188+
input,
189+
&self.lhses,
190+
))
191+
}
178192
}
179193
}
180194

@@ -333,11 +347,20 @@ fn expand_macro<'cx>(
333347
}
334348
Err(CanRetry::Yes) => {
335349
// Retry and emit a better error.
336-
diagnostics::failed_to_match_macro(cx, sp, def_span, name, arg, lhses)
350+
let (span, guar) =
351+
diagnostics::failed_to_match_macro(cx.psess(), sp, def_span, name, arg, lhses);
352+
cx.trace_macros_diag();
353+
DummyResult::any(span, guar)
337354
}
338355
}
339356
}
340357

358+
pub(super) enum CanRetry {
359+
Yes,
360+
/// We are not allowed to retry macro expansion as a fatal error has been emitted already.
361+
No(ErrorGuaranteed),
362+
}
363+
341364
/// Try expanding the macro. Returns the index of the successful arm and its named_matches if it was successful,
342365
/// and nothing if it failed. On failure, it's the callers job to use `track` accordingly to record all errors
343366
/// correctly.

compiler/rustc_middle/src/expand.rs

+1-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use rustc_ast::tokenstream::TokenStream;
22
use rustc_ast::NodeId;
3-
use rustc_macros::HashStable_Generic;
43
use rustc_session::Session;
54
use rustc_span::symbol::Ident;
65
use rustc_span::{ErrorGuaranteed, LocalExpnId, Span};
@@ -12,18 +11,11 @@ pub trait TcxMacroExpander {
1211
_span: Span,
1312
_input: TokenStream,
1413
_expand_id: LocalExpnId,
15-
) -> Result<(TokenStream, usize), CanRetry>;
14+
) -> Result<(TokenStream, usize), (Span, ErrorGuaranteed)>;
1615

1716
fn name(&self) -> Ident;
1817

1918
fn arm_span(&self, rhs: usize) -> Span;
2019

2120
fn node_id(&self) -> NodeId;
2221
}
23-
24-
#[derive(Copy, Clone, HashStable_Generic, Debug)]
25-
pub enum CanRetry {
26-
Yes,
27-
/// We are not allowed to retry macro expansion as a fatal error has been emitted already.
28-
No(ErrorGuaranteed),
29-
}

compiler/rustc_middle/src/lib.rs

-2
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,6 @@ pub mod query;
9292
#[macro_use]
9393
pub mod dep_graph;
9494

95-
use rustc_span::HashStableContext;
96-
9795
// Allows macros to refer to this crate as `::rustc_middle`
9896
extern crate self as rustc_middle;
9997

compiler/rustc_middle/src/query/erase.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::intrinsics::transmute_unchecked;
22
use std::mem::MaybeUninit;
33

44
use rustc_ast::tokenstream::TokenStream;
5-
use rustc_middle::expand::CanRetry;
5+
use rustc_span::{ErrorGuaranteed, Span};
66

77
use crate::query::CyclePlaceholder;
88
use crate::ty::adjustment::CoerceUnsizedInfo;
@@ -175,8 +175,8 @@ impl EraseType for Result<ty::EarlyBinder<'_, Ty<'_>>, CyclePlaceholder> {
175175
type Result = [u8; size_of::<Result<ty::EarlyBinder<'static, Ty<'_>>, CyclePlaceholder>>()];
176176
}
177177

178-
impl EraseType for Result<(&'_ TokenStream, usize), CanRetry> {
179-
type Result = [u8; size_of::<Result<(&'_ TokenStream, usize), CanRetry>>()];
178+
impl EraseType for Result<(&'_ TokenStream, usize), (Span, ErrorGuaranteed)> {
179+
type Result = [u8; size_of::<Result<(&'_ TokenStream, usize), (Span, ErrorGuaranteed)>>()];
180180
}
181181

182182
impl<T> EraseType for Option<&'_ T> {

compiler/rustc_middle/src/query/mod.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ use rustc_target::abi;
4545
use rustc_target::spec::PanicStrategy;
4646
use {rustc_ast as ast, rustc_attr as attr, rustc_hir as hir};
4747

48-
use crate::expand::CanRetry;
4948
use crate::infer::canonical::{self, Canonical};
5049
use crate::lint::LintExpectation;
5150
use crate::metadata::ModChild;
@@ -111,7 +110,7 @@ rustc_queries! {
111110
desc { "triggering a delayed bug for testing incremental" }
112111
}
113112

114-
query expand_legacy_bang(key: (LocalExpnId, LocalExpnId)) -> Result<(&'tcx TokenStream, usize), CanRetry> {
113+
query expand_legacy_bang(key: (LocalExpnId, LocalExpnId)) -> Result<(&'tcx TokenStream, usize), (Span, ErrorGuaranteed)> {
115114
eval_always
116115
no_hash
117116
desc { "expand legacy bang" }

compiler/rustc_resolve/src/macros.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ use rustc_expand::expand::{
2222
};
2323
use rustc_hir::def::{self, DefKind, Namespace, NonMacroAttrKind};
2424
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
25-
use rustc_middle::expand::CanRetry;
2625
use rustc_middle::middle::stability;
2726
use rustc_middle::ty::{RegisteredTools, TyCtxt, Visibility};
2827
use rustc_session::lint::builtin::{
@@ -35,7 +34,7 @@ use rustc_span::edit_distance::edit_distance;
3534
use rustc_span::edition::Edition;
3635
use rustc_span::hygiene::{self, AstPass, ExpnData, ExpnKind, LocalExpnId, MacroKind};
3736
use rustc_span::symbol::{kw, sym, Ident, Symbol};
38-
use rustc_span::{Span, DUMMY_SP};
37+
use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
3938

4039
use crate::errors::{
4140
self, AddAsNonDerive, CannotDetermineMacroResolution, CannotFindIdentInThisScope,
@@ -539,7 +538,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
539538
&self,
540539
invoc_id: LocalExpnId,
541540
current_expansion: LocalExpnId,
542-
) -> Result<(TokenStream, usize), CanRetry> {
541+
) -> Result<(TokenStream, usize), (Span, ErrorGuaranteed)> {
543542
self.tcx()
544543
.expand_legacy_bang((invoc_id, current_expansion))
545544
.map(|(tts, i)| (tts.clone(), i))

0 commit comments

Comments
 (0)