]> git.lizzy.rs Git - rust.git/commitdiff
fixes #40013
authorCengiz Can <canc@thoughtworks.com>
Tue, 11 Apr 2017 21:37:40 +0000 (00:37 +0300)
committerCengiz Can <canc@thoughtworks.com>
Tue, 18 Apr 2017 18:43:22 +0000 (21:43 +0300)
21 files changed:
src/librustc/diagnostics.rs
src/librustc/traits/error_reporting.rs
src/librustc_typeck/check/writeback.rs
src/librustc_typeck/diagnostics.rs
src/test/compile-fail/E0101.rs [deleted file]
src/test/compile-fail/E0102.rs [deleted file]
src/test/compile-fail/issue-22897.rs [deleted file]
src/test/ui/type-check/cannot_infer_local_or_array.rs [new file with mode: 0644]
src/test/ui/type-check/cannot_infer_local_or_array.stderr [new file with mode: 0644]
src/test/ui/type-check/cannot_infer_local_or_vec.rs [new file with mode: 0644]
src/test/ui/type-check/cannot_infer_local_or_vec.stderr [new file with mode: 0644]
src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.rs [new file with mode: 0644]
src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr [new file with mode: 0644]
src/test/ui/type-check/issue-22897.rs [new file with mode: 0644]
src/test/ui/type-check/issue-22897.stderr [new file with mode: 0644]
src/test/ui/type-check/issue-38812-2.rs [deleted file]
src/test/ui/type-check/issue-38812-2.stderr [deleted file]
src/test/ui/type-check/issue-38812.rs [deleted file]
src/test/ui/type-check/issue-38812.stderr [deleted file]
src/test/ui/type-check/unknown_type_for_closure.rs [new file with mode: 0644]
src/test/ui/type-check/unknown_type_for_closure.stderr [new file with mode: 0644]

index 8a391f9cde3a3a37b9dc74dddd09106617a86292..ec4444ac4e36ff472922a7e6fd3f612c411b91d8 100644 (file)
@@ -1807,6 +1807,58 @@ extern "C" fn foo(userdata: Box<i32>) {
 [rfc401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
 "##,
 
+/*
+
+E0101: r##"
+#### Note: this error code is no longer emitted by the compiler.
+
+You hit this error because the compiler lacks the information to
+determine a type for this expression. Erroneous code example:
+
+```ignore
+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##"
+#### Note: this error code is no longer emitted by the compiler.
+
+You hit this error because the compiler lacks the information to
+determine the type of this variable. Erroneous code example:
+
+```ignore
+// 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] = [];
+}
+```
+"##,
+
+*/
+
 }
 
 
index f7a7d0e2071f210287dc4b4b6c575866146e1f21..8a8a5ef3e3afb1092b3bf9fe483add6f5beea7bd 100644 (file)
@@ -25,7 +25,7 @@
 
 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::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 @@ fn from_error(infcx: &InferCtxt<'a, 'gcx, '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 @@ fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'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 @@ fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'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 @@ fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'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 @@ fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'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 @@ fn extract_type_name(&self, ty: &'a Ty<'tcx>) -> String {
         }
     }
 
-    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();
     }
 
