Skip to content

Commit e10d503

Browse files
authored
Rollup merge of #95318 - rust-lang:notriddle/issue-95208, r=wesleywiser
diagnostics: correct generic bounds with doubled colon Fixes #95208
2 parents 72770ef + 2a78372 commit e10d503

8 files changed

+93
-0
lines changed

compiler/rustc_parse/src/parser/diagnostics.rs

+28
Original file line numberDiff line numberDiff line change
@@ -2369,6 +2369,34 @@ impl<'a> Parser<'a> {
23692369
Err(err)
23702370
}
23712371

2372+
crate fn maybe_recover_bounds_doubled_colon(&mut self, ty: &Ty) -> PResult<'a, ()> {
2373+
let TyKind::Path(qself, path) = &ty.kind else { return Ok(()) };
2374+
let qself_position = qself.as_ref().map(|qself| qself.position);
2375+
for (i, segments) in path.segments.windows(2).enumerate() {
2376+
if qself_position.map(|pos| i < pos).unwrap_or(false) {
2377+
continue;
2378+
}
2379+
if let [a, b] = segments {
2380+
let (a_span, b_span) = (a.span(), b.span());
2381+
let between_span = a_span.shrink_to_hi().to(b_span.shrink_to_lo());
2382+
if self.span_to_snippet(between_span).as_ref().map(|a| &a[..]) == Ok(":: ") {
2383+
let mut err = self.struct_span_err(
2384+
path.span.shrink_to_hi(),
2385+
"expected `:` followed by trait or lifetime",
2386+
);
2387+
err.span_suggestion(
2388+
between_span,
2389+
"use single colon",
2390+
": ".to_owned(),
2391+
Applicability::MachineApplicable,
2392+
);
2393+
return Err(err);
2394+
}
2395+
}
2396+
}
2397+
Ok(())
2398+
}
2399+
23722400
/// Parse and throw away a parenthesized comma separated
23732401
/// sequence of patterns until `)` is reached.
23742402
fn skip_pat_list(&mut self) -> PResult<'a, ()> {

compiler/rustc_parse/src/parser/generics.rs

+1
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ impl<'a> Parser<'a> {
312312
id: ast::DUMMY_NODE_ID,
313313
}))
314314
} else {
315+
self.maybe_recover_bounds_doubled_colon(&ty)?;
315316
self.unexpected()
316317
}
317318
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// run-rustfix
2+
3+
#[allow(unused)]
4+
struct Struct<T>(T);
5+
6+
impl<T: Iterator> Struct<T> where <T as std:: iter::Iterator>::Item: std::fmt::Display {
7+
//~^ ERROR expected `:` followed by trait or lifetime
8+
//~| HELP use single colon
9+
}
10+
11+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// run-rustfix
2+
3+
#[allow(unused)]
4+
struct Struct<T>(T);
5+
6+
impl<T: Iterator> Struct<T> where <T as std:: iter::Iterator>::Item:: std::fmt::Display {
7+
//~^ ERROR expected `:` followed by trait or lifetime
8+
//~| HELP use single colon
9+
}
10+
11+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: expected `:` followed by trait or lifetime
2+
--> $DIR/issue-95208-ignore-qself.rs:6:88
3+
|
4+
LL | impl<T: Iterator> Struct<T> where <T as std:: iter::Iterator>::Item:: std::fmt::Display {
5+
| --- ^
6+
| |
7+
| help: use single colon: `:`
8+
9+
error: aborting due to previous error
10+
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// run-rustfix
2+
3+
#[allow(unused)]
4+
struct Struct<T>(T);
5+
6+
impl<T> Struct<T> where T: std::fmt::Display {
7+
//~^ ERROR expected `:` followed by trait or lifetime
8+
//~| HELP use single colon
9+
}
10+
11+
fn main() {}

src/test/ui/generics/issue-95208.rs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// run-rustfix
2+
3+
#[allow(unused)]
4+
struct Struct<T>(T);
5+
6+
impl<T> Struct<T> where T:: std::fmt::Display {
7+
//~^ ERROR expected `:` followed by trait or lifetime
8+
//~| HELP use single colon
9+
}
10+
11+
fn main() {}
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: expected `:` followed by trait or lifetime
2+
--> $DIR/issue-95208.rs:6:46
3+
|
4+
LL | impl<T> Struct<T> where T:: std::fmt::Display {
5+
| --- ^
6+
| |
7+
| help: use single colon: `:`
8+
9+
error: aborting due to previous error
10+

0 commit comments

Comments
 (0)