mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
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
@ -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]
|
||||
|
@ -24,6 +24,7 @@ use rustc::ty::subst::{Kind, Subst};
|
||||
use rustc::traits::{ObligationCause, Reveal};
|
||||
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc::infer::{self, InferOk, InferResult};
|
||||
use rustc::infer::type_variable::TypeVariableOrigin;
|
||||
use rustc_metadata::cstore::CStore;
|
||||
use rustc::hir::map as hir_map;
|
||||
use rustc::session::{self, config};
|
||||
@ -36,6 +37,7 @@ use errors::emitter::Emitter;
|
||||
use errors::{Level, DiagnosticBuilder};
|
||||
use syntax::feature_gate::UnstableFeatures;
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax_pos::DUMMY_SP;
|
||||
|
||||
use rustc::hir;
|
||||
|
||||
@ -489,7 +491,7 @@ fn sub_free_bound_false_infer() {
|
||||
//! does NOT hold for any instantiation of `_#1`.
|
||||
|
||||
test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
|
||||
let t_infer1 = env.infcx.next_ty_var();
|
||||
let t_infer1 = env.infcx.next_ty_var(TypeVariableOrigin::MiscVariable(DUMMY_SP));
|
||||
let t_rptr_bound1 = env.t_rptr_late_bound(1);
|
||||
env.check_not_sub(env.t_fn(&[t_infer1], env.tcx().types.isize),
|
||||
env.t_fn(&[t_rptr_bound1], env.tcx().types.isize));
|
||||
@ -508,7 +510,7 @@ fn lub_free_bound_infer() {
|
||||
|
||||
test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
|
||||
env.create_simple_region_hierarchy();
|
||||
let t_infer1 = env.infcx.next_ty_var();
|
||||
let t_infer1 = env.infcx.next_ty_var(TypeVariableOrigin::MiscVariable(DUMMY_SP));
|
||||
let t_rptr_bound1 = env.t_rptr_late_bound(1);
|
||||
let t_rptr_free1 = env.t_rptr_free(1, 1);
|
||||
env.check_lub(env.t_fn(&[t_infer1], env.tcx().types.isize),
|
||||
@ -628,7 +630,7 @@ fn glb_bound_free() {
|
||||
fn glb_bound_free_infer() {
|
||||
test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
|
||||
let t_rptr_bound1 = env.t_rptr_late_bound(1);
|
||||
let t_infer1 = env.infcx.next_ty_var();
|
||||
let t_infer1 = env.infcx.next_ty_var(TypeVariableOrigin::MiscVariable(DUMMY_SP));
|
||||
|
||||
// compute GLB(fn(_) -> isize, for<'b> fn(&'b isize) -> isize),
|
||||
// which should yield for<'b> fn(&'b isize) -> isize
|
||||
|
@ -12,6 +12,7 @@ use rustc::hir::{self, PatKind};
|
||||
use rustc::hir::def::{Def, CtorKind};
|
||||
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
|
||||
use rustc::infer;
|
||||
use rustc::infer::type_variable::TypeVariableOrigin;
|
||||
use rustc::traits::ObligationCauseCode;
|
||||
use rustc::ty::{self, Ty, TypeFoldable, LvaluePreference};
|
||||
use check::{FnCtxt, Expectation, Diverges};
|
||||
@ -162,7 +163,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
let max_len = cmp::max(expected_len, elements.len());
|
||||
|
||||
let element_tys_iter = (0..max_len).map(|_| self.next_ty_var());
|
||||
let element_tys_iter = (0..max_len).map(|_| self.next_ty_var(
|
||||
// FIXME: MiscVariable for now, obtaining the span and name information
|
||||
// from all tuple elements isn't trivial.
|
||||
TypeVariableOrigin::TypeInference(pat.span)));
|
||||
let element_tys = tcx.mk_type_list(element_tys_iter);
|
||||
let pat_ty = tcx.mk_ty(ty::TyTuple(element_tys));
|
||||
self.demand_eqtype(pat.span, expected, pat_ty);
|
||||
@ -172,7 +176,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
pat_ty
|
||||
}
|
||||
PatKind::Box(ref inner) => {
|
||||
let inner_ty = self.next_ty_var();
|
||||
let inner_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(inner.span));
|
||||
let uniq_ty = tcx.mk_box(inner_ty);
|
||||
|
||||
if self.check_dereferencable(pat.span, expected, &inner) {
|
||||
@ -203,7 +207,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
(expected, mt.ty)
|
||||
}
|
||||
_ => {
|
||||
let inner_ty = self.next_ty_var();
|
||||
let inner_ty = self.next_ty_var(
|
||||
TypeVariableOrigin::TypeInference(inner.span));
|
||||
let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
|
||||
let region = self.next_region_var(infer::PatternRegion(pat.span));
|
||||
let rptr_ty = tcx.mk_ref(region, mt);
|
||||
@ -379,7 +384,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
// ...but otherwise we want to use any supertype of the
|
||||
// discriminant. This is sort of a workaround, see note (*) in
|
||||
// `check_pat` for some details.
|
||||
discrim_ty = self.next_ty_var();
|
||||
discrim_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(discrim.span));
|
||||
self.check_expr_has_type(discrim, discrim_ty);
|
||||
};
|
||||
let discrim_diverges = self.diverges.get();
|
||||
@ -407,7 +412,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
// of execution reach it, we will panic, so bottom is an appropriate
|
||||
// type in that case)
|
||||
let expected = expected.adjust_for_branches(self);
|
||||
let mut result_ty = self.next_diverging_ty_var();
|
||||
let mut result_ty = self.next_diverging_ty_var(
|
||||
TypeVariableOrigin::DivergingBlockExpr(expr.span));
|
||||
let mut all_arms_diverge = Diverges::WarnedAlways;
|
||||
let coerce_first = match expected {
|
||||
// We don't coerce to `()` so that if the match expression is a
|
||||
|
@ -13,6 +13,7 @@
|
||||
use super::{check_fn, Expectation, FnCtxt};
|
||||
|
||||
use astconv::AstConv;
|
||||
use rustc::infer::type_variable::TypeVariableOrigin;
|
||||
use rustc::ty::{self, ToPolyTraitRef, Ty};
|
||||
use std::cmp;
|
||||
use std::iter;
|
||||
@ -66,7 +67,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
let closure_type = self.tcx.mk_closure(expr_def_id,
|
||||
self.parameter_environment.free_substs.extend_to(self.tcx, expr_def_id,
|
||||
|_, _| span_bug!(expr.span, "closure has region param"),
|
||||
|_, _| self.infcx.next_ty_var()
|
||||
|_, _| self.infcx.next_ty_var(TypeVariableOrigin::TransformedUpvar(expr.span))
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -20,6 +20,7 @@ use rustc::infer::InferOk;
|
||||
use rustc::ty::subst::{Subst, Substs};
|
||||
use rustc::traits::{self, ObligationCause};
|
||||
use rustc::ty::{self, Ty, ToPolyTraitRef, TraitRef, TypeFoldable};
|
||||
use rustc::infer::type_variable::TypeVariableOrigin;
|
||||
use rustc::util::nodemap::FxHashSet;
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
@ -1225,7 +1226,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||
let substs = Substs::for_item(self.tcx,
|
||||
impl_def_id,
|
||||
|_, _| self.tcx.mk_region(ty::ReErased),
|
||||
|_, _| self.next_ty_var());
|
||||
|_, _| self.next_ty_var(
|
||||
TypeVariableOrigin::SubstitutionPlaceholder(
|
||||
self.tcx.def_span(impl_def_id))));
|
||||
|
||||
(impl_ty, substs)
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ use syntax_pos::Span;
|
||||
|
||||
use rustc::hir::print as pprust;
|
||||
use rustc::hir;
|
||||
use rustc::infer::type_variable::TypeVariableOrigin;
|
||||
|
||||
use std::cell;
|
||||
use std::cmp::Ordering;
|
||||
@ -53,7 +54,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
self.autoderef(span, ty).any(|(ty, _)| {
|
||||
self.probe(|_| {
|
||||
let fn_once_substs = tcx.mk_substs_trait(ty, &[self.next_ty_var()]);
|
||||
let fn_once_substs = tcx.mk_substs_trait(ty,
|
||||
&[self.next_ty_var(TypeVariableOrigin::MiscVariable(span))]);
|
||||
let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
|
||||
let poly_trait_ref = trait_ref.to_poly_trait_ref();
|
||||
let obligation =
|
||||
|
@ -85,8 +85,8 @@ use dep_graph::DepNode;
|
||||
use fmt_macros::{Parser, Piece, Position};
|
||||
use hir::def::{Def, CtorKind};
|
||||
use hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin,
|
||||
TypeTrace, type_variable};
|
||||
use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin, TypeTrace};
|
||||
use rustc::infer::type_variable::{self, TypeVariableOrigin};
|
||||
use rustc::ty::subst::{Kind, Subst, Substs};
|
||||
use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
|
||||
use rustc::ty::{ParamTy, ParameterEnvironment};
|
||||
@ -117,7 +117,7 @@ use syntax::feature_gate::{GateIssue, emit_feature_err};
|
||||
use syntax::ptr::P;
|
||||
use syntax::symbol::{Symbol, InternedString, keywords};
|
||||
use syntax::util::lev_distance::find_best_match_for_name;
|
||||
use syntax_pos::{self, BytePos, Span};
|
||||
use syntax_pos::{self, BytePos, Span, DUMMY_SP};
|
||||
|
||||
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
||||
@ -683,11 +683,11 @@ struct GatherLocalsVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> GatherLocalsVisitor<'a, 'gcx, 'tcx> {
|
||||
fn assign(&mut self, _span: Span, nid: ast::NodeId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
|
||||
fn assign(&mut self, span: Span, nid: ast::NodeId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
|
||||
match ty_opt {
|
||||
None => {
|
||||
// infer the variable's type
|
||||
let var_ty = self.fcx.next_ty_var();
|
||||
let var_ty = self.fcx.next_ty_var(TypeVariableOrigin::TypeInference(span));
|
||||
self.fcx.locals.borrow_mut().insert(nid, var_ty);
|
||||
var_ty
|
||||
}
|
||||
@ -1444,8 +1444,8 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
fn ty_infer(&self, _span: Span) -> Ty<'tcx> {
|
||||
self.next_ty_var()
|
||||
fn ty_infer(&self, span: Span) -> Ty<'tcx> {
|
||||
self.next_ty_var(TypeVariableOrigin::TypeInference(span))
|
||||
}
|
||||
|
||||
fn ty_infer_for_def(&self,
|
||||
@ -1751,13 +1751,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
if let Some(ty_var) = self.anon_types.borrow().get(&def_id) {
|
||||
return ty_var;
|
||||
}
|
||||
let ty_var = self.next_ty_var();
|
||||
let span = self.tcx.def_span(def_id);
|
||||
let ty_var = self.next_ty_var(TypeVariableOrigin::TypeInference(span));
|
||||
self.anon_types.borrow_mut().insert(def_id, ty_var);
|
||||
|
||||
let item_predicates = self.tcx.item_predicates(def_id);
|
||||
let bounds = item_predicates.instantiate(self.tcx, substs);
|
||||
|
||||
let span = self.tcx.def_span(def_id);
|
||||
for predicate in bounds.predicates {
|
||||
// Change the predicate to refer to the type variable,
|
||||
// which will be the concrete type, instead of the TyAnon.
|
||||
@ -2204,7 +2204,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
let conflicting_default =
|
||||
self.find_conflicting_default(&unbound_tyvars, &default_map, conflict)
|
||||
.unwrap_or(type_variable::Default {
|
||||
ty: self.next_ty_var(),
|
||||
ty: self.next_ty_var(
|
||||
TypeVariableOrigin::MiscVariable(syntax_pos::DUMMY_SP)),
|
||||
origin_span: syntax_pos::DUMMY_SP,
|
||||
// what do I put here?
|
||||
def_id: self.tcx.map.local_def_id(ast::CRATE_NODE_ID)
|
||||
@ -2398,7 +2399,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
unsize,
|
||||
index_ty);
|
||||
|
||||
let input_ty = self.next_ty_var();
|
||||
let input_ty = self.next_ty_var(TypeVariableOrigin::AutoDeref(base_expr.span));
|
||||
|
||||
// First, try built-in indexing.
|
||||
match (adjusted_ty.builtin_index(), &index_ty.sty) {
|
||||
@ -3486,8 +3487,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
// Add adjustments to !-expressions
|
||||
if ty.is_never() {
|
||||
if let Some(hir::map::NodeExpr(_)) = self.tcx.map.find(expr.id) {
|
||||
let adj_ty = self.next_diverging_ty_var();
|
||||
if let Some(hir::map::NodeExpr(node_expr)) = self.tcx.map.find(expr.id) {
|
||||
let adj_ty = self.next_diverging_ty_var(
|
||||
TypeVariableOrigin::AdjustmentType(node_expr.span));
|
||||
self.write_adjustment(expr.id, adjustment::Adjustment {
|
||||
kind: adjustment::Adjust::NeverToAny,
|
||||
target: adj_ty
|
||||
@ -3781,7 +3783,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
hir::ExprLoop(ref body, _, _) => {
|
||||
let unified = self.next_ty_var();
|
||||
let unified = self.next_ty_var(TypeVariableOrigin::TypeInference(body.span));
|
||||
let coerce_to = expected.only_has_type(self).unwrap_or(unified);
|
||||
let ctxt = LoopCtxt {
|
||||
unified: unified,
|
||||
@ -3860,7 +3862,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
});
|
||||
|
||||
let mut unified = self.next_ty_var();
|
||||
let mut unified = self.next_ty_var(TypeVariableOrigin::TypeInference(expr.span));
|
||||
let coerce_to = uty.unwrap_or(unified);
|
||||
|
||||
for (i, e) in args.iter().enumerate() {
|
||||
@ -3905,7 +3907,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
(uty, uty)
|
||||
}
|
||||
None => {
|
||||
let t: Ty = self.next_ty_var();
|
||||
let t: Ty = self.next_ty_var(TypeVariableOrigin::MiscVariable(element.span));
|
||||
let element_ty = self.check_expr_has_type(&element, t);
|
||||
(element_ty, t)
|
||||
}
|
||||
@ -4154,31 +4156,35 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
self.diverges.set(Diverges::Maybe);
|
||||
self.has_errors.set(false);
|
||||
|
||||
let node_id = match stmt.node {
|
||||
let (node_id, span) = match stmt.node {
|
||||
hir::StmtDecl(ref decl, id) => {
|
||||
match decl.node {
|
||||
let span = match decl.node {
|
||||
hir::DeclLocal(ref l) => {
|
||||
self.check_decl_local(&l);
|
||||
l.span
|
||||
}
|
||||
hir::DeclItem(_) => {/* ignore for now */ }
|
||||
}
|
||||
id
|
||||
hir::DeclItem(_) => {/* ignore for now */
|
||||
DUMMY_SP
|
||||
}
|
||||
};
|
||||
(id, span)
|
||||
}
|
||||
hir::StmtExpr(ref expr, id) => {
|
||||
// Check with expected type of ()
|
||||
self.check_expr_has_type(&expr, self.tcx.mk_nil());
|
||||
id
|
||||
(id, expr.span)
|
||||
}
|
||||
hir::StmtSemi(ref expr, id) => {
|
||||
self.check_expr(&expr);
|
||||
id
|
||||
(id, expr.span)
|
||||
}
|
||||
};
|
||||
|
||||
if self.has_errors.get() {
|
||||
self.write_error(node_id);
|
||||
} else if self.diverges.get().always() {
|
||||
self.write_ty(node_id, self.next_diverging_ty_var());
|
||||
self.write_ty(node_id, self.next_diverging_ty_var(
|
||||
TypeVariableOrigin::DivergingStmt(span)));
|
||||
} else {
|
||||
self.write_nil(node_id);
|
||||
}
|
||||
@ -4224,7 +4230,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
ty = self.next_diverging_ty_var();
|
||||
ty = self.next_diverging_ty_var(TypeVariableOrigin::DivergingBlockExpr(blk.span));
|
||||
} else if let ExpectHasType(ety) = expected {
|
||||
if let Some(ref e) = blk.expr {
|
||||
// Coerce the tail expression to the right type.
|
||||
|
@ -13,6 +13,7 @@
|
||||
use super::FnCtxt;
|
||||
use hir::def_id::DefId;
|
||||
use rustc::ty::{Ty, TypeFoldable, PreferMutLvalue};
|
||||
use rustc::infer::type_variable::TypeVariableOrigin;
|
||||
use syntax::ast;
|
||||
use syntax::symbol::Symbol;
|
||||
use rustc::hir;
|
||||
@ -179,7 +180,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
// using this variable as the expected type, which sometimes lets
|
||||
// us do better coercions than we would be able to do otherwise,
|
||||
// particularly for things like `String + &String`.
|
||||
let rhs_ty_var = self.next_ty_var();
|
||||
let rhs_ty_var = self.next_ty_var(TypeVariableOrigin::MiscVariable(rhs_expr.span));
|
||||
|
||||
let return_ty = match self.lookup_op_method(expr, lhs_ty, vec![rhs_ty_var],
|
||||
Symbol::intern(name), trait_def_id,
|
||||
|
@ -25,6 +25,6 @@ pub fn let_<'var, VAR, F: for<'v: 'var> Fn(Expr<'v, VAR>) -> Expr<'v, VAR>>
|
||||
|
||||
fn main() {
|
||||
let ex = |x| {
|
||||
let_(add(x,x), |y| { //~ ERROR unable to infer enough type information about `_`
|
||||
let_(add(x,x), |y| { //~ ERROR unable to infer enough type information about `VAR`
|
||||
let_(add(x, x), |x|x)})};
|
||||
}
|
||||
|
@ -9,4 +9,4 @@
|
||||
// except according to those terms.
|
||||
|
||||
fn main() { format!("{:?}", None); }
|
||||
//~^ ERROR unable to infer enough type information about `_` [E0282]
|
||||
//~^ ERROR unable to infer enough type information about `T` [E0282]
|
||||
|
@ -11,5 +11,5 @@
|
||||
fn main() {
|
||||
// Unconstrained type:
|
||||
format!("{:?}", None);
|
||||
//~^ ERROR unable to infer enough type information about `_` [E0282]
|
||||
//~^ ERROR unable to infer enough type information about `T` [E0282]
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ use std::mem;
|
||||
|
||||
fn main() {
|
||||
mem::transmute(0);
|
||||
//~^ ERROR unable to infer enough type information about `_` [E0282]
|
||||
//~| NOTE cannot infer type for `_`
|
||||
//~^ ERROR unable to infer enough type information about `U` [E0282]
|
||||
//~| NOTE cannot infer type for `U`
|
||||
//~| NOTE type annotations or generic parameter binding
|
||||
}
|
||||
|
@ -17,8 +17,8 @@ pub fn foo<State>(_: TypeWithState<State>) {}
|
||||
|
||||
pub fn bar() {
|
||||
foo(TypeWithState(marker::PhantomData));
|
||||
//~^ ERROR unable to infer enough type information about `_` [E0282]
|
||||
//~| NOTE cannot infer type for `_`
|
||||
//~^ ERROR unable to infer enough type information about `State` [E0282]
|
||||
//~| NOTE cannot infer type for `State`
|
||||
//~| NOTE type annotations or generic parameter binding
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
fn main() {
|
||||
let v = &[];
|
||||
let it = v.iter(); //~ ERROR unable to infer enough type information about `_` [E0282]
|
||||
//~| NOTE cannot infer type for `_`
|
||||
let it = v.iter(); //~ ERROR unable to infer enough type information about `T` [E0282]
|
||||
//~| NOTE cannot infer type for `T`
|
||||
//~| NOTE type annotations or generic parameter binding
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ impl foo for Vec<isize> {
|
||||
fn m1() {
|
||||
// we couldn't infer the type of the vector just based on calling foo()...
|
||||
let mut x = Vec::new();
|
||||
//~^ ERROR unable to infer enough type information about `_` [E0282]
|
||||
//~^ ERROR unable to infer enough type information about `T` [E0282]
|
||||
x.foo();
|
||||
}
|
||||
|
||||
|
@ -34,8 +34,8 @@ where T : Convert<U>
|
||||
|
||||
fn a() {
|
||||
test(22, std::default::Default::default());
|
||||
//~^ ERROR unable to infer enough type information about `_` [E0282]
|
||||
//~| NOTE cannot infer type for `_`
|
||||
//~^ ERROR unable to infer enough type information about `U` [E0282]
|
||||
//~| NOTE cannot infer type for `U`
|
||||
//~| NOTE type annotations or generic parameter binding
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
// Issue #5062
|
||||
|
||||
fn main() {
|
||||
None; //~ ERROR unable to infer enough type information about `_` [E0282]
|
||||
//~| NOTE cannot infer type for `_`
|
||||
None; //~ ERROR unable to infer enough type information about `T` [E0282]
|
||||
//~| NOTE cannot infer type for `T`
|
||||
//~| NOTE type annotations or generic parameter binding
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ struct S<'a, T:'a> {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
S { o: &None }; //~ ERROR unable to infer enough type information about `_` [E0282]
|
||||
//~| NOTE cannot infer type for `_`
|
||||
S { o: &None }; //~ ERROR unable to infer enough type information about `T` [E0282]
|
||||
//~| NOTE cannot infer type for `T`
|
||||
//~| NOTE type annotations or generic parameter binding
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
fn main() {
|
||||
let _foo = Vec::new();
|
||||
//~^ ERROR unable to infer enough type information about `_` [E0282]
|
||||
//~| NOTE cannot infer type for `_`
|
||||
//~^ ERROR unable to infer enough type information about `T` [E0282]
|
||||
//~| NOTE cannot infer type for `T`
|
||||
//~| NOTE type annotations or generic parameter binding
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0282]: unable to infer enough type information about `_`
|
||||
error[E0282]: unable to infer enough type information about `T`
|
||||
--> $DIR/repair_span_std_macros.rs:12:13
|
||||
|
|
||||
12 | let x = vec![];
|
||||
| ^^^^^^ cannot infer type for `_`
|
||||
| ^^^^^^ cannot infer type for `T`
|
||||
|
|
||||
= note: type annotations or generic parameter binding required
|
||||
= note: this error originates in a macro outside of the current crate
|
||||
|
15
src/test/ui/missing-items/missing-type-parameter.rs
Normal file
15
src/test/ui/missing-items/missing-type-parameter.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
fn foo<X>() { }
|
||||
|
||||
fn main() {
|
||||
foo();
|
||||
}
|
10
src/test/ui/missing-items/missing-type-parameter.stderr
Normal file
10
src/test/ui/missing-items/missing-type-parameter.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error[E0282]: unable to infer enough type information about `X`
|
||||
--> $DIR/missing-type-parameter.rs:14:5
|
||||
|
|
||||
14 | foo();
|
||||
| ^^^ cannot infer type for `X`
|
||||
|
|
||||
= note: type annotations or generic parameter binding required
|
||||
|
||||
error: aborting due to previous error
|
||||
|
Loading…
Reference in New Issue
Block a user