Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions compiler/rustc_error_messages/locales/en-US/expand.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,12 @@ expand_explain_doc_comment_outer =

expand_explain_doc_comment_inner =
inner doc comments expand to `#![doc = "..."]`, which is what this macro attempted to match

expand_expr_repeat_no_syntax_vars =
attempted to repeat an expression containing no syntax variables matched as repeating at this depth

expand_must_repeat_once =
this must repeat at least once

count_repetition_misplaced =
`count` can not be placed inside the inner-most repetition
38 changes: 25 additions & 13 deletions compiler/rustc_expand/src/mbe/transcribe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenStream, TokenTree};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{pluralize, PResult};
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
use rustc_macros::SessionDiagnostic;
use rustc_span::hygiene::{LocalExpnId, Transparency};
use rustc_span::symbol::{sym, Ident, MacroRulesNormalizedIdent};
use rustc_span::Span;
Expand Down Expand Up @@ -53,6 +54,20 @@ impl<'a> Iterator for Frame<'a> {
}
}

#[derive(SessionDiagnostic)]
#[error(expand::expr_repeat_no_syntax_vars)]
struct NoSyntaxVarsExprRepeat {
#[primary_span]
span: Span,
}

#[derive(SessionDiagnostic)]
#[error(expand::must_repeat_once)]
struct MustRepeatOnce {
#[primary_span]
span: Span,
}

/// This can do Macro-By-Example transcription.
/// - `interp` is a map of meta-variables to the tokens (non-terminals) they matched in the
/// invocation. We are assuming we already know there is a match.
Expand Down Expand Up @@ -165,11 +180,7 @@ pub(super) fn transcribe<'a>(
seq @ mbe::TokenTree::Sequence(_, delimited) => {
match lockstep_iter_size(&seq, interp, &repeats) {
LockstepIterSize::Unconstrained => {
return Err(cx.struct_span_err(
seq.span(), /* blame macro writer */
"attempted to repeat an expression containing no syntax variables \
matched as repeating at this depth",
));
return Err(cx.create_err(NoSyntaxVarsExprRepeat { span: seq.span() }));
}

LockstepIterSize::Contradiction(msg) => {
Expand All @@ -193,10 +204,7 @@ pub(super) fn transcribe<'a>(
// FIXME: this really ought to be caught at macro definition
// time... It happens when the Kleene operator in the matcher and
// the body for the same meta-variable do not match.
return Err(cx.struct_span_err(
sp.entire(),
"this must repeat at least once",
));
return Err(cx.create_err(MustRepeatOnce { span: sp.entire() }));
}
} else {
// 0 is the initial counter (we have done 0 repetitions so far). `len`
Expand Down Expand Up @@ -420,6 +428,13 @@ fn lockstep_iter_size(
}
}

#[derive(SessionDiagnostic)]
#[error(expand::count_repetition_misplaced)]
struct CountRepetitionMisplaced {
#[primary_span]
span: Span,
}

/// Used solely by the `count` meta-variable expression, counts the outer-most repetitions at a
/// given optional nested depth.
///
Expand Down Expand Up @@ -448,10 +463,7 @@ fn count_repetitions<'a>(
match matched {
MatchedTokenTree(_) | MatchedNonterminal(_) => {
if declared_lhs_depth == 0 {
return Err(cx.struct_span_err(
sp.entire(),
"`count` can not be placed inside the inner-most repetition",
));
return Err(cx.create_err(CountRepetitionMisplaced { span: sp.entire() }));
}
match depth_opt {
None => Ok(1),
Expand Down