Rollup merge of #50712 - leodasvacas:improve-eager-resolution-error-message, r=estebank

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 where in the past we 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
This commit is contained in:
Guillaume Gomez 2018-05-15 14:27:02 +02:00 committed by GitHub
commit 7c7941dc26
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 70 additions and 11 deletions

View file

@ -14,6 +14,7 @@ use infer::InferCtxt;
use infer::type_variable::TypeVariableOrigin;
use ty::{self, Ty, TyInfer, TyVar};
use syntax_pos::Span;
use errors::DiagnosticBuilder;
struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
@ -86,7 +87,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}
}
pub fn need_type_info(&self, body_id: Option<hir::BodyId>, span: Span, ty: Ty<'tcx>) {
pub fn need_type_info_err(&self,
body_id: Option<hir::BodyId>,
span: Span,
ty: Ty<'tcx>)
-> DiagnosticBuilder<'gcx> {
let ty = self.resolve_type_vars_if_possible(&ty);
let name = self.extract_type_name(&ty);
@ -142,6 +147,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
err.span_label(target_span, label_message);
}
err.emit();
err
}
}

View file

@ -1234,7 +1234,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
self.tcx.lang_items().sized_trait()
.map_or(false, |sized_id| sized_id == trait_ref.def_id())
{
self.need_type_info(body_id, span, self_ty);
self.need_type_info_err(body_id, span, self_ty).emit();
} else {
let mut err = struct_span_err!(self.tcx.sess,
span, E0283,
@ -1251,7 +1251,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
// Same hacky approach as above to avoid deluging user
// with error messages.
if !ty.references_error() && !self.tcx.sess.has_errors() {
self.need_type_info(body_id, span, ty);
self.need_type_info_err(body_id, span, ty).emit();
}
}
@ -1262,9 +1262,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
// both must be type variables, or the other would've been instantiated
assert!(a.is_ty_var() && b.is_ty_var());
self.need_type_info(body_id,
obligation.cause.span,
a);
self.need_type_info_err(body_id,
obligation.cause.span,
a).emit();
}
}

View file

@ -3067,7 +3067,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
base: &'gcx hir::Expr,
field: &Spanned<ast::Name>) -> Ty<'tcx> {
let expr_t = self.check_expr_with_needs(base, needs);
let expr_t = self.structurally_resolved_type(expr.span,
let expr_t = self.structurally_resolved_type(base.span,
expr_t);
let mut private_candidate = None;
let mut autoderef = self.autoderef(expr.span, expr_t);
@ -4088,7 +4088,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} else if idx_t.references_error() {
idx_t
} else {
let base_t = self.structurally_resolved_type(expr.span, base_t);
let base_t = self.structurally_resolved_type(base.span, base_t);
match self.lookup_indexing(expr, base, base_t, idx_t, needs) {
Some((index_ty, element_ty)) => {
// two-phase not needed because index_ty is never mutable
@ -5061,7 +5061,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
ty
} else {
if !self.is_tainted_by_errors() {
self.need_type_info((**self).body_id, sp, ty);
self.need_type_info_err((**self).body_id, sp, ty)
.note("type must be known at this point")
.emit();
}
self.demand_suptype(sp, self.tcx.types.err, ty);
self.tcx.types.err

View file

@ -593,7 +593,7 @@ impl<'cx, 'gcx, 'tcx> Resolver<'cx, 'gcx, 'tcx> {
fn report_error(&self, t: Ty<'tcx>) {
if !self.tcx.sess.has_errors() {
self.infcx
.need_type_info(Some(self.body.id()), self.span.to_span(&self.tcx), t);
.need_type_info_err(Some(self.body.id()), self.span.to_span(&self.tcx), t).emit();
}
}
}

View file

@ -5,6 +5,8 @@ LL | let x: Option<_> = None;
| - consider giving `x` a type
LL | x.unwrap().method_that_could_exist_on_some_type();
| ^^^^^^^^^^ cannot infer type for `T`
|
= note: type must be known at this point
error[E0282]: type annotations needed
--> $DIR/issue-42234-unknown-receiver-type.rs:22:5
@ -12,6 +14,8 @@ error[E0282]: type annotations needed
LL | / data.iter() //~ ERROR 22:5: 23:20: type annotations needed
LL | | .sum::<_>()
| |___________________^ cannot infer type for `_`
|
= note: type must be known at this point
error: aborting due to 2 previous errors

View file

@ -0,0 +1,25 @@
// Copyright 2018 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.
// Test that spans get only base in eager type resolution (structurally_resolve_type).
fn main() {
let mut x = Default::default();
x.0;
//~^ ERROR type annotations needed
x = 1;
}
fn foo() {
let mut x = Default::default();
x[0];
//~^ ERROR type annotations needed
x = 1;
}

View file

@ -0,0 +1,23 @@
error[E0282]: type annotations needed
--> $DIR/method-and-field-eager-resolution.rs:15:5
|
LL | let mut x = Default::default();
| ----- consider giving `x` a type
LL | x.0;
| ^ cannot infer type for `_`
|
= note: type must be known at this point
error[E0282]: type annotations needed
--> $DIR/method-and-field-eager-resolution.rs:22:5
|
LL | let mut x = Default::default();
| ----- consider giving `x` a type
LL | x[0];
| ^ cannot infer type for `_`
|
= note: type must be known at this point
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0282`.