resolution
}
- fn type_ascription_suggestion(&self,
- err: &mut DiagnosticBuilder<'_>,
- base_span: Span) {
+ /// Only used in a specific case of type ascription suggestions
+ #[doc(hidden)]
+ fn get_colon_suggestion_span(&self, start: Span) -> Span {
+ let cm = self.session.source_map();
+ start.to(cm.next_point(start))
+ }
+
+ fn type_ascription_suggestion(
+ &self,
+ err: &mut DiagnosticBuilder<'_>,
+ base_span: Span,
+ ) {
debug!("type_ascription_suggetion {:?}", base_span);
let cm = self.session.source_map();
+ let base_snippet = cm.span_to_snippet(base_span);
debug!("self.current_type_ascription {:?}", self.current_type_ascription);
if let Some(sp) = self.current_type_ascription.last() {
let mut sp = *sp;
// Try to find the `:`; bail on first non-':' / non-whitespace.
sp = cm.next_point(sp);
if let Ok(snippet) = cm.span_to_snippet(sp.to(cm.next_point(sp))) {
- debug!("snippet {:?}", snippet);
let line_sp = cm.lookup_char_pos(sp.hi()).line;
let line_base_sp = cm.lookup_char_pos(base_span.lo()).line;
- debug!("{:?} {:?}", line_sp, line_base_sp);
if snippet == ":" {
err.span_label(base_span,
"expecting a type here because of type ascription");
";".to_string(),
Applicability::MaybeIncorrect,
);
+ } else {
+ let colon_sp = self.get_colon_suggestion_span(sp);
+ let after_colon_sp = self.get_colon_suggestion_span(
+ colon_sp.shrink_to_hi(),
+ );
+ if !cm.span_to_snippet(after_colon_sp).map(|s| s == " ")
+ .unwrap_or(false)
+ {
+ err.span_suggestion(
+ colon_sp,
+ "maybe you meant to write a path separator here",
+ "::".to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ if let Ok(base_snippet) = base_snippet {
+ err.span_suggestion(
+ base_span,
+ "maybe you meant to write an assignment here",
+ format!("let {}", base_snippet),
+ Applicability::MaybeIncorrect,
+ );
+ }
}
break;
} else if !snippet.trim().is_empty() {
lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Cast)?;
continue
} else if op == AssocOp::Colon {
+ let maybe_path = self.could_ascription_be_path(&lhs.node);
+ let next_sp = self.span;
+
lhs = match self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Type) {
Ok(lhs) => lhs,
Err(mut err) => {
- err.span_label(self.span,
- "expecting a type here because of type ascription");
- let cm = self.sess.source_map();
- let cur_pos = cm.lookup_char_pos(self.span.lo());
- let op_pos = cm.lookup_char_pos(cur_op_span.hi());
- if cur_pos.line != op_pos.line {
- err.span_suggestion(
- cur_op_span,
- "try using a semicolon",
- ";".to_string(),
- Applicability::MaybeIncorrect // speculative
- );
- }
+ self.bad_type_ascription(
+ &mut err,
+ lhs_span,
+ cur_op_span,
+ next_sp,
+ maybe_path,
+ );
return Err(err);
}
};
Ok(lhs)
}
+ fn could_ascription_be_path(&self, node: &ast::ExprKind) -> bool {
+ self.token.is_ident() &&
+ if let ast::ExprKind::Path(..) = node { true } else { false } &&
+ !self.token.is_reserved_ident() && // v `foo:bar(baz)`
+ self.look_ahead(1, |t| t == &token::OpenDelim(token::Paren)) ||
+ self.look_ahead(1, |t| t == &token::Lt) && // `foo:bar<baz`
+ self.look_ahead(2, |t| t.is_ident()) ||
+ self.look_ahead(1, |t| t == &token::Colon) && // `foo:bar:baz`
+ self.look_ahead(2, |t| t.is_ident()) ||
+ self.look_ahead(1, |t| t == &token::ModSep) && // `foo:bar::baz`
+ self.look_ahead(2, |t| t.is_ident())
+ }
+
+ fn bad_type_ascription(
+ &self,
+ err: &mut DiagnosticBuilder<'a>,
+ lhs_span: Span,
+ cur_op_span: Span,
+ next_sp: Span,
+ maybe_path: bool,
+ ) {
+ err.span_label(self.span, "expecting a type here because of type ascription");
+ let cm = self.sess.source_map();
+ let next_pos = cm.lookup_char_pos(next_sp.lo());
+ let op_pos = cm.lookup_char_pos(cur_op_span.hi());
+ if op_pos.line != next_pos.line {
+ err.span_suggestion(
+ cur_op_span,
+ "try using a semicolon",
+ ";".to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ } else {
+ if maybe_path {
+ err.span_suggestion(
+ cur_op_span,
+ "maybe you meant to write a path separator here",
+ "::".to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ } else {
+ err.note("type ascription is a nightly only feature that lets \
+ you annotate expressions with a type: `<expr>: <type>`");
+ err.span_note(
+ lhs_span,
+ "this expression is annotated with type ascription...",
+ );
+ err.span_note(
+ cur_op_span,
+ "...due to this, which is why a type is expected after",
+ );
+ err.help("this might be indicative of a syntax error elsewhere");
+ }
+ }
+ }
+
fn parse_assoc_op_cast(&mut self, lhs: P<Expr>, lhs_span: Span,
expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind)
-> PResult<'a, P<Expr>> {
|
LL | if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
| ^ expecting a type here because of type ascription
+ |
+ = note: type ascription is a nightly only feature that lets you annotate expressions with a type: `<expr>: <type>`
+note: this expression is annotated with type ascription...
+ --> $DIR/E0423.rs:12:36
+ |
+LL | if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
+ | ^
+note: ...due to this, which is why a type is expected after
+ --> $DIR/E0423.rs:12:37
+ |
+LL | if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
+ | ^
+ = help: this might be indicative of a syntax error elsewhere
error: expected expression, found `==`
--> $DIR/E0423.rs:15:13
|
LL | for _ in std::ops::Range { start: 0, end: 10 } {}
| ^ expecting a type here because of type ascription
+ |
+ = note: type ascription is a nightly only feature that lets you annotate expressions with a type: `<expr>: <type>`
+note: this expression is annotated with type ascription...
+ --> $DIR/E0423.rs:21:32
+ |
+LL | for _ in std::ops::Range { start: 0, end: 10 } {}
+ | ^^^^^
+note: ...due to this, which is why a type is expected after
+ --> $DIR/E0423.rs:21:37
+ |
+LL | for _ in std::ops::Range { start: 0, end: 10 } {}
+ | ^
+ = help: this might be indicative of a syntax error elsewhere
error[E0423]: expected function, found struct `Foo`
--> $DIR/E0423.rs:4:13
|
LL | println!("{}", a: &mut 4);
| ^ expecting a type here because of type ascription
+ |
+ = note: type ascription is a nightly only feature that lets you annotate expressions with a type: `<expr>: <type>`
+note: this expression is annotated with type ascription...
+ --> $DIR/issue-22644.rs:34:20
+ |
+LL | println!("{}", a: &mut 4);
+ | ^
+note: ...due to this, which is why a type is expected after
+ --> $DIR/issue-22644.rs:34:21
+ |
+LL | println!("{}", a: &mut 4);
+ | ^
+ = help: this might be indicative of a syntax error elsewhere
error: aborting due to 9 previous errors
--- /dev/null
+enum Test {
+ Drill {
+ field: i32,
+ }
+}
+
+fn main() {
+ Test::Drill(field: 42);
+ //~^ ERROR expected type, found
+}
--- /dev/null
+error: expected type, found `42`
+ --> $DIR/issue-34255-1.rs:8:24
+ |
+LL | Test::Drill(field: 42);
+ | ^^ expecting a type here because of type ascription
+ |
+ = note: type ascription is a nightly only feature that lets you annotate expressions with a type: `<expr>: <type>`
+note: this expression is annotated with type ascription...
+ --> $DIR/issue-34255-1.rs:8:17
+ |
+LL | Test::Drill(field: 42);
+ | ^^^^^
+note: ...due to this, which is why a type is expected after
+ --> $DIR/issue-34255-1.rs:8:22
+ |
+LL | Test::Drill(field: 42);
+ | ^
+ = help: this might be indicative of a syntax error elsewhere
+
+error: aborting due to previous error
+
|
LL | loop { break 'label: loop { break 'label 42; }; }
| ^^^^ expecting a type here because of type ascription
+ |
+ = note: type ascription is a nightly only feature that lets you annotate expressions with a type: `<expr>: <type>`
+note: this expression is annotated with type ascription...
+ --> $DIR/lifetime_starts_expressions.rs:6:12
+ |
+LL | loop { break 'label: loop { break 'label 42; }; }
+ | ^^^^^^^^^^^^
+note: ...due to this, which is why a type is expected after
+ --> $DIR/lifetime_starts_expressions.rs:6:24
+ |
+LL | loop { break 'label: loop { break 'label 42; }; }
+ | ^
+ = help: this might be indicative of a syntax error elsewhere
error: aborting due to 2 previous errors
|
LL | x: 3
| ^ expecting a type here because of type ascription
+ |
+ = note: type ascription is a nightly only feature that lets you annotate expressions with a type: `<expr>: <type>`
+note: this expression is annotated with type ascription...
+ --> $DIR/struct-literal-in-for.rs:13:9
+ |
+LL | x: 3
+ | ^
+note: ...due to this, which is why a type is expected after
+ --> $DIR/struct-literal-in-for.rs:13:10
+ |
+LL | x: 3
+ | ^
+ = help: this might be indicative of a syntax error elsewhere
error: expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
--> $DIR/struct-literal-in-for.rs:14:12
|
LL | x: 3
| ^ expecting a type here because of type ascription
+ |
+ = note: type ascription is a nightly only feature that lets you annotate expressions with a type: `<expr>: <type>`
+note: this expression is annotated with type ascription...
+ --> $DIR/struct-literal-in-if.rs:13:9
+ |
+LL | x: 3
+ | ^
+note: ...due to this, which is why a type is expected after
+ --> $DIR/struct-literal-in-if.rs:13:10
+ |
+LL | x: 3
+ | ^
+ = help: this might be indicative of a syntax error elsewhere
error: expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
--> $DIR/struct-literal-in-if.rs:14:12
|
LL | x: 3
| ^ expecting a type here because of type ascription
+ |
+ = note: type ascription is a nightly only feature that lets you annotate expressions with a type: `<expr>: <type>`
+note: this expression is annotated with type ascription...
+ --> $DIR/struct-literal-in-while.rs:13:9
+ |
+LL | x: 3
+ | ^
+note: ...due to this, which is why a type is expected after
+ --> $DIR/struct-literal-in-while.rs:13:10
+ |
+LL | x: 3
+ | ^
+ = help: this might be indicative of a syntax error elsewhere
error: expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
--> $DIR/struct-literal-in-while.rs:14:12
|
LL | x: 3
| ^ expecting a type here because of type ascription
+ |
+ = note: type ascription is a nightly only feature that lets you annotate expressions with a type: `<expr>: <type>`
+note: this expression is annotated with type ascription...
+ --> $DIR/struct-literal-restrictions-in-lamda.rs:13:9
+ |
+LL | x: 3
+ | ^
+note: ...due to this, which is why a type is expected after
+ --> $DIR/struct-literal-restrictions-in-lamda.rs:13:10
+ |
+LL | x: 3
+ | ^
+ = help: this might be indicative of a syntax error elsewhere
error: expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
--> $DIR/struct-literal-restrictions-in-lamda.rs:14:12
--- /dev/null
+fn fun(x: i32) -> i32 { x }
+
+fn main() {
+ let closure_annotated = |value: i32| -> i32 {
+ temp: i32 = fun(5i32);
+ //~^ ERROR cannot find value `temp` in this scope
+ //~| ERROR type ascription is experimental
+ temp + value + 1
+ //~^ ERROR cannot find value `temp` in this scope
+ };
+}
--- /dev/null
+error[E0425]: cannot find value `temp` in this scope
+ --> $DIR/type-ascription-instead-of-let.rs:5:9
+ |
+LL | temp: i32 = fun(5i32);
+ | ^^^^
+ | |
+ | not found in this scope
+ | expecting a type here because of type ascription
+ | help: maybe you meant to write an assignment here: `let temp`
+
+error[E0425]: cannot find value `temp` in this scope
+ --> $DIR/type-ascription-instead-of-let.rs:8:9
+ |
+LL | temp + value + 1
+ | ^^^^ not found in this scope
+
+error[E0658]: type ascription is experimental (see issue #23416)
+ --> $DIR/type-ascription-instead-of-let.rs:5:9
+ |
+LL | temp: i32 = fun(5i32);
+ | ^^^^^^^^^
+ |
+ = help: add #![feature(type_ascription)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0425, E0658.
+For more information about an error, try `rustc --explain E0425`.
--- /dev/null
+fn main() {
+ Box:new("foo".to_string())
+ //~^ ERROR expected type, found
+}
--- /dev/null
+error: expected type, found `"foo"`
+ --> $DIR/type-ascription-instead-of-method.rs:2:13
+ |
+LL | Box:new("foo".to_string())
+ | - ^^^^^ expecting a type here because of type ascription
+ | |
+ | help: maybe you meant to write a path separator here: `::`
+
+error: aborting due to previous error
+
--- /dev/null
+fn main() {
+ std:io::stdin();
+ //~^ ERROR failed to resolve: use of undeclared type or module `io`
+ //~| ERROR expected value, found module
+ //~| ERROR type ascription is experimental
+}
--- /dev/null
+error[E0433]: failed to resolve: use of undeclared type or module `io`
+ --> $DIR/type-ascription-instead-of-path.rs:2:9
+ |
+LL | std:io::stdin();
+ | ^^ use of undeclared type or module `io`
+
+error[E0423]: expected value, found module `std`
+ --> $DIR/type-ascription-instead-of-path.rs:2:5
+ |
+LL | std:io::stdin();
+ | ^^^
+ | |
+ | not a value
+ | expecting a type here because of type ascription
+help: maybe you meant to write a path separator here
+ |
+LL | std::io::stdin();
+ | ^^
+help: maybe you meant to write an assignment here
+ |
+LL | let std:io::stdin();
+ | ^^^^^^^
+
+error[E0658]: type ascription is experimental (see issue #23416)
+ --> $DIR/type-ascription-instead-of-path.rs:2:5
+ |
+LL | std:io::stdin();
+ | ^^^^^^^^^^^^^^^
+ |
+ = help: add #![feature(type_ascription)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0423, E0433, E0658.
+For more information about an error, try `rustc --explain E0423`.
--- /dev/null
+fn main() {
+ let _ = Option:Some("");
+ //~^ ERROR expected type, found
+}
--- /dev/null
+error: expected type, found `""`
+ --> $DIR/type-ascription-instead-of-variant.rs:2:25
+ |
+LL | let _ = Option:Some("");
+ | - ^^ expecting a type here because of type ascription
+ | |
+ | help: maybe you meant to write a path separator here: `::`
+
+error: aborting due to previous error
+
|
LL | println!("test"): 0;
| ^ expecting a type here because of type ascription
+ |
+ = note: type ascription is a nightly only feature that lets you annotate expressions with a type: `<expr>: <type>`
+note: this expression is annotated with type ascription...
+ --> $DIR/type-ascription-instead-of-statement-end.rs:9:5
+ |
+LL | println!("test"): 0;
+ | ^^^^^^^^^^^^^^^^
+note: ...due to this, which is why a type is expected after
+ --> $DIR/type-ascription-instead-of-statement-end.rs:9:21
+ |
+LL | println!("test"): 0;
+ | ^
+ = help: this might be indicative of a syntax error elsewhere
error: aborting due to 2 previous errors