Auto merge of #38057 - KiChjang:display-formal-type-param, r=nikomatsakis
Display better error messages for E0282 Fixes #36554.
This commit is contained in:
commit
5e2f37fca9
28 changed files with 191 additions and 76 deletions
|
|
@ -13,6 +13,7 @@ use super::InferCtxt;
|
|||
use super::lattice::{self, LatticeDir};
|
||||
use super::Subtype;
|
||||
|
||||
use traits::ObligationCause;
|
||||
use ty::{self, Ty, TyCtxt};
|
||||
use ty::relate::{Relate, RelateResult, TypeRelation};
|
||||
|
||||
|
|
@ -83,6 +84,10 @@ impl<'combine, 'infcx, 'gcx, 'tcx> LatticeDir<'infcx, 'gcx, 'tcx>
|
|||
self.fields.infcx
|
||||
}
|
||||
|
||||
fn cause(&self) -> &ObligationCause<'tcx> {
|
||||
&self.fields.trace.cause
|
||||
}
|
||||
|
||||
fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
|
||||
let mut sub = self.fields.sub(self.a_is_expected);
|
||||
sub.relate(&v, &a)?;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,9 @@
|
|||
//! a lattice.
|
||||
|
||||
use super::InferCtxt;
|
||||
use super::type_variable::TypeVariableOrigin;
|
||||
|
||||
use traits::ObligationCause;
|
||||
use ty::TyVar;
|
||||
use ty::{self, Ty};
|
||||
use ty::relate::{RelateResult, TypeRelation};
|
||||
|
|
@ -38,6 +40,8 @@ use ty::relate::{RelateResult, TypeRelation};
|
|||
pub trait LatticeDir<'f, 'gcx: 'f+'tcx, 'tcx: 'f> : TypeRelation<'f, 'gcx, 'tcx> {
|
||||
fn infcx(&self) -> &'f InferCtxt<'f, 'gcx, 'tcx>;
|
||||
|
||||
fn cause(&self) -> &ObligationCause<'tcx>;
|
||||
|
||||
// Relates the type `v` to `a` and `b` such that `v` represents
|
||||
// the LUB/GLB of `a` and `b` as appropriate.
|
||||
fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()>;
|
||||
|
|
@ -64,14 +68,15 @@ pub fn super_lattice_tys<'a, 'gcx, 'tcx, L>(this: &mut L,
|
|||
match (&a.sty, &b.sty) {
|
||||
(&ty::TyInfer(TyVar(..)), &ty::TyInfer(TyVar(..)))
|
||||
if infcx.type_var_diverges(a) && infcx.type_var_diverges(b) => {
|
||||
let v = infcx.next_diverging_ty_var();
|
||||
let v = infcx.next_diverging_ty_var(
|
||||
TypeVariableOrigin::LatticeVariable(this.cause().span));
|
||||
this.relate_bound(v, a, b)?;
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
(&ty::TyInfer(TyVar(..)), _) |
|
||||
(_, &ty::TyInfer(TyVar(..))) => {
|
||||
let v = infcx.next_ty_var();
|
||||
let v = infcx.next_ty_var(TypeVariableOrigin::LatticeVariable(this.cause().span));
|
||||
this.relate_bound(v, a, b)?;
|
||||
Ok(v)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ use super::InferCtxt;
|
|||
use super::lattice::{self, LatticeDir};
|
||||
use super::Subtype;
|
||||
|
||||
use traits::ObligationCause;
|
||||
use ty::{self, Ty, TyCtxt};
|
||||
use ty::relate::{Relate, RelateResult, TypeRelation};
|
||||
|
||||
|
|
@ -83,6 +84,10 @@ impl<'combine, 'infcx, 'gcx, 'tcx> LatticeDir<'infcx, 'gcx, 'tcx>
|
|||
self.fields.infcx
|
||||
}
|
||||
|
||||
fn cause(&self) -> &ObligationCause<'tcx> {
|
||||
&self.fields.trace.cause
|
||||
}
|
||||
|
||||
fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
|
||||
let mut sub = self.fields.sub(self.a_is_expected);
|
||||
sub.relate(&a, &v)?;
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ use util::nodemap::{FxHashMap, FxHashSet, NodeMap};
|
|||
use self::combine::CombineFields;
|
||||
use self::higher_ranked::HrMatchResult;
|
||||
use self::region_inference::{RegionVarBindings, RegionSnapshot};
|
||||
use self::type_variable::TypeVariableOrigin;
|
||||
use self::unify_key::ToType;
|
||||
|
||||
mod bivariate;
|
||||
|
|
@ -114,7 +115,7 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
|||
// We instantiate UnificationTable with bounds<Ty> because the
|
||||
// types that might instantiate a general type variable have an
|
||||
// order, represented by its upper and lower bounds.
|
||||
type_variables: RefCell<type_variable::TypeVariableTable<'tcx>>,
|
||||
pub type_variables: RefCell<type_variable::TypeVariableTable<'tcx>>,
|
||||
|
||||
// Map from integral variable to the kind of integer it represents
|
||||
int_unification_table: RefCell<UnificationTable<ty::IntVid>>,
|
||||
|
|
@ -1054,18 +1055,18 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn next_ty_var_id(&self, diverging: bool) -> TyVid {
|
||||
pub fn next_ty_var_id(&self, diverging: bool, origin: TypeVariableOrigin) -> TyVid {
|
||||
self.type_variables
|
||||
.borrow_mut()
|
||||
.new_var(diverging, None)
|
||||
.new_var(diverging, origin, None)
|
||||
}
|
||||
|
||||
pub fn next_ty_var(&self) -> Ty<'tcx> {
|
||||
self.tcx.mk_var(self.next_ty_var_id(false))
|
||||
pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
|
||||
self.tcx.mk_var(self.next_ty_var_id(false, origin))
|
||||
}
|
||||
|
||||
pub fn next_diverging_ty_var(&self) -> Ty<'tcx> {
|
||||
self.tcx.mk_var(self.next_ty_var_id(true))
|
||||
pub fn next_diverging_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
|
||||
self.tcx.mk_var(self.next_ty_var_id(true, origin))
|
||||
}
|
||||
|
||||
pub fn next_int_var_id(&self) -> IntVid {
|
||||
|
|
@ -1118,7 +1119,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
let ty_var_id = self.type_variables
|
||||
.borrow_mut()
|
||||
.new_var(false, default);
|
||||
.new_var(false,
|
||||
TypeVariableOrigin::TypeParameterDefinition(span, def.name),
|
||||
default);
|
||||
|
||||
self.tcx.mk_var(ty_var_id)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ use self::TypeVariableValue::*;
|
|||
use self::UndoEntry::*;
|
||||
use hir::def_id::{DefId};
|
||||
use syntax::util::small_vector::SmallVector;
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
use ty::{self, Ty};
|
||||
|
||||
|
|
@ -28,8 +29,24 @@ pub struct TypeVariableTable<'tcx> {
|
|||
eq_relations: ut::UnificationTable<ty::TyVid>,
|
||||
}
|
||||
|
||||
/// Reasons to create a type inference variable
|
||||
pub enum TypeVariableOrigin {
|
||||
MiscVariable(Span),
|
||||
NormalizeProjectionType(Span),
|
||||
TypeInference(Span),
|
||||
TypeParameterDefinition(Span, ast::Name),
|
||||
TransformedUpvar(Span),
|
||||
SubstitutionPlaceholder(Span),
|
||||
AutoDeref(Span),
|
||||
AdjustmentType(Span),
|
||||
DivergingStmt(Span),
|
||||
DivergingBlockExpr(Span),
|
||||
LatticeVariable(Span),
|
||||
}
|
||||
|
||||
struct TypeVariableData<'tcx> {
|
||||
value: TypeVariableValue<'tcx>,
|
||||
origin: TypeVariableOrigin,
|
||||
diverging: bool
|
||||
}
|
||||
|
||||
|
|
@ -107,6 +124,10 @@ impl<'tcx> TypeVariableTable<'tcx> {
|
|||
self.values.get(vid.index as usize).diverging
|
||||
}
|
||||
|
||||
pub fn var_origin(&self, vid: ty::TyVid) -> &TypeVariableOrigin {
|
||||
&self.values.get(vid.index as usize).origin
|
||||
}
|
||||
|
||||
/// Records that `a <: b`, `a :> b`, or `a == b`, depending on `dir`.
|
||||
///
|
||||
/// Precondition: neither `a` nor `b` are known.
|
||||
|
|
@ -173,10 +194,12 @@ impl<'tcx> TypeVariableTable<'tcx> {
|
|||
|
||||
pub fn new_var(&mut self,
|
||||
diverging: bool,
|
||||
default: Option<Default<'tcx>>) -> ty::TyVid {
|
||||
origin: TypeVariableOrigin,
|
||||
default: Option<Default<'tcx>>,) -> ty::TyVid {
|
||||
self.eq_relations.new_key(());
|
||||
let index = self.values.push(TypeVariableData {
|
||||
value: Bounded { relations: vec![], default: default },
|
||||
origin: origin,
|
||||
diverging: diverging
|
||||
});
|
||||
let v = ty::TyVid { index: index as u32 };
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ use super::{
|
|||
use fmt_macros::{Parser, Piece, Position};
|
||||
use hir::def_id::DefId;
|
||||
use infer::{self, InferCtxt};
|
||||
use infer::type_variable::TypeVariableOrigin;
|
||||
use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL;
|
||||
use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
|
||||
use ty::error::ExpectedFound;
|
||||
|
|
@ -38,7 +39,7 @@ use util::nodemap::{FxHashMap, FxHashSet};
|
|||
use std::cmp;
|
||||
use std::fmt;
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
use syntax_pos::{DUMMY_SP, Span};
|
||||
use errors::DiagnosticBuilder;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||
|
|
@ -790,9 +791,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.infcx.tcx }
|
||||
|
||||
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
if let ty::TyParam(..) = ty.sty {
|
||||
if let ty::TyParam(ty::ParamTy {name, ..}) = ty.sty {
|
||||
let infcx = self.infcx;
|
||||
self.var_map.entry(ty).or_insert_with(|| infcx.next_ty_var())
|
||||
self.var_map.entry(ty).or_insert_with(||
|
||||
infcx.next_ty_var(
|
||||
TypeVariableOrigin::TypeParameterDefinition(DUMMY_SP, name)))
|
||||
} else {
|
||||
ty.super_fold_with(self)
|
||||
}
|
||||
|
|
@ -824,12 +827,26 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
|
||||
fn need_type_info(&self, span: Span, ty: Ty<'tcx>) {
|
||||
let ty = self.resolve_type_vars_if_possible(&ty);
|
||||
let name = if let ty::TyInfer(ty::TyVar(ty_vid)) = ty.sty {
|
||||
let ty_vars = self.type_variables.borrow();
|
||||
if let TypeVariableOrigin::TypeParameterDefinition(_, name) =
|
||||
*ty_vars.var_origin(ty_vid)
|
||||
{
|
||||
name.to_string()
|
||||
} else {
|
||||
ty.to_string()
|
||||
}
|
||||
} else {
|
||||
ty.to_string()
|
||||
};
|
||||
|
||||
let mut err = struct_span_err!(self.tcx.sess, span, E0282,
|
||||
"unable to infer enough type information about `{}`",
|
||||
ty);
|
||||
name);
|
||||
err.note("type annotations or generic parameter binding required");
|
||||
err.span_label(span, &format!("cannot infer type for `{}`", ty));
|
||||
err.emit()
|
||||
err.span_label(span, &format!("cannot infer type for `{}`", name));
|
||||
err.emit();
|
||||
}
|
||||
|
||||
fn note_obligation_cause<T>(&self,
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ use super::util;
|
|||
|
||||
use hir::def_id::DefId;
|
||||
use infer::InferOk;
|
||||
use infer::type_variable::TypeVariableOrigin;
|
||||
use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap};
|
||||
use syntax::ast;
|
||||
use syntax::symbol::Symbol;
|
||||
|
|
@ -382,7 +383,12 @@ pub fn normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
|
|||
// and a deferred predicate to resolve this when more type
|
||||
// information is available.
|
||||
|
||||
let ty_var = selcx.infcx().next_ty_var();
|
||||
let tcx = selcx.infcx().tcx;
|
||||
let def_id = tcx.associated_items(projection_ty.trait_ref.def_id).find(|i|
|
||||
i.name == projection_ty.item_name && i.kind == ty::AssociatedKind::Type
|
||||
).map(|i| i.def_id).unwrap();
|
||||
let ty_var = selcx.infcx().next_ty_var(
|
||||
TypeVariableOrigin::NormalizeProjectionType(tcx.def_span(def_id)));
|
||||
let projection = ty::Binder(ty::ProjectionPredicate {
|
||||
projection_ty: projection_ty,
|
||||
ty: ty_var
|
||||
|
|
@ -596,7 +602,12 @@ fn normalize_to_error<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a, 'gcx, 'tc
|
|||
let trait_obligation = Obligation { cause: cause,
|
||||
recursion_depth: depth,
|
||||
predicate: trait_ref.to_predicate() };
|
||||
let new_value = selcx.infcx().next_ty_var();
|
||||
let tcx = selcx.infcx().tcx;
|
||||
let def_id = tcx.associated_items(projection_ty.trait_ref.def_id).find(|i|
|
||||
i.name == projection_ty.item_name && i.kind == ty::AssociatedKind::Type
|
||||
).map(|i| i.def_id).unwrap();
|
||||
let new_value = selcx.infcx().next_ty_var(
|
||||
TypeVariableOrigin::NormalizeProjectionType(tcx.def_span(def_id)));
|
||||
Normalized {
|
||||
value: new_value,
|
||||
obligations: vec![trait_obligation]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue