]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_typeck/check/mod.rs
Auto merge of #30036 - mitaa:doc_id, r=alexcrichton
[rust.git] / src / librustc_typeck / check / mod.rs
index 5ed6b62e8c3ef46f1edabe56851784779105c8a9..a50213202b82c8cb94905f2ac3c65aa0c5f53683 100644 (file)
 use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv, PathParamMode};
 use check::_match::pat_ctxt;
 use fmt_macros::{Parser, Piece, Position};
-use metadata::cstore::LOCAL_CRATE;
 use middle::astconv_util::prohibit_type_params;
+use middle::cstore::LOCAL_CRATE;
 use middle::def;
 use middle::def_id::DefId;
 use middle::infer;
-use middle::infer::type_variable;
+use middle::infer::{TypeOrigin, type_variable};
 use middle::pat_util::{self, pat_id_map};
 use middle::privacy::{AllPublic, LastMod};
 use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace};
 use lint;
 use util::common::{block_query, ErrorReported, indenter, loop_query};
 use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
-use util::lev_distance::lev_distance;
 
 use std::cell::{Cell, Ref, RefCell};
 use std::collections::{HashSet};
 use syntax::owned_slice::OwnedSlice;
 use syntax::parse::token::{self, InternedString};
 use syntax::ptr::P;
+use syntax::util::lev_distance::lev_distance;
 
-use rustc_front::visit::{self, Visitor};
+use rustc_front::intravisit::{self, Visitor};
 use rustc_front::hir;
 use rustc_front::hir::Visibility;
 use rustc_front::hir::{Item, ItemImpl};
@@ -363,7 +363,7 @@ struct CheckItemBodiesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
 impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> {
     fn visit_item(&mut self, i: &'tcx hir::Item) {
         check_item_type(self.ccx, i);
-        visit::walk_item(self, i);
+        intravisit::walk_item(self, i);
     }
 
     fn visit_ty(&mut self, t: &'tcx hir::Ty) {
@@ -371,22 +371,16 @@ fn visit_ty(&mut self, t: &'tcx hir::Ty) {
             hir::TyFixedLengthVec(_, ref expr) => {
                 check_const_in_type(self.ccx, &**expr, self.ccx.tcx.types.usize);
             }
-            hir::TyBareFn(ref function_declaration) => {
-                visit::walk_fn_decl_nopat(self, &function_declaration.decl);
-                walk_list!(self, visit_lifetime_def, &function_declaration.lifetimes);
-                return
-            }
             _ => {}
         }
 
-        visit::walk_ty(self, t);
+        intravisit::walk_ty(self, t);
     }
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> {
     fn visit_item(&mut self, i: &'tcx hir::Item) {
         check_item_body(self.ccx, i);
-        visit::walk_item(self, i);
     }
 }
 
@@ -398,7 +392,7 @@ pub fn check_wf_old(ccx: &CrateCtxt) {
     // comes, we run the new code and issue warnings.
     let krate = ccx.tcx.map.krate();
     let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx);
-    visit::walk_crate(&mut visit, krate);
+    krate.visit_all_items(&mut visit);
 
     // If types are not well-formed, it leads to all manner of errors
     // downstream, so stop reporting errors at this point.
@@ -408,7 +402,7 @@ pub fn check_wf_old(ccx: &CrateCtxt) {
 pub fn check_wf_new(ccx: &CrateCtxt) {
     let krate = ccx.tcx.map.krate();
     let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(ccx);
-    visit::walk_crate(&mut visit, krate);
+    krate.visit_all_items(&mut visit);
 
     // If types are not well-formed, it leads to all manner of errors
     // downstream, so stop reporting errors at this point.
@@ -418,14 +412,14 @@ pub fn check_wf_new(ccx: &CrateCtxt) {
 pub fn check_item_types(ccx: &CrateCtxt) {
     let krate = ccx.tcx.map.krate();
     let mut visit = CheckItemTypesVisitor { ccx: ccx };
-    visit::walk_crate(&mut visit, krate);
+    krate.visit_all_items(&mut visit);
     ccx.tcx.sess.abort_if_errors();
 }
 
 pub fn check_item_bodies(ccx: &CrateCtxt) {
     let krate = ccx.tcx.map.krate();
     let mut visit = CheckItemBodiesVisitor { ccx: ccx };
-    visit::walk_crate(&mut visit, krate);
+    krate.visit_all_items(&mut visit);
 
     ccx.tcx.sess.abort_if_errors();
 }
@@ -523,7 +517,7 @@ fn visit_local(&mut self, local: &'tcx hir::Local) {
                local.pat,
                self.fcx.infcx().ty_to_string(
                    self.fcx.inh.locals.borrow().get(&local.id).unwrap().clone()));
-        visit::walk_local(self, local);
+        intravisit::walk_local(self, local);
     }
 
     // Add pattern bindings.
@@ -542,14 +536,14 @@ fn visit_pat(&mut self, p: &'tcx hir::Pat) {
                        var_ty);
             }
         }
-        visit::walk_pat(self, p);
+        intravisit::walk_pat(self, p);
     }
 
     fn visit_block(&mut self, b: &'tcx hir::Block) {
         // non-obvious: the `blk` variable maps to region lb, so
         // we have to keep this up-to-date.  This
         // is... unfortunate.  It'd be nice to not need this.
-        visit::walk_block(self, b);
+        intravisit::walk_block(self, b);
     }
 
     // Since an expr occurs as part of the type fixed size arrays we
