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:
commit
7c7941dc26
7 changed files with 70 additions and 11 deletions
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
25
src/test/ui/span/method-and-field-eager-resolution.rs
Normal file
25
src/test/ui/span/method-and-field-eager-resolution.rs
Normal 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;
|
||||
}
|
||||
23
src/test/ui/span/method-and-field-eager-resolution.stderr
Normal file
23
src/test/ui/span/method-and-field-eager-resolution.stderr
Normal 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`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue