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;
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;
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);
}
}
// 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,
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);
// 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);
}
}
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);
}
}
}
}
- 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 a type to pattern")));
}
}
+ 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();
}
// 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
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();
// 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.
}
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);
}
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);
}
}
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 })
}
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);
}
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.
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);
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);
}
}
}
}
- 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) => {
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) {
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)
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<T>(&self, x: &T, reason: ResolveReason) -> T::Lifted
+ fn resolve<T>(&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) }
}
///////////////////////////////////////////////////////////////////////////
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);
}
}
}
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)
}
}