Rollup merge of #140228 - fmease:revert-overzealous-colon-recovery, r=jieyouxu
Revert overzealous parse recovery for single colons in paths Basically manually reverts #136808, cc ``@chenyukang`` ``@estebank.`` Reopens #129273. Fixes [after beta backport] #140227.
This commit is contained in:
@@ -2058,6 +2058,17 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
self.expect_field_ty_separator()?;
|
self.expect_field_ty_separator()?;
|
||||||
let ty = self.parse_ty()?;
|
let ty = self.parse_ty()?;
|
||||||
|
if self.token == token::Colon && self.look_ahead(1, |&t| t != token::Colon) {
|
||||||
|
self.dcx()
|
||||||
|
.struct_span_err(self.token.span, "found single colon in a struct field type path")
|
||||||
|
.with_span_suggestion_verbose(
|
||||||
|
self.token.span,
|
||||||
|
"write a path separator here",
|
||||||
|
"::",
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
let default = if self.token == token::Eq {
|
let default = if self.token == token::Eq {
|
||||||
self.bump();
|
self.bump();
|
||||||
let const_expr = self.parse_expr_anon_const()?;
|
let const_expr = self.parse_expr_anon_const()?;
|
||||||
|
|||||||
@@ -248,19 +248,13 @@ impl<'a> Parser<'a> {
|
|||||||
segments.push(segment);
|
segments.push(segment);
|
||||||
|
|
||||||
if self.is_import_coupler() || !self.eat_path_sep() {
|
if self.is_import_coupler() || !self.eat_path_sep() {
|
||||||
let ok_for_recovery = self.may_recover()
|
// IMPORTANT: We can *only ever* treat single colons as typo'ed double colons in
|
||||||
&& match style {
|
// expression contexts (!) since only there paths cannot possibly be followed by
|
||||||
PathStyle::Expr => true,
|
// a colon and still form a syntactically valid construct. In pattern contexts,
|
||||||
PathStyle::Type if let Some((ident, _)) = self.prev_token.ident() => {
|
// a path may be followed by a type annotation. E.g., `let pat:ty`. In type
|
||||||
self.token == token::Colon
|
// contexts, a path may be followed by a list of bounds. E.g., `where ty:bound`.
|
||||||
&& ident.as_str().chars().all(|c| c.is_lowercase())
|
if self.may_recover()
|
||||||
&& self.token.span.lo() == self.prev_token.span.hi()
|
&& style == PathStyle::Expr // (!)
|
||||||
&& self
|
|
||||||
.look_ahead(1, |token| self.token.span.hi() == token.span.lo())
|
|
||||||
}
|
|
||||||
_ => false,
|
|
||||||
};
|
|
||||||
if ok_for_recovery
|
|
||||||
&& self.token == token::Colon
|
&& self.token == token::Colon
|
||||||
&& self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident())
|
&& self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
error: path separator must be a double colon
|
error: path separator must be a double colon
|
||||||
--> $DIR/single-colon-path-not-const-generics.rs:8:18
|
--> $DIR/single-colon-path-not-const-generics.rs:8:18
|
||||||
|
|
|
|
||||||
|
LL | pub struct Foo {
|
||||||
|
| --- while parsing this struct
|
||||||
LL | a: Vec<foo::bar:A>,
|
LL | a: Vec<foo::bar:A>,
|
||||||
| ^
|
| ^
|
||||||
|
|
|
|
||||||
help: use a double colon instead
|
help: use a double colon instead
|
||||||
|
|
|
|
||||||
LL | a: Vec<foo::bar::A>,
|
LL | a: Vec<foo::bar::A>,
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
|||||||
22
tests/ui/parser/ty-path-followed-by-single-colon.rs
Normal file
22
tests/ui/parser/ty-path-followed-by-single-colon.rs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
// Paths in type contexts may be followed by single colons.
|
||||||
|
// This means we can't generally assume that the user typo'ed a double colon.
|
||||||
|
// issue: <https://github.com/rust-lang/rust/issues/140227>
|
||||||
|
//@ check-pass
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
#![expect(non_camel_case_types)]
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
mod garden {
|
||||||
|
|
||||||
|
fn f<path>() where path:to::somewhere {} // OK!
|
||||||
|
|
||||||
|
fn g(_: impl Take<path:to::somewhere>) {} // OK!
|
||||||
|
|
||||||
|
#[cfg(any())] fn h() where a::path:to::nowhere {} // OK!
|
||||||
|
|
||||||
|
fn i(_: impl Take<path::<>:to::somewhere>) {} // OK!
|
||||||
|
|
||||||
|
mod to { pub(super) trait somewhere {} }
|
||||||
|
trait Take { type path; }
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
//@ run-rustfix
|
|
||||||
|
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
struct Hello;
|
|
||||||
|
|
||||||
impl fmt::Display for Hello {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { //~ ERROR path separator must be a double colon
|
|
||||||
write!(f, "hello")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let _ = Hello;
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
//@ run-rustfix
|
|
||||||
|
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
struct Hello;
|
|
||||||
|
|
||||||
impl fmt::Display for Hello {
|
|
||||||
fn fmt(&self, f: &mut fmt:Formatter) -> fmt::Result { //~ ERROR path separator must be a double colon
|
|
||||||
write!(f, "hello")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let _ = Hello;
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
error: path separator must be a double colon
|
|
||||||
--> $DIR/argument-list-from-path-sep-error-129273.rs:8:30
|
|
||||||
|
|
|
||||||
LL | fn fmt(&self, f: &mut fmt:Formatter) -> fmt::Result {
|
|
||||||
| ^
|
|
||||||
|
|
|
||||||
help: use a double colon instead
|
|
||||||
|
|
|
||||||
LL | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
| +
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
|
||||||
|
|
||||||
@@ -7,14 +7,14 @@ mod foo {
|
|||||||
|
|
||||||
struct Foo {
|
struct Foo {
|
||||||
a: foo:A,
|
a: foo:A,
|
||||||
//~^ ERROR path separator must be a double colon
|
//~^ ERROR found single colon in a struct field type path
|
||||||
//~| ERROR struct `A` is private
|
//~| ERROR expected `,`, or `}`, found `:`
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Bar {
|
struct Bar {
|
||||||
b: foo::bar:B,
|
b: foo::bar:B,
|
||||||
//~^ ERROR path separator must be a double colon
|
//~^ ERROR found single colon in a struct field type path
|
||||||
//~| ERROR module `bar` is private
|
//~| ERROR expected `,`, or `}`, found `:`
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|||||||
@@ -1,51 +1,40 @@
|
|||||||
error: path separator must be a double colon
|
error: found single colon in a struct field type path
|
||||||
--> $DIR/struct-field-type-including-single-colon.rs:9:11
|
--> $DIR/struct-field-type-including-single-colon.rs:9:11
|
||||||
|
|
|
|
||||||
LL | a: foo:A,
|
LL | a: foo:A,
|
||||||
| ^
|
| ^
|
||||||
|
|
|
|
||||||
help: use a double colon instead
|
help: write a path separator here
|
||||||
|
|
|
|
||||||
LL | a: foo::A,
|
LL | a: foo::A,
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: path separator must be a double colon
|
error: expected `,`, or `}`, found `:`
|
||||||
|
--> $DIR/struct-field-type-including-single-colon.rs:9:11
|
||||||
|
|
|
||||||
|
LL | struct Foo {
|
||||||
|
| --- while parsing this struct
|
||||||
|
LL | a: foo:A,
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: found single colon in a struct field type path
|
||||||
--> $DIR/struct-field-type-including-single-colon.rs:15:16
|
--> $DIR/struct-field-type-including-single-colon.rs:15:16
|
||||||
|
|
|
|
||||||
LL | b: foo::bar:B,
|
LL | b: foo::bar:B,
|
||||||
| ^
|
| ^
|
||||||
|
|
|
|
||||||
help: use a double colon instead
|
help: write a path separator here
|
||||||
|
|
|
|
||||||
LL | b: foo::bar::B,
|
LL | b: foo::bar::B,
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error[E0603]: struct `A` is private
|
error: expected `,`, or `}`, found `:`
|
||||||
--> $DIR/struct-field-type-including-single-colon.rs:9:12
|
--> $DIR/struct-field-type-including-single-colon.rs:15:16
|
||||||
|
|
|
||||||
LL | a: foo:A,
|
|
||||||
| ^ private struct
|
|
||||||
|
|
|
||||||
note: the struct `A` is defined here
|
|
||||||
--> $DIR/struct-field-type-including-single-colon.rs:2:5
|
|
||||||
|
|
|
||||||
LL | struct A;
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
||||||
error[E0603]: module `bar` is private
|
|
||||||
--> $DIR/struct-field-type-including-single-colon.rs:15:13
|
|
||||||
|
|
|
|
||||||
|
LL | struct Bar {
|
||||||
|
| --- while parsing this struct
|
||||||
LL | b: foo::bar:B,
|
LL | b: foo::bar:B,
|
||||||
| ^^^ - struct `B` is not publicly re-exported
|
| ^
|
||||||
| |
|
|
||||||
| private module
|
|
||||||
|
|
|
||||||
note: the module `bar` is defined here
|
|
||||||
--> $DIR/struct-field-type-including-single-colon.rs:3:5
|
|
||||||
|
|
|
||||||
LL | mod bar {
|
|
||||||
| ^^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0603`.
|
|
||||||
|
|||||||
Reference in New Issue
Block a user