Skip to content

Commit 8789056

Browse files
committedMay 13, 2018
Improve eager type resolution error message
This PR improves the span of eager resolution type errors referring to indexing and field access to use the base span rather than the whole expression. Also a note "Type must be known at this point." is added to where we at some point in the past emitted the "type must be known at this context" error, so that early failures can be differentiated and will hopefully be less surprising. Fixes #50692 (or at least does the best we can for the moment) r? @estebank
1 parent e6db79f commit 8789056

File tree

7 files changed

+70
-11
lines changed

7 files changed

+70
-11
lines changed
 

‎src/librustc/infer/error_reporting/need_type_info.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use infer::InferCtxt;
1414
use infer::type_variable::TypeVariableOrigin;
1515
use ty::{self, Ty, TyInfer, TyVar};
1616
use syntax_pos::Span;
17+
use errors::DiagnosticBuilder;
1718

1819
struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
1920
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
@@ -86,7 +87,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
8687
}
8788
}
8889

89-
pub fn need_type_info(&self, body_id: Option<hir::BodyId>, span: Span, ty: Ty<'tcx>) {
90+
pub fn need_type_info_err(&self,
91+
body_id: Option<hir::BodyId>,
92+
span: Span,
93+
ty: Ty<'tcx>)
94+
-> DiagnosticBuilder<'gcx> {
9095
let ty = self.resolve_type_vars_if_possible(&ty);
9196
let name = self.extract_type_name(&ty);
9297

@@ -142,6 +147,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
142147
err.span_label(target_span, label_message);
143148
}
144149

145-
err.emit();
150+
err
146151
}
147152
}

‎src/librustc/traits/error_reporting.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1234,7 +1234,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
12341234
self.tcx.lang_items().sized_trait()
12351235
.map_or(false, |sized_id| sized_id == trait_ref.def_id())
12361236
{
1237-
self.need_type_info(body_id, span, self_ty);
1237+
self.need_type_info_err(body_id, span, self_ty).emit();
12381238
} else {
12391239
let mut err = struct_span_err!(self.tcx.sess,
12401240
span, E0283,
@@ -1251,7 +1251,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
12511251
// Same hacky approach as above to avoid deluging user
12521252
// with error messages.
12531253
if !ty.references_error() && !self.tcx.sess.has_errors() {
1254-
self.need_type_info(body_id, span, ty);
1254+
self.need_type_info_err(body_id, span, ty).emit();
12551255
}
12561256
}
12571257

@@ -1262,9 +1262,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
12621262
let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
12631263
// both must be type variables, or the other would've been instantiated
12641264
assert!(a.is_ty_var() && b.is_ty_var());
1265-
self.need_type_info(body_id,
1266-
obligation.cause.span,
1267-
a);
1265+
self.need_type_info_err(body_id,
1266+
obligation.cause.span,
1267+
a).emit();
12681268
}
12691269
}
12701270

‎src/librustc_typeck/check/mod.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -3067,7 +3067,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
30673067
base: &'gcx hir::Expr,
30683068
field: &Spanned<ast::Name>) -> Ty<'tcx> {
30693069
let expr_t = self.check_expr_with_needs(base, needs);
3070-
let expr_t = self.structurally_resolved_type(expr.span,
3070+
let expr_t = self.structurally_resolved_type(base.span,
30713071
expr_t);
30723072
let mut private_candidate = None;
30733073
let mut autoderef = self.autoderef(expr.span, expr_t);
@@ -4080,7 +4080,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
40804080
} else if idx_t.references_error() {
40814081
idx_t
40824082
} else {
4083-
let base_t = self.structurally_resolved_type(expr.span, base_t);
4083+
let base_t = self.structurally_resolved_type(base.span, base_t);
40844084
match self.lookup_indexing(expr, base, base_t, idx_t, needs) {
40854085
Some((index_ty, element_ty)) => {
40864086
// two-phase not needed because index_ty is never mutable
@@ -5053,7 +5053,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
50535053
ty
50545054
} else {
50555055
if !self.is_tainted_by_errors() {
5056-
self.need_type_info((**self).body_id, sp, ty);
5056+
self.need_type_info_err((**self).body_id, sp, ty)
5057+
.note("type must be known at this point")
5058+
.emit();
50575059
}
50585060
self.demand_suptype(sp, self.tcx.types.err, ty);
50595061
self.tcx.types.err

‎src/librustc_typeck/check/writeback.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,7 @@ impl<'cx, 'gcx, 'tcx> Resolver<'cx, 'gcx, 'tcx> {
593593
fn report_error(&self, t: Ty<'tcx>) {
594594
if !self.tcx.sess.has_errors() {
595595
self.infcx
596-
.need_type_info(Some(self.body.id()), self.span.to_span(&self.tcx), t);
596+
.need_type_info_err(Some(self.body.id()), self.span.to_span(&self.tcx), t).emit();
597597
}
598598
}
599599
}

‎src/test/ui/span/issue-42234-unknown-receiver-type.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@ LL | let x: Option<_> = None;
55
| - consider giving `x` a type
66
LL | x.unwrap().method_that_could_exist_on_some_type();
77
| ^^^^^^^^^^ cannot infer type for `T`
8+
|
9+
= note: type must be known at this point
810

911
error[E0282]: type annotations needed
1012
--> $DIR/issue-42234-unknown-receiver-type.rs:22:5
1113
|
1214
LL | / data.iter() //~ ERROR 22:5: 23:20: type annotations needed
1315
LL | | .sum::<_>()
1416
| |___________________^ cannot infer type for `_`
17+
|
18+
= note: type must be known at this point
1519

1620
error: aborting due to 2 previous errors
1721

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2018 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+
// Test that spans get only base in eager type resolution (structurally_resolve_type).
12+
13+
fn main() {
14+
let mut x = Default::default();
15+
x.0;
16+
//~^ ERROR type annotations needed
17+
x = 1;
18+
}
19+
20+
fn foo() {
21+
let mut x = Default::default();
22+
x[0];
23+
//~^ ERROR type annotations needed
24+
x = 1;
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error[E0282]: type annotations needed
2+
--> $DIR/method-and-field-eager-resolution.rs:15:5
3+
|
4+
LL | let mut x = Default::default();
5+
| ----- consider giving `x` a type
6+
LL | x.0;
7+
| ^ cannot infer type for `_`
8+
|
9+
= note: type must be known at this point
10+
11+
error[E0282]: type annotations needed
12+
--> $DIR/method-and-field-eager-resolution.rs:22:5
13+
|
14+
LL | let mut x = Default::default();
15+
| ----- consider giving `x` a type
16+
LL | x[0];
17+
| ^ cannot infer type for `_`
18+
|
19+
= note: type must be known at this point
20+
21+
error: aborting due to 2 previous errors
22+
23+
For more information about this error, try `rustc --explain E0282`.

0 commit comments

Comments
 (0)
Please sign in to comment.