Rollup merge of #139341 - nnethercote:fix-137874, r=petrochenkov

Apply `Recovery::Forbidden` when reparsing pasted macro fragments.

Fixes #137874.

The changes to the output of `tests/ui/associated-consts/issue-93835.rs`
partly undo the changes seen when `NtTy` was removed in #133436, which
is good.

r? ``@petrochenkov``
This commit is contained in:
Stuart Cook 2025-04-05 13:18:17 +11:00 committed by GitHub
commit 66ccc4fe28
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 48 additions and 33 deletions

View file

@ -676,12 +676,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
let ty = let ty =
self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy)); self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
let safety = self.lower_safety(*safety, hir::Safety::Unsafe); let safety = self.lower_safety(*safety, hir::Safety::Unsafe);
// njn: where for this?
if define_opaque.is_some() { if define_opaque.is_some() {
self.dcx().span_err(i.span, "foreign statics cannot define opaque types"); self.dcx().span_err(i.span, "foreign statics cannot define opaque types");
} }
(ident, hir::ForeignItemKind::Static(ty, *mutability, safety)) (ident, hir::ForeignItemKind::Static(ty, *mutability, safety))
} }
ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => { ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => {

View file

@ -512,6 +512,14 @@ impl<'a> Parser<'a> {
self self
} }
#[inline]
fn with_recovery<T>(&mut self, recovery: Recovery, f: impl FnOnce(&mut Self) -> T) -> T {
let old = mem::replace(&mut self.recovery, recovery);
let res = f(self);
self.recovery = old;
res
}
/// Whether the parser is allowed to recover from broken code. /// Whether the parser is allowed to recover from broken code.
/// ///
/// If this returns false, recovering broken code into valid code (especially if this recovery does lookahead) /// If this returns false, recovering broken code into valid code (especially if this recovery does lookahead)
@ -770,7 +778,14 @@ impl<'a> Parser<'a> {
&& match_mv_kind(mv_kind) && match_mv_kind(mv_kind)
{ {
self.bump(); self.bump();
let res = f(self).expect("failed to reparse {mv_kind:?}");
// Recovery is disabled when parsing macro arguments, so it must
// also be disabled when reparsing pasted macro arguments,
// otherwise we get inconsistent results (e.g. #137874).
let res = self.with_recovery(Recovery::Forbidden, |this| {
f(this).expect("failed to reparse {mv_kind:?}")
});
if let token::CloseDelim(delim) = self.token.kind if let token::CloseDelim(delim) = self.token.kind
&& let Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind)) = delim && let Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind)) = delim
&& match_mv_kind(mv_kind) && match_mv_kind(mv_kind)

View file

@ -1,4 +0,0 @@
//@ known-bug: #137874
fn a() {
match b { deref !(0c) };
}

View file

@ -3,11 +3,10 @@
fn e() { fn e() {
type_ascribe!(p, a<p:p<e=6>>); type_ascribe!(p, a<p:p<e=6>>);
//~^ ERROR cannot find type `a` in this scope //~^ ERROR cannot find type `a` in this scope
//~| ERROR path separator must be a double colon
//~| ERROR cannot find value //~| ERROR cannot find value
//~| ERROR associated const equality //~| ERROR associated const equality
//~| ERROR cannot find trait `p` in this scope
//~| ERROR associated const equality //~| ERROR associated const equality
//~| ERROR failed to resolve: use of unresolved module or unlinked crate `p`
} }
fn main() {} fn main() {}

View file

@ -1,15 +1,3 @@
error: path separator must be a double colon
--> $DIR/issue-93835.rs:4:25
|
LL | type_ascribe!(p, a<p:p<e=6>>);
| ^
|
= note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
help: use a double colon instead
|
LL | type_ascribe!(p, a<p::p<e=6>>);
| +
error[E0425]: cannot find value `p` in this scope error[E0425]: cannot find value `p` in this scope
--> $DIR/issue-93835.rs:4:19 --> $DIR/issue-93835.rs:4:19
| |
@ -22,6 +10,12 @@ error[E0412]: cannot find type `a` in this scope
LL | type_ascribe!(p, a<p:p<e=6>>); LL | type_ascribe!(p, a<p:p<e=6>>);
| ^ not found in this scope | ^ not found in this scope
error[E0405]: cannot find trait `p` in this scope
--> $DIR/issue-93835.rs:4:26
|
LL | type_ascribe!(p, a<p:p<e=6>>);
| ^ not found in this scope
error[E0658]: associated const equality is incomplete error[E0658]: associated const equality is incomplete
--> $DIR/issue-93835.rs:4:28 --> $DIR/issue-93835.rs:4:28
| |
@ -43,15 +37,7 @@ LL | type_ascribe!(p, a<p:p<e=6>>);
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0433]: failed to resolve: use of unresolved module or unlinked crate `p` error: aborting due to 5 previous errors
--> $DIR/issue-93835.rs:4:24
|
LL | type_ascribe!(p, a<p:p<e=6>>);
| ^ use of unresolved module or unlinked crate `p`
|
= help: you might be missing a crate named `p`
error: aborting due to 6 previous errors Some errors have detailed explanations: E0405, E0412, E0425, E0658.
For more information about an error, try `rustc --explain E0405`.
Some errors have detailed explanations: E0412, E0425, E0433, E0658.
For more information about an error, try `rustc --explain E0412`.

View file

@ -0,0 +1,12 @@
// This originally crashed because `Recovery::Forbidden` wasn't being applied
// when fragments pasted by declarative macros were reparsed.
macro_rules! m {
($p:pat) => {
if let $p = 0 {}
}
}
fn main() {
m!(0X0); //~ ERROR invalid base prefix for number literal
}

View file

@ -0,0 +1,10 @@
error: invalid base prefix for number literal
--> $DIR/failed-to-reparse-issue-137874.rs:11:8
|
LL | m!(0X0);
| ^^^ help: try making the prefix lowercase (notice the capitalization): `0x0`
|
= note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
error: aborting due to 1 previous error