Skip to content

Commit 7da4f76

Browse files
authored
Unrolled build for rust-lang#130673
Rollup merge of rust-lang#130673 - GrigorenkoPV:path-triple-colon, r=compiler-errors Parser: recover from `:::` to `::` Closes rust-lang#130613
2 parents 1d68e6d + 82482dc commit 7da4f76

11 files changed

+366
-16
lines changed

compiler/rustc_parse/messages.ftl

+1-1
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ parse_parentheses_with_struct_fields = invalid `struct` delimiters or `fn` call
670670
parse_parenthesized_lifetime = parenthesized lifetime bounds are not supported
671671
parse_parenthesized_lifetime_suggestion = remove the parentheses
672672
673-
parse_path_single_colon = path separator must be a double colon
673+
parse_path_double_colon = path separator must be a double colon
674674
.suggestion = use a double colon instead
675675
676676
parse_pattern_method_param_without_body = patterns aren't allowed in methods without bodies

compiler/rustc_parse/src/errors.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -1571,7 +1571,7 @@ pub(crate) struct ExpectedFnPathFoundFnKeyword {
15711571
}
15721572

15731573
#[derive(Diagnostic)]
1574-
#[diag(parse_path_single_colon)]
1574+
#[diag(parse_path_double_colon)]
15751575
pub(crate) struct PathSingleColon {
15761576
#[primary_span]
15771577
pub span: Span,
@@ -1583,6 +1583,14 @@ pub(crate) struct PathSingleColon {
15831583
pub type_ascription: bool,
15841584
}
15851585

1586+
#[derive(Diagnostic)]
1587+
#[diag(parse_path_double_colon)]
1588+
pub(crate) struct PathTripleColon {
1589+
#[primary_span]
1590+
#[suggestion(applicability = "maybe-incorrect", code = "", style = "verbose")]
1591+
pub span: Span,
1592+
}
1593+
15861594
#[derive(Diagnostic)]
15871595
#[diag(parse_colon_as_semi)]
15881596
pub(crate) struct ColonAsSemi {

compiler/rustc_parse/src/parser/item.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -707,7 +707,7 @@ impl<'a> Parser<'a> {
707707
})
708708
};
709709

