Skip to content

Commit

Permalink
Suggest syntax when finding method on array
Browse files Browse the repository at this point in the history
On a file like the following:

```rust
fn main() {
    let a = [1, 2, 3];
    let _ = [i32; 3]::clone(&a);
}
```

it is a fair assumption that what was meant was to use an associated
type on an array, so we suggest the correct syntax:

```
error: expected one of `.`, `;`, `?`, or an operator, found `::`
 --> file.rs:3:21
  |
3 |     let _ = [i32; 3]::clone(&a);
  |             --------^^
  |             |       |
  |             |       expected one of `.`, `;`, `?`, or an operator here
  |             help: did you mean to use an associated type?: `<[i32; 3]>::`
```
  • Loading branch information
estebank committed Oct 2, 2017
1 parent 14039a4 commit 78e7fa0
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,7 @@ impl fmt::Debug for Stmt {
}


#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
#[derive(Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
pub enum StmtKind {
/// A local (let) binding.
Local(P<Local>),
Expand Down
26 changes: 25 additions & 1 deletion src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3653,7 +3653,9 @@ impl<'a> Parser<'a> {
} else {
None
};
debug!("parse_local ty {:?}", ty);
let init = self.parse_initializer()?;
debug!("parse_local init {:?}", init);
Ok(P(ast::Local {
ty,
pat,
Expand Down Expand Up @@ -4173,7 +4175,29 @@ impl<'a> Parser<'a> {
if macro_legacy_warnings && self.token != token::Semi {
self.warn_missing_semicolon();
} else {
self.expect_one_of(&[token::Semi], &[])?;
match self.expect_one_of(&[token::Semi], &[]) {
Ok(_) => (),
Err(mut err) => {
if let (token::ModSep, StmtKind::Local(local)) = (self.token,
stmt.node) {
if let Some(ref init) = local.init {
// We have an initializer for the `let` binding, which means
// that "something" was parsed correctly as a value there, but
// was followed by more code.
if let ExprKind::Repeat(_, _) = init.node {
let expr_str = self.sess.codemap()
.span_to_snippet(init.span)
.unwrap_or(pprust::expr_to_string(init));
err.span_suggestion(init.span.to(self.span),
"did you mean to use an associated \
type instead?",
format!("<{}>::", expr_str));
}
}
}
return Err(err);
}
}
}
}
_ => {}
Expand Down
14 changes: 14 additions & 0 deletions src/test/ui/suggestions/associated-item-from-array.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

fn main() {
let a = [1, 2, 3];
let _ = [i32; 3]::clone(&a);
}
11 changes: 11 additions & 0 deletions src/test/ui/suggestions/associated-item-from-array.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error: expected one of `.`, `;`, `?`, or an operator, found `::`
--> $DIR/associated-item-from-array.rs:13:21
|
13 | let _ = [i32; 3]::clone(&a);
| --------^^
| | |
| | expected one of `.`, `;`, `?`, or an operator here
| help: did you mean to use an associated type?: `<[i32; 3]>::`

error: aborting due to previous error

0 comments on commit 78e7fa0

Please sign in to comment.