index 7fffbd14e216056b71596c1a95ec092d9c31a1a7..f196aa82b1ef3ebc7a76da218e2a1de2b5b52e68 100644 (file)
 // 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 @@ pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body)
         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 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
     }
 
     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 @@ fn visit_expr(&mut self, e: &'gcx hir::Expr) {
     }
 
     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 @@ fn visit_upvar_borrow_map(&mut self) {
                 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 @@ fn visit_upvar_borrow_map(&mut self) {
 
     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 @@ fn visit_free_region_map(&mut self) {
     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 @@ fn visit_anon_types(&mut self) {
                     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 @@ fn visit_anon_types(&mut self) {
 
                     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 @@ fn visit_anon_types(&mut self) {
         }
     }
 
-    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 @@ fn visit_adjustments(&mut self, reason: ResolveReason, id: ast::NodeId) {
 
                     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 @@ fn visit_method_map_entry(&mut self,
                        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 @@ fn visit_method_map_entry(&mut self,
 
     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) }
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -505,82 +480,25 @@ fn span(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Span {
 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 @@ fn tcx<'a>(&'a self) -> TyCtxt<'a, '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)
             }
         }
index 2d72052f1e5ad6b4bf4e807671c74c64fcd9e36e..36094d6a8f6b19639969efa72969e6b0db7b38f2 100644 (file)
@@ -1351,50 +1351,6 @@ fn main() {
 ```
 "##,
 
-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,6 @@ fn main() { }
 //  E0068,
 //  E0085,
 //  E0086,
-    E0103, // @GuillaumeGomez: I was unable to get this error, try your best!
-    E0104,
 //  E0123,
 //  E0127,
 //  E0129,
@@ -4164,7 +4118,7 @@ fn main() { }
 //  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 // @cengizIO: this is no longer thrown. should I DELETE THIS?
     E0203, // type parameter has more than one relaxed default bound,
            // and only one is supported
     E0208,
diff --git a/src/test/compile-fail/E0101.rs b/src/test/compile-fail/E0101.rs
deleted file mode 100644 (file)
index 0005da0..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2016 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 main() {
-    let x = |_| {};
-    //~^ ERROR E0101
-    //~| NOTE cannot resolve type of expression
-}
diff --git a/src/test/compile-fail/E0102.rs b/src/test/compile-fail/E0102.rs
deleted file mode 100644 (file)
index 6a17dde..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2016 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 main() {
-    let x = [];
-    //~^ ERROR type annotations needed
-    //~| NOTE consider giving `x` a type
-    //~| NOTE cannot infer type for `_`
-}
diff --git a/src/test/compile-fail/issue-22897.rs b/src/test/compile-fail/issue-22897.rs
deleted file mode 100644 (file)
index c6bbf2d..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2015 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 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/cannot_infer_local_or_array.rs b/src/test/ui/type-check/cannot_infer_local_or_array.rs
new file mode 100644 (file)
index 0000000..0b35a9c
--- /dev/null
@@ -0,0 +1,13 @@
+// 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.
+//
+// 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 main() {
+    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 (file)
index 0000000..8c52bb5
--- /dev/null
@@ -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/cannot_infer_local_or_vec.rs b/src/test/ui/type-check/cannot_infer_local_or_vec.rs
new file mode 100644 (file)
index 0000000..a9943f7
--- /dev/null
@@ -0,0 +1,13 @@
+// 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.
+//
+// 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 main() {
+    let x = vec![];
+}
diff --git a/src/test/ui/type-check/cannot_infer_local_or_vec.stderr b/src/test/ui/type-check/cannot_infer_local_or_vec.stderr
new file mode 100644 (file)
index 0000000..4788fad
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0282]: type annotations needed
+  --> $DIR/cannot_infer_local_or_vec.rs:12:13
+   |
+12 |     let x = vec![];
+   |         -   ^^^^^^ cannot infer type for `T`
+   |         |
+   |         consider giving `x` 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/ui/type-check/cannot_infer_local_or_vec_in_tuples.rs b/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.rs
new file mode 100644 (file)
index 0000000..8d32c1f
--- /dev/null
@@ -0,0 +1,13 @@
+// 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.
+//
+// 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 main() {
+    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 (file)
index 0000000..3431a1d
--- /dev/null
@@ -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 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/ui/type-check/issue-22897.rs b/src/test/ui/type-check/issue-22897.rs
new file mode 100644 (file)
index 0000000..296dc81
--- /dev/null
@@ -0,0 +1,15 @@
+// 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.
+//
+// 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 main() { }
+
+fn 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 (file)
index 0000000..9568411
--- /dev/null
@@ -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.rs b/src/test/ui/type-check/issue-38812-2.rs
deleted file mode 100644 (file)
index c476657..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// 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.
-//
-// 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 main() {
-    let (x,) = (vec![],);
-}
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 (file)
index 156a6bd..0000000
+++ /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/ui/type-check/issue-38812.rs b/src/test/ui/type-check/issue-38812.rs
deleted file mode 100644 (file)
index a9943f7..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// 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.
-//
-// 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 main() {
-    let x = vec![];
-}
diff --git a/src/test/ui/type-check/issue-38812.stderr b/src/test/ui/type-check/issue-38812.stderr
deleted file mode 100644 (file)
index 6365e76..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0282]: type annotations needed
-  --> $DIR/issue-38812.rs:12:13
-   |
-12 |     let x = vec![];
-   |         -   ^^^^^^ cannot infer type for `T`
-   |         |
-   |         consider giving `x` 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/ui/type-check/unknown_type_for_closure.rs b/src/test/ui/type-check/unknown_type_for_closure.rs
new file mode 100644 (file)
index 0000000..f1d357d
--- /dev/null
@@ -0,0 +1,13 @@
+// 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.
+//
+// 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 main() {
+    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 (file)
index 0000000..afbd15c
--- /dev/null
@@ -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
+