Skip to content

Commit

Permalink
Rollup merge of rust-lang#68681 - bobrippling:fix-matched-angle-brack…
Browse files Browse the repository at this point in the history
…ets, r=Centril

Suggest path separator for single-colon typos

This commit adds guidance for when a user means to type a path, but ends
up typing a single colon, such as `<<Impl as T>:Ty>`.

This change seemed pertinent as the current error message is
particularly misleading, emitting `error: unmatched angle bracket`,
despite the angle bracket being matched later on, leaving the user to
track down the typo'd colon.
  • Loading branch information
JohnTitor authored Feb 1, 2020
2 parents bf68a05 + 07ee472 commit b18b269
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 1 deletion.
37 changes: 36 additions & 1 deletion src/librustc_parse/parser/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,49 @@ impl<'a> Parser<'a> {
debug!("parse_qpath: (decrement) count={:?}", self.unmatched_angle_bracket_count);
}

self.expect(&token::ModSep)?;
if !self.recover_colon_before_qpath_proj() {
self.expect(&token::ModSep)?;
}

let qself = QSelf { ty, path_span, position: path.segments.len() };
self.parse_path_segments(&mut path.segments, style)?;

Ok((qself, Path { segments: path.segments, span: lo.to(self.prev_span) }))
}

/// Recover from an invalid single colon, when the user likely meant a qualified path.
/// We avoid emitting this if not followed by an identifier, as our assumption that the user
/// intended this to be a qualified path may not be correct.
///
/// ```ignore (diagnostics)
/// <Bar as Baz<T>>:Qux
/// ^ help: use double colon
/// ```
fn recover_colon_before_qpath_proj(&mut self) -> bool {
if self.token.kind != token::Colon
|| self.look_ahead(1, |t| !t.is_ident() || t.is_reserved_ident())
{
return false;
}

self.bump(); // colon

self.diagnostic()
.struct_span_err(
self.prev_span,
"found single colon before projection in qualified path",
)
.span_suggestion(
self.prev_span,
"use double colon",
"::".to_string(),
Applicability::MachineApplicable,
)
.emit();

true
}

/// Parses simple paths.
///
/// `path = [::] segment+`
Expand Down
19 changes: 19 additions & 0 deletions src/test/ui/parser/qualified-path-in-turbofish.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// run-rustfix
trait T {
type Ty;
}

struct Impl;

impl T for Impl {
type Ty = u32;
}

fn template<T>() -> i64 {
3
}

fn main() {
template::<<Impl as T>::Ty>();
//~^ ERROR found single colon before projection in qualified path
}
19 changes: 19 additions & 0 deletions src/test/ui/parser/qualified-path-in-turbofish.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// run-rustfix
trait T {
type Ty;
}

struct Impl;

impl T for Impl {
type Ty = u32;
}

fn template<T>() -> i64 {
3
}

fn main() {
template::<<Impl as T>:Ty>();
//~^ ERROR found single colon before projection in qualified path
}
8 changes: 8 additions & 0 deletions src/test/ui/parser/qualified-path-in-turbofish.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error: found single colon before projection in qualified path
--> $DIR/qualified-path-in-turbofish.rs:17:27
|
LL | template::<<Impl as T>:Ty>();
| ^ help: use double colon: `::`

error: aborting due to previous error

0 comments on commit b18b269

Please # to comment.