diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 8a391f9cde3a3..618561f3b0257 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -1812,6 +1812,8 @@ makes a difference in practice.) register_diagnostics! { // E0006 // merged with E0005 +// E0101, // replaced with E0282 +// E0102, // replaced with E0282 // E0134, // E0135, E0278, // requirement is not satisfied diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index f7a7d0e2071f2..71dff3b2bb94d 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -25,7 +25,7 @@ use super::{ use errors::DiagnosticBuilder; use fmt_macros::{Parser, Piece, Position}; -use hir::{intravisit, Local, Pat}; +use hir::{self, intravisit, Local, Pat, Body}; use hir::intravisit::{Visitor, NestedVisitorMap}; use hir::map::NodeExpr; use hir::def_id::DefId; @@ -33,8 +33,8 @@ use infer::{self, InferCtxt}; use infer::type_variable::TypeVariableOrigin; use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL; use std::fmt; -use syntax::ast; -use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; +use syntax::ast::{self, NodeId}; +use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable, TyInfer, TyVar}; use ty::error::ExpectedFound; use ty::fast_reject; use ty::fold::TypeFolder; @@ -66,37 +66,52 @@ impl<'a, 'gcx, 'tcx> TraitErrorKey<'tcx> { struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, target_ty: &'a Ty<'tcx>, - found_pattern: Option<&'a Pat>, + hir_map: &'a hir::map::Map<'gcx>, + found_local_pattern: Option<&'gcx Pat>, + found_arg_pattern: Option<&'gcx Pat>, } impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> { - fn is_match(&self, ty: Ty<'tcx>) -> bool { - ty == *self.target_ty || match (&ty.sty, &self.target_ty.sty) { - (&ty::TyInfer(ty::TyVar(a_vid)), &ty::TyInfer(ty::TyVar(b_vid))) => - self.infcx.type_variables - .borrow_mut() - .sub_unified(a_vid, b_vid), - + fn node_matches_type(&mut self, node_id: &'gcx NodeId) -> bool { + match self.infcx.tables.borrow().node_types.get(node_id) { + Some(&ty) => { + let ty = self.infcx.resolve_type_vars_if_possible(&ty); + ty.walk().any(|inner_ty| { + inner_ty == *self.target_ty || match (&inner_ty.sty, &self.target_ty.sty) { + (&TyInfer(TyVar(a_vid)), &TyInfer(TyVar(b_vid))) => { + self.infcx + .type_variables + .borrow_mut() + .sub_unified(a_vid, b_vid) + } + _ => false, + } + }) + } _ => false, } } } -impl<'a, 'gcx, 'tcx> Visitor<'a> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'a> { - NestedVisitorMap::None +impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> { + NestedVisitorMap::OnlyBodies(&self.hir_map) } - fn visit_local(&mut self, local: &'a Local) { - if let Some(&ty) = self.infcx.tables.borrow().node_types.get(&local.id) { - let ty = self.infcx.resolve_type_vars_if_possible(&ty); - let is_match = ty.walk().any(|t| self.is_match(t)); + fn visit_local(&mut self, local: &'gcx Local) { + if self.found_local_pattern.is_none() && self.node_matches_type(&local.id) { + self.found_local_pattern = Some(&*local.pat); + } + intravisit::walk_local(self, local); + } - if is_match && self.found_pattern.is_none() { - self.found_pattern = Some(&*local.pat); + fn visit_body(&mut self, body: &'gcx Body) { + for argument in &body.arguments { + if self.found_arg_pattern.is_none() && self.node_matches_type(&argument.id) { + self.found_arg_pattern = Some(&*argument.pat); } } - intravisit::walk_local(self, local); + intravisit::walk_body(self, body); } } @@ -721,6 +736,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // coherence violation, so we don't report it here. let predicate = self.resolve_type_vars_if_possible(&obligation.predicate); + let body_id = hir::BodyId { node_id: obligation.cause.body_id }; + let span = obligation.cause.span; debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})", predicate, @@ -768,10 +785,10 @@ 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(obligation, self_ty); + self.need_type_info(body_id, span, self_ty); } else { let mut err = struct_span_err!(self.tcx.sess, - obligation.cause.span, E0283, + span, E0283, "type annotations required: \ cannot resolve `{}`", predicate); @@ -785,7 +802,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(obligation, ty); + self.need_type_info(body_id, span, ty); } } @@ -796,7 +813,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(obligation, a); + self.need_type_info(hir::BodyId { node_id: obligation.cause.body_id }, + obligation.cause.span, + a); } } @@ -874,42 +893,66 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } - fn need_type_info(&self, obligation: &PredicateObligation<'tcx>, ty: Ty<'tcx>) { + pub fn need_type_info(&self, body_id: hir::BodyId, span: Span, ty: Ty<'tcx>) { let ty = self.resolve_type_vars_if_possible(&ty); let name = self.extract_type_name(&ty); - let ref cause = obligation.cause; - let mut err = struct_span_err!(self.tcx.sess, - cause.span, - E0282, - "type annotations needed"); - - err.span_label(cause.span, &format!("cannot infer type for `{}`", name)); + let mut err_span = span; + let mut labels = vec![(span, format!("cannot infer type for `{}`", name))]; let mut local_visitor = FindLocalByTypeVisitor { infcx: &self, target_ty: &ty, - found_pattern: None, + hir_map: &self.tcx.hir, + found_local_pattern: None, + found_arg_pattern: None, }; // #40294: cause.body_id can also be a fn declaration. // Currently, if it's anything other than NodeExpr, we just ignore it - match self.tcx.hir.find(cause.body_id) { + match self.tcx.hir.find(body_id.node_id) { Some(NodeExpr(expr)) => local_visitor.visit_expr(expr), _ => () } - if let Some(pattern) = local_visitor.found_pattern { - let pattern_span = pattern.span; + if let Some(pattern) = local_visitor.found_arg_pattern { + err_span = pattern.span; + // We don't want to show the default label for closures. + // + // So, before clearing, the output would look something like this: + // ``` + // let x = |_| { }; + // - ^^^^ cannot infer type for `[_; 0]` + // | + // consider giving this closure parameter a type + // ``` + // + // After clearing, it looks something like this: + // ``` + // let x = |_| { }; + // ^ consider giving this closure parameter a type + // ``` + labels.clear(); + labels.push((pattern.span, format!("consider giving this closure parameter a type"))); + } + + if let Some(pattern) = local_visitor.found_local_pattern { if let Some(simple_name) = pattern.simple_name() { - err.span_label(pattern_span, - &format!("consider giving `{}` a type", - simple_name)); + labels.push((pattern.span, format!("consider giving `{}` a type", simple_name))); } else { - err.span_label(pattern_span, &format!("consider giving a type to pattern")); + labels.push((pattern.span, format!("consider giving the pattern a type"))); } } + let mut err = struct_span_err!(self.tcx.sess, + err_span, + E0282, + "type annotations needed"); + + for (target_span, label_message) in labels { + err.span_label(target_span, &label_message); + } + err.emit(); } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 7fffbd14e2160..f196aa82b1ef3 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -11,22 +11,18 @@ // Type resolution: the phase that finds all the types in the AST with // unresolved type variables and replaces "ty_var" types with their // substitutions. -use self::ResolveReason::*; use check::FnCtxt; +use rustc::hir; +use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; +use rustc::infer::{InferCtxt}; use rustc::ty::{self, Ty, TyCtxt, MethodCall, MethodCallee}; use rustc::ty::adjustment; use rustc::ty::fold::{TypeFolder,TypeFoldable}; -use rustc::infer::{InferCtxt, FixupError}; use rustc::util::nodemap::{DefIdMap, DefIdSet}; - -use std::mem; - use syntax::ast; use syntax_pos::Span; - -use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; -use rustc::hir; +use std::mem; /////////////////////////////////////////////////////////////////////////// // Entry point @@ -37,9 +33,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let item_id = self.tcx.hir.body_owner(body.id()); let item_def_id = self.tcx.hir.local_def_id(item_id); - let mut wbcx = WritebackCx::new(self); + let mut wbcx = WritebackCx::new(self, body); for arg in &body.arguments { - wbcx.visit_node_id(ResolvingPattern(arg.pat.span), arg.id); + wbcx.visit_node_id(arg.pat.span, arg.id); } wbcx.visit_body(body); wbcx.visit_upvar_borrow_map(); @@ -80,15 +76,19 @@ struct WritebackCx<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> { // early-bound versions of them, visible from the // outside of the function. This is needed by, and // only populated if there are any `impl Trait`. - free_to_bound_regions: DefIdMap<&'gcx ty::Region> + free_to_bound_regions: DefIdMap<&'gcx ty::Region>, + + body: &'gcx hir::Body, } impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { - fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>) -> WritebackCx<'cx, 'gcx, 'tcx> { + fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>, body: &'gcx hir::Body) + -> WritebackCx<'cx, 'gcx, 'tcx> { let mut wbcx = WritebackCx { fcx: fcx, tables: ty::TypeckTables::empty(), - free_to_bound_regions: DefIdMap() + free_to_bound_regions: DefIdMap(), + body: body }; // Only build the reverse mapping if `impl Trait` is used. @@ -195,21 +195,20 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { } fn visit_stmt(&mut self, s: &'gcx hir::Stmt) { - self.visit_node_id(ResolvingExpr(s.span), s.node.id()); + self.visit_node_id(s.span, s.node.id()); intravisit::walk_stmt(self, s); } fn visit_expr(&mut self, e: &'gcx hir::Expr) { self.fix_scalar_builtin_expr(e); - self.visit_node_id(ResolvingExpr(e.span), e.id); - self.visit_method_map_entry(ResolvingExpr(e.span), - MethodCall::expr(e.id)); + self.visit_node_id(e.span, e.id); + self.visit_method_map_entry(e.span, MethodCall::expr(e.id)); if let hir::ExprClosure(_, _, body, _) = e.node { let body = self.fcx.tcx.hir.body(body); for arg in &body.arguments { - self.visit_node_id(ResolvingExpr(e.span), arg.id); + self.visit_node_id(e.span, arg.id); } self.visit_body(body); @@ -219,20 +218,20 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { } fn visit_block(&mut self, b: &'gcx hir::Block) { - self.visit_node_id(ResolvingExpr(b.span), b.id); + self.visit_node_id(b.span, b.id); intravisit::walk_block(self, b); } fn visit_pat(&mut self, p: &'gcx hir::Pat) { - self.visit_node_id(ResolvingPattern(p.span), p.id); + self.visit_node_id(p.span, p.id); intravisit::walk_pat(self, p); } fn visit_local(&mut self, l: &'gcx hir::Local) { + intravisit::walk_local(self, l); let var_ty = self.fcx.local_ty(l.span, l.id); - let var_ty = self.resolve(&var_ty, ResolvingLocal(l.span)); + let var_ty = self.resolve(&var_ty, &l.span); self.write_ty_to_tables(l.id, var_ty); - intravisit::walk_local(self, l); } } @@ -243,7 +242,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue, ty::UpvarCapture::ByRef(ref upvar_borrow) => { let r = upvar_borrow.region; - let r = self.resolve(&r, ResolvingUpvar(*upvar_id)); + let r = self.resolve(&r, &upvar_id.var_id); ty::UpvarCapture::ByRef( ty::UpvarBorrow { kind: upvar_borrow.kind, region: r }) } @@ -257,7 +256,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { fn visit_closures(&mut self) { for (&id, closure_ty) in self.fcx.tables.borrow().closure_tys.iter() { - let closure_ty = self.resolve(closure_ty, ResolvingClosure(id)); + let closure_ty = self.resolve(closure_ty, &id); self.tables.closure_tys.insert(id, closure_ty); } @@ -282,8 +281,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { fn visit_anon_types(&mut self) { let gcx = self.tcx().global_tcx(); for (&node_id, &concrete_ty) in self.fcx.anon_types.borrow().iter() { - let reason = ResolvingAnonTy(node_id); - let inside_ty = self.resolve(&concrete_ty, reason); + let inside_ty = self.resolve(&concrete_ty, &node_id); // Convert the type from the function into a type valid outside // the function, by replacing free regions with early-bound ones. @@ -305,7 +303,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { ty::ReLateBound(..) | ty::ReScope(_) | ty::ReSkolemized(..) => { - let span = reason.span(self.tcx()); + let span = node_id.to_span(&self.fcx.tcx); span_err!(self.tcx().sess, span, E0564, "only named lifetimes are allowed in `impl Trait`, \ but `{}` was found in the type `{}`", r, inside_ty); @@ -314,7 +312,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { ty::ReVar(_) | ty::ReErased => { - let span = reason.span(self.tcx()); + let span = node_id.to_span(&self.fcx.tcx); span_bug!(span, "invalid region in impl Trait: {:?}", r); } } @@ -324,37 +322,37 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } } - fn visit_node_id(&mut self, reason: ResolveReason, id: ast::NodeId) { + fn visit_node_id(&mut self, span: Span, node_id: ast::NodeId) { // Export associated path extensions. - if let Some(def) = self.fcx.tables.borrow_mut().type_relative_path_defs.remove(&id) { - self.tables.type_relative_path_defs.insert(id, def); + if let Some(def) = self.fcx.tables.borrow_mut().type_relative_path_defs.remove(&node_id) { + self.tables.type_relative_path_defs.insert(node_id, def); } - // Resolve any borrowings for the node with id `id` - self.visit_adjustments(reason, id); + // Resolve any borrowings for the node with id `node_id` + self.visit_adjustments(span, node_id); - // Resolve the type of the node with id `id` - let n_ty = self.fcx.node_ty(id); - let n_ty = self.resolve(&n_ty, reason); - self.write_ty_to_tables(id, n_ty); - debug!("Node {} has type {:?}", id, n_ty); + // Resolve the type of the node with id `node_id` + let n_ty = self.fcx.node_ty(node_id); + let n_ty = self.resolve(&n_ty, &span); + self.write_ty_to_tables(node_id, n_ty); + debug!("Node {} has type {:?}", node_id, n_ty); // Resolve any substitutions - self.fcx.opt_node_ty_substs(id, |item_substs| { - let item_substs = self.resolve(item_substs, reason); + self.fcx.opt_node_ty_substs(node_id, |item_substs| { + let item_substs = self.resolve(item_substs, &span); if !item_substs.is_noop() { - debug!("write_substs_to_tcx({}, {:?})", id, item_substs); + debug!("write_substs_to_tcx({}, {:?})", node_id, item_substs); assert!(!item_substs.substs.needs_infer()); - self.tables.item_substs.insert(id, item_substs); + self.tables.item_substs.insert(node_id, item_substs); } }); } - fn visit_adjustments(&mut self, reason: ResolveReason, id: ast::NodeId) { - let adjustments = self.fcx.tables.borrow_mut().adjustments.remove(&id); + fn visit_adjustments(&mut self, span: Span, node_id: ast::NodeId) { + let adjustments = self.fcx.tables.borrow_mut().adjustments.remove(&node_id); match adjustments { None => { - debug!("No adjustments for node {}", id); + debug!("No adjustments for node {}", node_id); } Some(adjustment) => { @@ -381,29 +379,29 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { adjustment::Adjust::DerefRef { autoderefs, autoref, unsize } => { for autoderef in 0..autoderefs { - let method_call = MethodCall::autoderef(id, autoderef as u32); - self.visit_method_map_entry(reason, method_call); + let method_call = MethodCall::autoderef(node_id, autoderef as u32); + self.visit_method_map_entry(span, method_call); } adjustment::Adjust::DerefRef { autoderefs: autoderefs, - autoref: self.resolve(&autoref, reason), + autoref: self.resolve(&autoref, &span), unsize: unsize, } } }; let resolved_adjustment = adjustment::Adjustment { kind: resolved_adjustment, - target: self.resolve(&adjustment.target, reason) + target: self.resolve(&adjustment.target, &span) }; - debug!("Adjustments for node {}: {:?}", id, resolved_adjustment); - self.tables.adjustments.insert(id, resolved_adjustment); + debug!("Adjustments for node {}: {:?}", node_id, resolved_adjustment); + self.tables.adjustments.insert(node_id, resolved_adjustment); } } } fn visit_method_map_entry(&mut self, - reason: ResolveReason, + method_span: Span, method_call: MethodCall) { // Resolve any method map entry let new_method = match self.fcx.tables.borrow_mut().method_map.remove(&method_call) { @@ -413,8 +411,8 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { method); let new_method = MethodCallee { def_id: method.def_id, - ty: self.resolve(&method.ty, reason), - substs: self.resolve(&method.substs, reason), + ty: self.resolve(&method.ty, &method_span), + substs: self.resolve(&method.substs, &method_span), }; Some(new_method) @@ -430,72 +428,49 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { fn visit_liberated_fn_sigs(&mut self) { for (&node_id, fn_sig) in self.fcx.tables.borrow().liberated_fn_sigs.iter() { - let fn_sig = self.resolve(fn_sig, ResolvingFnSig(node_id)); + let fn_sig = self.resolve(fn_sig, &node_id); self.tables.liberated_fn_sigs.insert(node_id, fn_sig.clone()); } } fn visit_fru_field_types(&mut self) { for (&node_id, ftys) in self.fcx.tables.borrow().fru_field_types.iter() { - let ftys = self.resolve(ftys, ResolvingFieldTypes(node_id)); + let ftys = self.resolve(ftys, &node_id); self.tables.fru_field_types.insert(node_id, ftys); } } fn visit_type_nodes(&self) { for (&id, ty) in self.fcx.ast_ty_to_ty_cache.borrow().iter() { - let ty = self.resolve(ty, ResolvingTyNode(id)); + let ty = self.resolve(ty, &id); self.fcx.tcx.ast_ty_to_ty_cache.borrow_mut().insert(id, ty); } } - fn resolve(&self, x: &T, reason: ResolveReason) -> T::Lifted + fn resolve(&self, x: &T, span: &Locatable) -> T::Lifted where T: TypeFoldable<'tcx> + ty::Lift<'gcx> { - let x = x.fold_with(&mut Resolver::new(self.fcx, reason)); + let x = x.fold_with(&mut Resolver::new(self.fcx, span, self.body)); if let Some(lifted) = self.tcx().lift_to_global(&x) { lifted } else { - span_bug!(reason.span(self.tcx()), - "writeback: `{:?}` missing from the global type context", x); + span_bug!(span.to_span(&self.fcx.tcx), + "writeback: `{:?}` missing from the global type context", + x); } } } -/////////////////////////////////////////////////////////////////////////// -// Resolution reason. - -#[derive(Copy, Clone, Debug)] -enum ResolveReason { - ResolvingExpr(Span), - ResolvingLocal(Span), - ResolvingPattern(Span), - ResolvingUpvar(ty::UpvarId), - ResolvingClosure(ast::NodeId), - ResolvingFnSig(ast::NodeId), - ResolvingFieldTypes(ast::NodeId), - ResolvingAnonTy(ast::NodeId), - ResolvingTyNode(ast::NodeId), +trait Locatable { + fn to_span(&self, tcx: &TyCtxt) -> Span; } -impl<'a, 'gcx, 'tcx> ResolveReason { - fn span(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Span { - match *self { - ResolvingExpr(s) => s, - ResolvingLocal(s) => s, - ResolvingPattern(s) => s, - ResolvingUpvar(upvar_id) => { - tcx.expr_span(upvar_id.closure_expr_id) - } - ResolvingClosure(id) | - ResolvingFnSig(id) | - ResolvingFieldTypes(id) | - ResolvingTyNode(id) | - ResolvingAnonTy(id) => { - tcx.hir.span(id) - } - } - } +impl Locatable for Span { + fn to_span(&self, _: &TyCtxt) -> Span { *self } +} + +impl Locatable for ast::NodeId { + fn to_span(&self, tcx: &TyCtxt) -> Span { tcx.hir.span(*self) } } /////////////////////////////////////////////////////////////////////////// @@ -505,82 +480,25 @@ impl<'a, 'gcx, 'tcx> ResolveReason { struct Resolver<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> { tcx: TyCtxt<'cx, 'gcx, 'tcx>, infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, - reason: ResolveReason, + span: &'cx Locatable, + body: &'gcx hir::Body, } impl<'cx, 'gcx, 'tcx> Resolver<'cx, 'gcx, 'tcx> { - fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>, - reason: ResolveReason) - -> Resolver<'cx, 'gcx, 'tcx> + fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>, span: &'cx Locatable, body: &'gcx hir::Body) + -> Resolver<'cx, 'gcx, 'tcx> { - Resolver::from_infcx(fcx, reason) - } - - fn from_infcx(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, - reason: ResolveReason) - -> Resolver<'cx, 'gcx, 'tcx> - { - Resolver { infcx: infcx, - tcx: infcx.tcx, - reason: reason } + Resolver { + tcx: fcx.tcx, + infcx: fcx, + span: span, + body: body, + } } - fn report_error(&self, e: FixupError) { + fn report_error(&self, t: Ty<'tcx>) { if !self.tcx.sess.has_errors() { - match self.reason { - ResolvingExpr(span) => { - struct_span_err!( - self.tcx.sess, span, E0101, - "cannot determine a type for this expression: {}", e) - .span_label(span, &format!("cannot resolve type of expression")) - .emit(); - } - - ResolvingLocal(span) => { - struct_span_err!( - self.tcx.sess, span, E0102, - "cannot determine a type for this local variable: {}", e) - .span_label(span, &format!("cannot resolve type of variable")) - .emit(); - } - - ResolvingPattern(span) => { - span_err!(self.tcx.sess, span, E0103, - "cannot determine a type for this pattern binding: {}", e); - } - - ResolvingUpvar(upvar_id) => { - let span = self.reason.span(self.tcx); - span_err!(self.tcx.sess, span, E0104, - "cannot resolve lifetime for captured variable `{}`: {}", - self.tcx.local_var_name_str(upvar_id.var_id), e); - } - - ResolvingClosure(_) => { - let span = self.reason.span(self.tcx); - span_err!(self.tcx.sess, span, E0196, - "cannot determine a type for this closure") - } - - ResolvingFnSig(_) | - ResolvingFieldTypes(_) | - ResolvingTyNode(_) => { - // any failures here should also fail when - // resolving the patterns, closure types, or - // something else. - let span = self.reason.span(self.tcx); - self.tcx.sess.delay_span_bug( - span, - &format!("cannot resolve some aspect of data for {:?}: {}", - self.reason, e)); - } - - ResolvingAnonTy(_) => { - let span = self.reason.span(self.tcx); - span_err!(self.tcx.sess, span, E0563, - "cannot determine a type for this `impl Trait`: {}", e) - } - } + self.infcx.need_type_info(self.body.id(), self.span.to_span(&self.tcx), t); } } } @@ -593,20 +511,21 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Resolver<'cx, 'gcx, 'tcx> { fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { match self.infcx.fully_resolve(&t) { Ok(t) => t, - Err(e) => { + Err(_) => { debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t); - self.report_error(e); + self.report_error(t); self.tcx().types.err } } } + // FIXME This should be carefully checked + // We could use `self.report_error` but it doesn't accept a ty::Region, right now. fn fold_region(&mut self, r: &'tcx ty::Region) -> &'tcx ty::Region { match self.infcx.fully_resolve(&r) { Ok(r) => r, - Err(e) => { - self.report_error(e); + Err(_) => { self.tcx.mk_region(ty::ReStatic) } } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 2d72052f1e5ad..68afcae2b6746 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -1351,50 +1351,6 @@ extern "rust-intrinsic" { ``` "##, -E0101: r##" -You hit this error because the compiler lacks the information to -determine a type for this expression. Erroneous code example: - -```compile_fail,E0101 -let x = |_| {}; // error: cannot determine a type for this expression -``` - -You have two possibilities to solve this situation: - -* Give an explicit definition of the expression -* Infer the expression - -Examples: - -``` -let x = |_ : u32| {}; // ok! -// or: -let x = |_| {}; -x(0u32); -``` -"##, - -E0102: r##" -You hit this error because the compiler lacks the information to -determine the type of this variable. Erroneous code example: - -```compile_fail,E0282 -// could be an array of anything -let x = []; // error: cannot determine a type for this local variable -``` - -To solve this situation, constrain the type of the variable. -Examples: - -``` -#![allow(unused_variables)] - -fn main() { - let x: [u8; 0] = []; -} -``` -"##, - E0107: r##" This error means that an incorrect number of lifetime parameters were provided for a type (like a struct or enum) or trait: @@ -4146,8 +4102,8 @@ register_diagnostics! { // E0068, // E0085, // E0086, - E0103, // @GuillaumeGomez: I was unable to get this error, try your best! - E0104, +// E0103, +// E0104, // E0123, // E0127, // E0129, @@ -4164,7 +4120,7 @@ register_diagnostics! { // E0188, // can not cast an immutable reference to a mutable pointer // E0189, // deprecated: can only cast a boxed pointer to a boxed object // E0190, // deprecated: can only cast a &-pointer to an &-object - E0196, // cannot determine a type for this closure +// E0196, // cannot determine a type for this closure E0203, // type parameter has more than one relaxed default bound, // and only one is supported E0208, diff --git a/src/test/compile-fail/issue-12187-1.rs b/src/test/compile-fail/issue-12187-1.rs index 6aeb9442c40ed..a79021d3cd5d2 100644 --- a/src/test/compile-fail/issue-12187-1.rs +++ b/src/test/compile-fail/issue-12187-1.rs @@ -16,5 +16,5 @@ fn main() { let &v = new(); //~^ ERROR type annotations needed [E0282] //~| NOTE cannot infer type for `_` - //~| NOTE consider giving a type to pattern + //~| NOTE consider giving the pattern a type } diff --git a/src/test/compile-fail/issue-12187-2.rs b/src/test/compile-fail/issue-12187-2.rs index d52ed06c4085d..38b3c5d4e9a64 100644 --- a/src/test/compile-fail/issue-12187-2.rs +++ b/src/test/compile-fail/issue-12187-2.rs @@ -16,5 +16,5 @@ fn main() { let &v = new(); //~^ ERROR type annotations needed [E0282] //~| NOTE cannot infer type for `_` - //~| NOTE consider giving a type to pattern + //~| NOTE consider giving the pattern a type } diff --git a/src/test/ui/type-check/issue-38812-2.rs b/src/test/ui/type-check/cannot_infer_local_or_array.rs similarity index 94% rename from src/test/ui/type-check/issue-38812-2.rs rename to src/test/ui/type-check/cannot_infer_local_or_array.rs index c476657d20796..0b35a9c3dbebc 100644 --- a/src/test/ui/type-check/issue-38812-2.rs +++ b/src/test/ui/type-check/cannot_infer_local_or_array.rs @@ -9,5 +9,5 @@ // except according to those terms. fn main() { - let (x,) = (vec![],); + let x = []; } diff --git a/src/test/ui/type-check/cannot_infer_local_or_array.stderr b/src/test/ui/type-check/cannot_infer_local_or_array.stderr new file mode 100644 index 0000000000000..8c52bb5a1d3a5 --- /dev/null +++ b/src/test/ui/type-check/cannot_infer_local_or_array.stderr @@ -0,0 +1,10 @@ +error[E0282]: type annotations needed + --> $DIR/cannot_infer_local_or_array.rs:12:13 + | +12 | let x = []; + | - ^^ cannot infer type for `_` + | | + | consider giving `x` a type + +error: aborting due to previous error + diff --git a/src/test/ui/type-check/issue-38812.rs b/src/test/ui/type-check/cannot_infer_local_or_vec.rs similarity index 100% rename from src/test/ui/type-check/issue-38812.rs rename to src/test/ui/type-check/cannot_infer_local_or_vec.rs diff --git a/src/test/ui/type-check/issue-38812.stderr b/src/test/ui/type-check/cannot_infer_local_or_vec.stderr similarity index 86% rename from src/test/ui/type-check/issue-38812.stderr rename to src/test/ui/type-check/cannot_infer_local_or_vec.stderr index 6365e761453f9..4788fad20889e 100644 --- a/src/test/ui/type-check/issue-38812.stderr +++ b/src/test/ui/type-check/cannot_infer_local_or_vec.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed - --> $DIR/issue-38812.rs:12:13 + --> $DIR/cannot_infer_local_or_vec.rs:12:13 | 12 | let x = vec![]; | - ^^^^^^ cannot infer type for `T` diff --git a/src/test/compile-fail/E0101.rs b/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.rs similarity index 73% rename from src/test/compile-fail/E0101.rs rename to src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.rs index 0005da048e4a5..8d32c1ff683bb 100644 --- a/src/test/compile-fail/E0101.rs +++ b/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.rs @@ -1,4 +1,4 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -9,7 +9,5 @@ // except according to those terms. fn main() { - let x = |_| {}; - //~^ ERROR E0101 - //~| NOTE cannot resolve type of expression + let (x, ) = (vec![], ); } diff --git a/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr b/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr new file mode 100644 index 0000000000000..ccffadebe9ee2 --- /dev/null +++ b/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr @@ -0,0 +1,12 @@ +error[E0282]: type annotations needed + --> $DIR/cannot_infer_local_or_vec_in_tuples.rs:12:18 + | +12 | let (x, ) = (vec![], ); + | ----- ^^^^^^ cannot infer type for `T` + | | + | consider giving the pattern a type + | + = note: this error originates in a macro outside of the current crate + +error: aborting due to previous error + diff --git a/src/test/compile-fail/issue-22897.rs b/src/test/ui/type-check/issue-22897.rs similarity index 63% rename from src/test/compile-fail/issue-22897.rs rename to src/test/ui/type-check/issue-22897.rs index c6bbf2d4abcc0..296dc81a89bcf 100644 --- a/src/test/compile-fail/issue-22897.rs +++ b/src/test/ui/type-check/issue-22897.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -10,10 +10,6 @@ fn main() { } -// Before these errors would ICE as "cat_expr Errd" because the errors -// were unknown when the bug was triggered. - fn unconstrained_type() { []; - //~^ ERROR cannot determine a type for this expression: unconstrained type } diff --git a/src/test/ui/type-check/issue-22897.stderr b/src/test/ui/type-check/issue-22897.stderr new file mode 100644 index 0000000000000..9568411885192 --- /dev/null +++ b/src/test/ui/type-check/issue-22897.stderr @@ -0,0 +1,8 @@ +error[E0282]: type annotations needed + --> $DIR/issue-22897.rs:14:5 + | +14 | []; + | ^^ cannot infer type for `[_; 0]` + +error: aborting due to previous error + diff --git a/src/test/ui/type-check/issue-38812-2.stderr b/src/test/ui/type-check/issue-38812-2.stderr deleted file mode 100644 index 156a6bdee9979..0000000000000 --- a/src/test/ui/type-check/issue-38812-2.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0282]: type annotations needed - --> $DIR/issue-38812-2.rs:12:17 - | -12 | let (x,) = (vec![],); - | ---- ^^^^^^ cannot infer type for `T` - | | - | consider giving a type to pattern - | - = note: this error originates in a macro outside of the current crate - -error: aborting due to previous error - diff --git a/src/test/compile-fail/E0102.rs b/src/test/ui/type-check/unknown_type_for_closure.rs similarity index 67% rename from src/test/compile-fail/E0102.rs rename to src/test/ui/type-check/unknown_type_for_closure.rs index 6a17ddebd1dc1..f1d357df12c43 100644 --- a/src/test/compile-fail/E0102.rs +++ b/src/test/ui/type-check/unknown_type_for_closure.rs @@ -1,4 +1,4 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -9,8 +9,5 @@ // except according to those terms. fn main() { - let x = []; - //~^ ERROR type annotations needed - //~| NOTE consider giving `x` a type - //~| NOTE cannot infer type for `_` + let x = |_| { }; } diff --git a/src/test/ui/type-check/unknown_type_for_closure.stderr b/src/test/ui/type-check/unknown_type_for_closure.stderr new file mode 100644 index 0000000000000..afbd15ca486bd --- /dev/null +++ b/src/test/ui/type-check/unknown_type_for_closure.stderr @@ -0,0 +1,8 @@ +error[E0282]: type annotations needed + --> $DIR/unknown_type_for_closure.rs:12:14 + | +12 | let x = |_| { }; + | ^ consider giving this closure parameter a type + +error: aborting due to previous error +