710-
let (ident, item_kind) = if self.eat(&token::PathSep) {
710+
let (ident, item_kind) = if self.eat_path_sep() {
711711
let suffixes = if self.eat(&token::BinOp(token::Star)) {
712712
None
713713
} else {
@@ -1054,7 +1054,7 @@ impl<'a> Parser<'a> {
10541054
{
10551055
// `use *;` or `use ::*;` or `use {...};` or `use ::{...};`
10561056
let mod_sep_ctxt = self.token.span.ctxt();
1057-
if self.eat(&token::PathSep) {
1057+
if self.eat_path_sep() {
10581058
prefix
10591059
.segments
10601060
.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
@@ -1065,7 +1065,7 @@ impl<'a> Parser<'a> {
10651065
// `use path::*;` or `use path::{...};` or `use path;` or `use path as bar;`
10661066
prefix = self.parse_path(PathStyle::Mod)?;
10671067

1068-
if self.eat(&token::PathSep) {
1068+
if self.eat_path_sep() {
10691069
self.parse_use_tree_glob_or_nested()?
10701070
} else {
10711071
// Recover from using a colon as path separator.

compiler/rustc_parse/src/parser/mod.rs

+17-4
Original file line numberDiff line numberDiff line change
@@ -1562,12 +1562,25 @@ impl<'a> Parser<'a> {
15621562
})
15631563
}
15641564

1565+
/// Checks for `::` or, potentially, `:::` and then look ahead after it.
1566+
fn check_path_sep_and_look_ahead(&mut self, looker: impl Fn(&Token) -> bool) -> bool {
1567+
if self.check(&token::PathSep) {
1568+
if self.may_recover() && self.look_ahead(1, |t| t.kind == token::Colon) {
1569+
debug_assert!(!self.look_ahead(1, &looker), "Looker must not match on colon");
1570+
self.look_ahead(2, looker)
1571+
} else {
1572+
self.look_ahead(1, looker)
1573+
}
1574+
} else {
1575+
false
1576+
}
1577+
}
1578+
15651579
/// `::{` or `::*`
15661580
fn is_import_coupler(&mut self) -> bool {
1567-
self.check(&token::PathSep)
1568-
&& self.look_ahead(1, |t| {
1569-
*t == token::OpenDelim(Delimiter::Brace) || *t == token::BinOp(token::Star)
1570-
})
1581+
self.check_path_sep_and_look_ahead(|t| {
1582+
matches!(t.kind, token::OpenDelim(Delimiter::Brace) | token::BinOp(token::Star))
1583+
})
15711584
}
15721585

15731586
// Debug view of the parser's token stream, up to `{lookahead}` tokens.

compiler/rustc_parse/src/parser/path.rs

+18-7
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use tracing::debug;
1616

1717
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
1818
use super::{Parser, Restrictions, TokenType};
19-
use crate::errors::PathSingleColon;
19+
use crate::errors::{PathSingleColon, PathTripleColon};
2020
use crate::parser::{CommaRecoveryMode, RecoverColon, RecoverComma};
2121
use crate::{errors, maybe_whole};
2222

@@ -210,7 +210,7 @@ impl<'a> Parser<'a> {
210210
let lo = self.token.span;
211211
let mut segments = ThinVec::new();
212212
let mod_sep_ctxt = self.token.span.ctxt();
213-
if self.eat(&token::PathSep) {
213+
if self.eat_path_sep() {
214214
segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
215215
}
216216
self.parse_path_segments(&mut segments, style, ty_generics)?;
@@ -246,7 +246,7 @@ impl<'a> Parser<'a> {
246246
}
247247
segments.push(segment);
248248

249-
if self.is_import_coupler() || !self.eat(&token::PathSep) {
249+
if self.is_import_coupler() || !self.eat_path_sep() {
250250
if style == PathStyle::Expr
251251
&& self.may_recover()
252252
&& self.token == token::Colon
@@ -272,6 +272,18 @@ impl<'a> Parser<'a> {
272272
}
273273
}
274274

275+
/// Eat `::` or, potentially, `:::`.
276+
#[must_use]
277+
pub(super) fn eat_path_sep(&mut self) -> bool {
278+
let result = self.eat(&token::PathSep);
279+
if result && self.may_recover() {
280+
if self.eat_noexpect(&token::Colon) {
281+
self.dcx().emit_err(PathTripleColon { span: self.prev_token.span });
282+
}
283+
}
284+
result
285+
}
286+
275287
pub(super) fn parse_path_segment(
276288
&mut self,
277289
style: PathStyle,
@@ -297,9 +309,7 @@ impl<'a> Parser<'a> {
297309

298310
Ok(
299311
if style == PathStyle::Type && check_args_start(self)
300-
|| style != PathStyle::Mod
301-
&& self.check(&token::PathSep)
302-
&& self.look_ahead(1, |t| is_args_start(t))
312+
|| style != PathStyle::Mod && self.check_path_sep_and_look_ahead(is_args_start)
303313
{
304314
// We use `style == PathStyle::Expr` to check if this is in a recursion or not. If
305315
// it isn't, then we reset the unmatched angle bracket count as we're about to start
@@ -310,7 +320,8 @@ impl<'a> Parser<'a> {
310320

311321
// Generic arguments are found - `<`, `(`, `::<` or `::(`.
312322
// First, eat `::` if it exists.
313-
let _ = self.eat(&token::PathSep);
323+
let _ = self.eat_path_sep();
324+
314325
let lo = self.token.span;
315326
let args = if self.eat_lt() {
316327
// `<'a, T, A = U>`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//@ run-rustfix
2+
3+
#![feature(fn_delegation)]
4+
#![allow(incomplete_features, unused)]
5+
6+
trait Trait {
7+
fn foo(&self) {}
8+
}
9+
10+
struct F;
11+
impl Trait for F {}
12+
13+
pub mod to_reuse {
14+
pub fn bar() {}
15+
}
16+
17+
mod fn_to_other {
18+
use super::*;
19+
20+
reuse Trait::foo; //~ ERROR path separator must be a double colon
21+
reuse to_reuse::bar; //~ ERROR path separator must be a double colon
22+
}
23+
24+
impl Trait for u8 {}
25+
26+
struct S(u8);
27+
28+
mod to_import {
29+
pub fn check(arg: &u8) -> &u8 { arg }
30+
}
31+
32+
impl Trait for S {
33+
reuse Trait::* { //~ ERROR path separator must be a double colon
34+
use to_import::check;
35+
36+
let _arr = Some(self.0).map(|x| [x * 2; 3]);
37+
check(&self.0)
38+
}
39+
}
40+
41+
fn main() {
42+
let s = S(0);
43+
s.foo();
44+
}
+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//@ run-rustfix
2+
3+
#![feature(fn_delegation)]
4+
#![allow(incomplete_features, unused)]
5+
6+
trait Trait {
7+
fn foo(&self) {}
8+
}
9+
10+
struct F;
11+
impl Trait for F {}
12+
13+
pub mod to_reuse {
14+
pub fn bar() {}
15+
}
16+
17+
mod fn_to_other {
18+
use super::*;
19+
20+
reuse Trait:::foo; //~ ERROR path separator must be a double colon
21+
reuse to_reuse:::bar; //~ ERROR path separator must be a double colon
22+
}
23+
24+
impl Trait for u8 {}
25+
26+
struct S(u8);
27+
28+
mod to_import {
29+
pub fn check(arg: &u8) -> &u8 { arg }
30+
}
31+
32+
impl Trait for S {
33+
reuse Trait:::* { //~ ERROR path separator must be a double colon
34+
use to_import::check;
35+
36+
let _arr = Some(self.0).map(|x| [x * 2; 3]);
37+
check(&self.0)
38+
}
39+
}
40+
41+
fn main() {
42+
let s = S(0);
43+
s.foo();
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
error: path separator must be a double colon
2+
--> $DIR/triple-colon-delegation.rs:20:18
3+
|
4+
LL | reuse Trait:::foo;
5+
| ^
6+
|
7+
help: use a double colon instead
8+
|
9+
LL - reuse Trait:::foo;
10+
LL + reuse Trait::foo;
11+
|
12+
13+
error: path separator must be a double colon
14+
--> $DIR/triple-colon-delegation.rs:21:21
15+
|
16+
LL | reuse to_reuse:::bar;
17+
| ^
18+
|
19+
help: use a double colon instead
20+
|
21+
LL - reuse to_reuse:::bar;
22+
LL + reuse to_reuse::bar;
23+
|
24+
25+
error: path separator must be a double colon
26+
--> $DIR/triple-colon-delegation.rs:33:18
27+
|
28+
LL | reuse Trait:::* {
29+
| ^
30+
|
31+
help: use a double colon instead
32+
|
33+
LL - reuse Trait:::* {
34+
LL + reuse Trait::* {
35+
|
36+
37+
error: aborting due to 3 previous errors
38+

tests/ui/parser/triple-colon.fixed

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//@ run-rustfix
2+
3+
#![allow(unused)]
4+
5+
use ::std::{cell as _}; //~ ERROR path separator must be a double colon
6+
use std::cell::*; //~ ERROR path separator must be a double colon
7+
use std::cell::Cell; //~ ERROR path separator must be a double colon
8+
use std::{cell as _}; //~ ERROR path separator must be a double colon
9+
10+
mod foo{
11+
use ::{}; //~ ERROR path separator must be a double colon
12+
use ::*; //~ ERROR path separator must be a double colon
13+
}
14+
15+
fn main() {
16+
let c: ::std::cell::Cell::<u8> = Cell::<u8>::new(0);
17+
//~^ ERROR path separator must be a double colon
18+
//~| ERROR path separator must be a double colon
19+
//~| ERROR path separator must be a double colon
20+
//~| ERROR path separator must be a double colon
21+
//~| ERROR path separator must be a double colon
22+
//~| ERROR path separator must be a double colon
23+
}

tests/ui/parser/triple-colon.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//@ run-rustfix
2+
3+
#![allow(unused)]
4+
5+
use :::std::{cell as _}; //~ ERROR path separator must be a double colon
6+
use std::cell:::*; //~ ERROR path separator must be a double colon
7+
use std::cell:::Cell; //~ ERROR path separator must be a double colon
8+
use std:::{cell as _}; //~ ERROR path separator must be a double colon
9+
10+
mod foo{
11+
use :::{}; //~ ERROR path separator must be a double colon
12+
use :::*; //~ ERROR path separator must be a double colon
13+
}
14+
15+
fn main() {
16+
let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
17+
//~^ ERROR path separator must be a double colon
18+
//~| ERROR path separator must be a double colon
19+
//~| ERROR path separator must be a double colon
20+
//~| ERROR path separator must be a double colon
21+
//~| ERROR path separator must be a double colon
22+
//~| ERROR path separator must be a double colon
23+
}

0 commit comments

Comments
 (0)