diff --git a/src/librustc/infer/glb.rs b/src/librustc/infer/glb.rs index a5709e1880801..8ccadc6b2af04 100644 --- a/src/librustc/infer/glb.rs +++ b/src/librustc/infer/glb.rs @@ -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)?; diff --git a/src/librustc/infer/lattice.rs b/src/librustc/infer/lattice.rs index eda78428e61ad..f7b26a918b3a2 100644 --- a/src/librustc/infer/lattice.rs +++ b/src/librustc/infer/lattice.rs @@ -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) } diff --git a/src/librustc/infer/lub.rs b/src/librustc/infer/lub.rs index 7d352be67d32b..89571dea10c34 100644 --- a/src/librustc/infer/lub.rs +++ b/src/librustc/infer/lub.rs @@ -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)?; diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 72ef987aefd5c..9b58334e65805 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -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 because the // types that might instantiate a general type variable have an // order, represented by its upper and lower bounds. - type_variables: RefCell>, + pub type_variables: RefCell>, // Map from integral variable to the kind of integer it represents int_unification_table: RefCell>, @@ -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) } diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs index 804765ec8811e..9c8419d9546d2 100644 --- a/src/librustc/infer/type_variable.rs +++ b/src/librustc/infer/type_variable.rs @@ -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, } +/// 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>) -> ty::TyVid { + origin: TypeVariableOrigin, + default: Option>,) -> 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 }; diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 2e8e45468ddcb..205a273df62d4 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -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(&self, diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 27b7adf0ef34a..865bc2a95608b 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -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] diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 464e15faeaf75..ad7def42b8965 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -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; @@ -494,7 +496,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)); @@ -513,7 +515,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), @@ -633,7 +635,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 diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 6e2b42881a709..b652f3c4ad734 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -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 diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 486f8fc25bb32..870c3045e6bdb 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -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 syntax::abi::Abi; @@ -65,7 +66,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)) ) ); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index b0787d75c9cb4..5cb0804b1bca1 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -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) } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 7cfefefc0d964..86bfede87b333 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -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 = diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 8d51f52e9986e..502a93a4aa2da 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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> { + fn assign(&mut self, span: Span, nid: ast::NodeId, ty_opt: Option>) -> 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 } @@ -1442,8 +1442,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, @@ -1749,13 +1749,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. @@ -2202,7 +2202,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) @@ -2396,7 +2397,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) { @@ -3485,8 +3486,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 @@ -3778,7 +3780,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, @@ -3857,7 +3859,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() { @@ -3902,7 +3904,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) } @@ -4151,31 +4153,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); } @@ -4221,7 +4227,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. diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index adb8c6be42bc1..d1a9b8ef85ae4 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -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, diff --git a/src/test/compile-fail/issue-23046.rs b/src/test/compile-fail/issue-23046.rs index dba9c32f9b480..c274665530fdb 100644 --- a/src/test/compile-fail/issue-23046.rs +++ b/src/test/compile-fail/issue-23046.rs @@ -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)})}; } diff --git a/src/test/compile-fail/issue-5062.rs b/src/test/compile-fail/issue-5062.rs index f5aa4fadbed88..cf78d6d8c0ad4 100644 --- a/src/test/compile-fail/issue-5062.rs +++ b/src/test/compile-fail/issue-5062.rs @@ -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] diff --git a/src/test/compile-fail/issue-6458-2.rs b/src/test/compile-fail/issue-6458-2.rs index 71f2805457915..3816896d43d1f 100644 --- a/src/test/compile-fail/issue-6458-2.rs +++ b/src/test/compile-fail/issue-6458-2.rs @@ -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] } diff --git a/src/test/compile-fail/issue-6458-3.rs b/src/test/compile-fail/issue-6458-3.rs index e397805565bbd..8029522f5d3cc 100644 --- a/src/test/compile-fail/issue-6458-3.rs +++ b/src/test/compile-fail/issue-6458-3.rs @@ -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 } diff --git a/src/test/compile-fail/issue-6458.rs b/src/test/compile-fail/issue-6458.rs index a64522a0e5b75..f8354ddbf12a5 100644 --- a/src/test/compile-fail/issue-6458.rs +++ b/src/test/compile-fail/issue-6458.rs @@ -17,8 +17,8 @@ pub fn foo(_: TypeWithState) {} 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 } diff --git a/src/test/compile-fail/issue-7813.rs b/src/test/compile-fail/issue-7813.rs index e3cb1d0c7daaf..e37a881642393 100644 --- a/src/test/compile-fail/issue-7813.rs +++ b/src/test/compile-fail/issue-7813.rs @@ -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 } diff --git a/src/test/compile-fail/method-ambig-one-trait-unknown-int-type.rs b/src/test/compile-fail/method-ambig-one-trait-unknown-int-type.rs index 4f86909765ef1..1cf41f95a2d6d 100644 --- a/src/test/compile-fail/method-ambig-one-trait-unknown-int-type.rs +++ b/src/test/compile-fail/method-ambig-one-trait-unknown-int-type.rs @@ -32,7 +32,7 @@ impl foo for Vec { 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(); } diff --git a/src/test/compile-fail/traits-multidispatch-convert-ambig-dest.rs b/src/test/compile-fail/traits-multidispatch-convert-ambig-dest.rs index e6545063dbd44..ed2ffa995e521 100644 --- a/src/test/compile-fail/traits-multidispatch-convert-ambig-dest.rs +++ b/src/test/compile-fail/traits-multidispatch-convert-ambig-dest.rs @@ -34,8 +34,8 @@ where T : Convert 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 } diff --git a/src/test/compile-fail/unconstrained-none.rs b/src/test/compile-fail/unconstrained-none.rs index 380cdd266cd6e..88080bc70cab4 100644 --- a/src/test/compile-fail/unconstrained-none.rs +++ b/src/test/compile-fail/unconstrained-none.rs @@ -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 } diff --git a/src/test/compile-fail/unconstrained-ref.rs b/src/test/compile-fail/unconstrained-ref.rs index ba94bf613d217..12278549215ed 100644 --- a/src/test/compile-fail/unconstrained-ref.rs +++ b/src/test/compile-fail/unconstrained-ref.rs @@ -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 } diff --git a/src/test/compile-fail/vector-no-ann.rs b/src/test/compile-fail/vector-no-ann.rs index 25709f35246e3..d559caf77a1a3 100644 --- a/src/test/compile-fail/vector-no-ann.rs +++ b/src/test/compile-fail/vector-no-ann.rs @@ -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 } diff --git a/src/test/ui/codemap_tests/repair_span_std_macros.stderr b/src/test/ui/codemap_tests/repair_span_std_macros.stderr index 73a1c5bae85e2..7e0d778a3b205 100644 --- a/src/test/ui/codemap_tests/repair_span_std_macros.stderr +++ b/src/test/ui/codemap_tests/repair_span_std_macros.stderr @@ -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 diff --git a/src/test/ui/missing-items/missing-type-parameter.rs b/src/test/ui/missing-items/missing-type-parameter.rs new file mode 100644 index 0000000000000..3671abd66246d --- /dev/null +++ b/src/test/ui/missing-items/missing-type-parameter.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn foo() { } + +fn main() { + foo(); +} diff --git a/src/test/ui/missing-items/missing-type-parameter.stderr b/src/test/ui/missing-items/missing-type-parameter.stderr new file mode 100644 index 0000000000000..2d007af4980b2 --- /dev/null +++ b/src/test/ui/missing-items/missing-type-parameter.stderr @@ -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 +