]> 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 a635c1b047da3474d38928820c8bf08bf2c0c1cc..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::intravisit::{self, Visitor};
 use rustc_front::hir;
@@ -704,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 {
@@ -880,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);
@@ -1446,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))
             }
@@ -1610,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>> {
@@ -1619,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>> {
@@ -1897,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(_) => {
@@ -1990,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(_) => {
@@ -2490,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);
@@ -2512,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
@@ -2542,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
@@ -2756,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.
@@ -2870,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())
@@ -3377,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 \
@@ -3661,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))
@@ -3996,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, _) => {
@@ -4165,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,
@@ -4196,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)]
@@ -4557,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?",
@@ -4876,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={:?})",
@@ -4895,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);
         }