@@ -561,18 +555,16 @@ fn visit_ty(&mut self, t: &'tcx hir::Ty) {
                 check_expr_with_hint(self.fcx, &**count_expr, self.fcx.tcx().types.usize);
             }
             hir::TyBareFn(ref function_declaration) => {
-                visit::walk_fn_decl_nopat(self, &function_declaration.decl);
+                intravisit::walk_fn_decl_nopat(self, &function_declaration.decl);
                 walk_list!(self, visit_lifetime_def, &function_declaration.lifetimes);
             }
-            _ => visit::walk_ty(self, t)
+            _ => intravisit::walk_ty(self, t)
         }
     }
 
-    // Don't descend into fns and items
-    fn visit_fn(&mut self, _: visit::FnKind<'tcx>, _: &'tcx hir::FnDecl,
+    // Don't descend into the bodies of nested closures
+    fn visit_fn(&mut self, _: intravisit::FnKind<'tcx>, _: &'tcx hir::FnDecl,
                 _: &'tcx hir::Block, _: Span, _: ast::NodeId) { }
-    fn visit_item(&mut self, _: &hir::Item) { }
-
 }
 
 /// Helper used by check_bare_fn and check_expr_fn. Does the grungy work of checking a function
@@ -712,18 +704,18 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
       hir::ItemStruct(..) => {
         check_struct(ccx, it.id, it.span);
       }
-      hir::ItemTy(ref t, ref generics) => {
+      hir::ItemTy(_, ref generics) => {
         let pty_ty = ccx.tcx.node_id_to_type(it.id);
-        check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
+        check_bounds_are_used(ccx, &generics.ty_params, pty_ty);
       }
       hir::ItemForeignMod(ref m) => {
         if m.abi == abi::RustIntrinsic {
             for item in &m.items {
-                intrinsic::check_intrinsic_type(ccx, &**item);
+                intrinsic::check_intrinsic_type(ccx, item);
             }
         } else if m.abi == abi::PlatformIntrinsic {
             for item in &m.items {
-                intrinsic::check_platform_intrinsic_type(ccx, &**item);
+                intrinsic::check_platform_intrinsic_type(ccx, item);
             }
         } else {
             for item in &m.items {
@@ -888,7 +880,7 @@ fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                             impl_span: Span,
                                             impl_trait_ref: &ty::TraitRef<'tcx>,
-                                            impl_items: &[P<hir::ImplItem>]) {
+                                            impl_items: &[hir::ImplItem]) {
     // Locate trait methods
     let tcx = ccx.tcx;
     let trait_items = tcx.trait_items(impl_trait_ref.def_id);
@@ -1454,7 +1446,7 @@ pub fn def_struct_variant(&self,
                               -> Option<(ty::AdtDef<'tcx>, ty::VariantDef<'tcx>)>
     {
         let (adt, variant) = match def {
-            def::DefVariant(enum_id, variant_id, true) => {
+            def::DefVariant(enum_id, variant_id, _) => {
                 let adt = self.tcx().lookup_adt_def(enum_id);
                 (adt, adt.variant_with_id(variant_id))
             }
@@ -1618,7 +1610,7 @@ pub fn opt_node_ty_substs<F>(&self,
 
     pub fn mk_subty(&self,
                     a_is_expected: bool,
-                    origin: infer::TypeOrigin,
+                    origin: TypeOrigin,
                     sub: Ty<'tcx>,
                     sup: Ty<'tcx>)
                     -> Result<(), TypeError<'tcx>> {
@@ -1627,7 +1619,7 @@ pub fn mk_subty(&self,
 
     pub fn mk_eqty(&self,
                    a_is_expected: bool,
-                   origin: infer::TypeOrigin,
+                   origin: TypeOrigin,
                    sub: Ty<'tcx>,
                    sup: Ty<'tcx>)
                    -> Result<(), TypeError<'tcx>> {
@@ -1905,7 +1897,7 @@ fn new_select_all_obligations_and_apply_defaults(&self) {
                                 if let Some(default) = default_map.get(ty) {
                                     let default = default.clone();
                                     match infer::mk_eqty(self.infcx(), false,
-                                                         infer::Misc(default.origin_span),
+                                                         TypeOrigin::Misc(default.origin_span),
                                                          ty, default.ty) {
                                         Ok(()) => {}
                                         Err(_) => {
@@ -1998,7 +1990,7 @@ fn find_conflicting_default(&self,
                         if let Some(default) = default_map.get(ty) {
                             let default = default.clone();
                             match infer::mk_eqty(self.infcx(), false,
-                                                 infer::Misc(default.origin_span),
+                                                 TypeOrigin::Misc(default.origin_span),
                                                  ty, default.ty) {
                                 Ok(()) => {}
                                 Err(_) => {
@@ -2498,6 +2490,8 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // of arguments when we typecheck the functions. This isn't really the
     // right way to do this.
     let xs = [false, true];
+    let mut any_diverges = false; // has any of the arguments diverged?
+    let mut warned = false; // have we already warned about unreachable code?
     for check_blocks in &xs {
         let check_blocks = *check_blocks;
         debug!("check_blocks={}", check_blocks);
@@ -2520,6 +2514,16 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             supplied_arg_count
         };
         for (i, arg) in args.iter().take(t).enumerate() {
+            if any_diverges && !warned {
+                fcx.ccx
+                    .tcx
+                    .sess
+                    .add_lint(lint::builtin::UNREACHABLE_CODE,
+                              arg.id,
+                              arg.span,
+                              "unreachable expression".to_string());
+                warned = true;
+            }
             let is_block = match arg.node {
                 hir::ExprClosure(..) => true,
                 _ => false
@@ -2550,7 +2554,23 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                     coerce_ty.map(|ty| demand::suptype(fcx, arg.span, formal_ty, ty));
                 });
             }
+
+            if let Some(&arg_ty) = fcx.inh.tables.borrow().node_types.get(&arg.id) {
+                any_diverges = any_diverges || fcx.infcx().type_var_diverges(arg_ty);
+            }
+        }
+        if any_diverges && !warned {
+            let parent = fcx.ccx.tcx.map.get_parent_node(args[0].id);
+            fcx.ccx
+                .tcx
+                .sess
+                .add_lint(lint::builtin::UNREACHABLE_CODE,
+                          parent,
+                          sp,
+                          "unreachable call".to_string());
+            warned = true;
         }
+
     }
 
     // We also need to make sure we at least write the ty of the other
@@ -2764,7 +2784,7 @@ fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 // return type (likely containing type variables if the function
                 // is polymorphic) and the expected return type.
                 // No argument expectations are produced if unification fails.
-                let origin = infer::Misc(call_span);
+                let origin = TypeOrigin::Misc(call_span);
                 let ures = fcx.infcx().sub_types(false, origin, formal_ret_ty, ret_ty);
                 // FIXME(#15760) can't use try! here, FromError doesn't default
                 // to identity so the resulting type is not constrained.
@@ -2878,14 +2898,14 @@ fn check_then_else<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 check_expr_with_expectation(fcx, &**else_expr, expected);
                 let else_ty = fcx.expr_ty(&**else_expr);
                 infer::common_supertype(fcx.infcx(),
-                                        infer::IfExpression(sp),
+                                        TypeOrigin::IfExpression(sp),
                                         true,
                                         then_ty,
                                         else_ty)
             }
             None => {
                 infer::common_supertype(fcx.infcx(),
-                                        infer::IfExpressionWithNoElse(sp),
+                                        TypeOrigin::IfExpressionWithNoElse(sp),
                                         false,
                                         then_ty,
                                         fcx.tcx().mk_nil())
@@ -3385,7 +3405,7 @@ fn check_expr_struct<'a, 'tcx>(fcx: &FnCtxt<'a,'tcx>,
             ty::FnConverging(result_type) => {
                 match *expr_opt {
                     None =>
-                        if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
+                        if let Err(_) = fcx.mk_eqty(false, TypeOrigin::Misc(expr.span),
                                                     result_type, fcx.tcx().mk_nil()) {
                             span_err!(tcx.sess, expr.span, E0069,
                                 "`return;` in a function whose return type is \
@@ -3669,7 +3689,7 @@ fn check_expr_struct<'a, 'tcx>(fcx: &FnCtxt<'a,'tcx>,
               }
               (Some(t_start), Some(t_end)) => {
                   Some(infer::common_supertype(fcx.infcx(),
-                                               infer::RangeExpression(expr.span),
+                                               TypeOrigin::RangeExpression(expr.span),
                                                true,
                                                t_start,
                                                t_end))
@@ -4004,8 +4024,8 @@ fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     let mut any_diverges = false;
     let mut any_err = false;
     for s in &blk.stmts {
-        check_stmt(fcx, &**s);
-        let s_id = ::rustc_front::util::stmt_id(&**s);
+        check_stmt(fcx, s);
+        let s_id = ::rustc_front::util::stmt_id(s);
         let s_ty = fcx.node_ty(s_id);
         if any_diverges && !warned && match s.node {
             hir::StmtDecl(ref decl, _) => {
@@ -4173,7 +4193,7 @@ pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
 
 pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                                     sp: Span,
-                                    vs: &'tcx [P<hir::Variant>],
+                                    vs: &'tcx [hir::Variant],
                                     id: ast::NodeId) {
 
     fn disr_in_range(ccx: &CrateCtxt,
@@ -4204,7 +4224,7 @@ fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
     }
 
     fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                          vs: &'tcx [P<hir::Variant>],
+                          vs: &'tcx [hir::Variant],
                           id: ast::NodeId,
                           hint: attr::ReprAttr) {
         #![allow(trivial_numeric_casts)]
@@ -4565,7 +4585,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                    impl_scheme.generics.regions.len(subst::TypeSpace));
 
         let impl_ty = fcx.instantiate_type_scheme(span, &substs, &impl_scheme.ty);
-        if fcx.mk_subty(false, infer::Misc(span), self_ty, impl_ty).is_err() {
+        if fcx.mk_subty(false, TypeOrigin::Misc(span), self_ty, impl_ty).is_err() {
             fcx.tcx().sess.span_bug(span,
             &format!(
                 "instantiate_path: (UFCS) {:?} was a subtype of {:?} but now is not?",
@@ -4884,7 +4904,6 @@ pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &hir::Block) -> bool {
 }
 
 pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                                       span: Span,
                                        tps: &OwnedSlice<hir::TyParam>,
                                        ty: Ty<'tcx>) {
     debug!("check_bounds_are_used(n_tps={}, ty={:?})",
@@ -4903,7 +4922,7 @@ pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
     for (i, b) in tps_used.iter().enumerate() {
         if !*b {
-            span_err!(ccx.tcx.sess, span, E0091,
+            span_err!(ccx.tcx.sess, tps[i].span, E0091,
                 "type parameter `{}` is unused",
                 tps[i].name);
         }