Skip to content

Commit e39bcec

Browse files
committed
Handle type ascription cases with a method call instead of a type
1 parent faf9035 commit e39bcec

File tree

3 files changed

+94
-14
lines changed

3 files changed

+94
-14
lines changed

src/librustc_resolve/lib.rs

+63-14
Original file line numberDiff line numberDiff line change
@@ -599,19 +599,24 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
599599
self.resolve_local(local);
600600
}
601601
fn visit_ty(&mut self, ty: &'tcx Ty) {
602-
if let TyKind::Path(ref qself, ref path) = ty.node {
603-
self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type);
604-
} else if let TyKind::ImplicitSelf = ty.node {
605-
let self_ty = keywords::SelfType.ident();
606-
let def = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, true, ty.span)
607-
.map_or(Def::Err, |d| d.def());
608-
self.record_def(ty.id, PathResolution::new(def));
609-
} else if let TyKind::Array(ref element, ref length) = ty.node {
610-
self.visit_ty(element);
611-
self.with_constant_rib(|this| {
612-
this.visit_expr(length);
613-
});
614-
return;
602+
match ty.node {
603+
TyKind::Path(ref qself, ref path) => {
604+
self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type);
605+
}
606+
TyKind::ImplicitSelf => {
607+
let self_ty = keywords::SelfType.ident();
608+
let def = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, true, ty.span)
609+
.map_or(Def::Err, |d| d.def());
610+
self.record_def(ty.id, PathResolution::new(def));
611+
}
612+
TyKind::Array(ref element, ref length) => {
613+
self.visit_ty(element);
614+
self.with_constant_rib(|this| {
615+
this.visit_expr(length);
616+
});
617+
return;
618+
}
619+
_ => (),
615620
}
616621
visit::walk_ty(self, ty);
617622
}
@@ -1221,6 +1226,9 @@ pub struct Resolver<'a> {
12211226
// This table maps struct IDs into struct constructor IDs,
12221227
// it's not used during normal resolution, only for better error reporting.
12231228
struct_constructors: DefIdMap<(Def, ty::Visibility)>,
1229+
1230+
// Only used for better errors on `fn(): fn()`
1231+
current_type_ascription: Vec<Span>,
12241232
}
12251233

12261234
pub struct ResolverArenas<'a> {
@@ -1411,6 +1419,7 @@ impl<'a> Resolver<'a> {
14111419
struct_constructors: DefIdMap(),
14121420
found_unresolved_macro: false,
14131421
unused_macros: FxHashSet(),
1422+
current_type_ascription: Vec::new(),
14141423
}
14151424
}
14161425

@@ -2495,6 +2504,7 @@ impl<'a> Resolver<'a> {
24952504
// Fallback label.
24962505
if !levenshtein_worked {
24972506
err.span_label(base_span, fallback_label);
2507+
this.type_ascription_suggestion(&mut err, base_span);
24982508
}
24992509
err
25002510
};
@@ -2550,6 +2560,41 @@ impl<'a> Resolver<'a> {
25502560
resolution
25512561
}
25522562

2563+
fn type_ascription_suggestion(&self,
2564+
err: &mut DiagnosticBuilder,
2565+
base_span: Span) {
2566+
debug!("type_ascription_suggetion {:?}", base_span);
2567+
let cm = self.session.codemap();
2568+
debug!("self.current_type_ascription {:?}", self.current_type_ascription);
2569+
if let Some(sp) = self.current_type_ascription.last() {
2570+
let mut sp = *sp;
2571+
loop { // try to find the `:`, bail on first non-':'/non-whitespace
2572+
sp = sp.next_point();
2573+
if let Ok(snippet) = cm.span_to_snippet(sp.to(sp.next_point())) {
2574+
debug!("snippet {:?}", snippet);
2575+
let line_sp = cm.lookup_char_pos(sp.hi).line;
2576+
let line_base_sp = cm.lookup_char_pos(base_span.lo).line;
2577+
debug!("{:?} {:?}", line_sp, line_base_sp);
2578+
if snippet == ":" {
2579+
err.span_label(base_span,
2580+
"expecting a type here because of type ascription");
2581+
if line_sp != line_base_sp {
2582+
err.span_suggestion_short(sp,
2583+
"did you mean to use `;` here instead?",
2584+
";".to_string());
2585+
}
2586+
break;
2587+
} else if snippet.trim().len() != 0 {
2588+
debug!("tried to find type ascription `:` token, couldn't find it");
2589+
break;
2590+
}
2591+
} else {
2592+
break;
2593+
}
2594+
}
2595+
}
2596+
}
2597+
25532598
fn self_type_is_available(&mut self, span: Span) -> bool {
25542599
let binding = self.resolve_ident_in_lexical_scope(keywords::SelfType.ident(),
25552600
TypeNS, false, span);
@@ -3166,7 +3211,11 @@ impl<'a> Resolver<'a> {
31663211
self.resolve_expr(argument, None);
31673212
}
31683213
}
3169-
3214+
ExprKind::Type(ref type_expr, _) => {
3215+
self.current_type_ascription.push(type_expr.span);
3216+
visit::walk_expr(self, expr);
3217+
self.current_type_ascription.pop();
3218+
}
31703219
_ => {
31713220
visit::walk_expr(self, expr);
31723221
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(type_ascription)]
12+
13+
fn main() {
14+
f() :
15+
f();
16+
}
17+
18+
fn f() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0573]: expected type, found function `f`
2+
--> $DIR/type-ascription-with-fn-call.rs:15:5
3+
|
4+
14 | f() :
5+
| - help: did you mean to use `;` here instead?
6+
15 | f();
7+
| ^^^
8+
| |
9+
| not a type
10+
| expecting a type here because of type ascription
11+
12+
error: aborting due to previous error
13+

0 commit comments

Comments
 (0)