]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_lint/types.rs
Fix rebase fallout.
[rust.git] / src / librustc_lint / types.rs
index f2ad400d5dd377f0b96368a3b8be96f7c0ef020c..9a4e981081fcfcd309411795bc7370dfc324e101 100644 (file)
@@ -4,7 +4,7 @@
 use crate::hir::def_id::DefId;
 use rustc::hir::lowering::is_range_literal;
 use rustc::ty::subst::SubstsRef;
-use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt, TypeFoldable};
+use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
 use rustc::ty::layout::{self, IntegerExt, LayoutOf, VariantIdx, SizeSkeleton};
 use rustc::{lint, util};
 use rustc_index::vec::Idx;
@@ -68,7 +68,7 @@ fn lint_overflowing_range_endpoint<'a, 'tcx>(
     max: u128,
     expr: &'tcx hir::Expr,
     parent_expr: &'tcx hir::Expr,
-    ty: impl std::fmt::Debug,
+    ty: &str,
 ) -> bool {
     // We only want to handle exclusive (`..`) ranges,
     // which are represented as `ExprKind::Struct`.
@@ -83,15 +83,15 @@ fn lint_overflowing_range_endpoint<'a, 'tcx>(
             let mut err = cx.struct_span_lint(
                 OVERFLOWING_LITERALS,
                 parent_expr.span,
-                &format!("range endpoint is out of range for `{:?}`", ty),
+                &format!("range endpoint is out of range for `{}`", ty),
             );
             if let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) {
                 use ast::{LitKind, LitIntType};
                 // We need to preserve the literal's suffix,
                 // as it may determine typing information.
                 let suffix = match lit.node {
-                    LitKind::Int(_, LitIntType::Signed(s)) => format!("{}", s),
-                    LitKind::Int(_, LitIntType::Unsigned(s)) => format!("{}", s),
+                    LitKind::Int(_, LitIntType::Signed(s)) => format!("{}", s.name_str()),
+                    LitKind::Int(_, LitIntType::Unsigned(s)) => format!("{}", s.name_str()),
                     LitKind::Int(_, LitIntType::Unsuffixed) => "".to_owned(),
                     _ => bug!(),
                 };
@@ -161,11 +161,11 @@ fn report_bin_hex_error(
     let (t, actually) = match ty {
         attr::IntType::SignedInt(t) => {
             let actually = sign_extend(val, size) as i128;
-            (format!("{:?}", t), actually.to_string())
+            (t.name_str(), actually.to_string())
         }
         attr::IntType::UnsignedInt(t) => {
             let actually = truncate(val, size);
-            (format!("{:?}", t), actually.to_string())
+            (t.name_str(), actually.to_string())
         }
     };
     let mut err = cx.struct_span_lint(
@@ -204,7 +204,7 @@ fn report_bin_hex_error(
 //  - `uX` => `uY`
 //
 // No suggestion for: `isize`, `usize`.
-fn get_type_suggestion(t: Ty<'_>, val: u128, negative: bool) -> Option<String> {
+fn get_type_suggestion(t: Ty<'_>, val: u128, negative: bool) -> Option<&'static str> {
     use syntax::ast::IntTy::*;
     use syntax::ast::UintTy::*;
     macro_rules! find_fit {
@@ -215,10 +215,10 @@ macro_rules! find_fit {
                 match $ty {
                     $($type => {
                         $(if !negative && val <= uint_ty_range($utypes).1 {
-                            return Some(format!("{:?}", $utypes))
+                            return Some($utypes.name_str())
                         })*
                         $(if val <= int_ty_range($itypes).1 as u128 + _neg {
-                            return Some(format!("{:?}", $itypes))
+                            return Some($itypes.name_str())
                         })*
                         None
                     },)+
@@ -281,7 +281,7 @@ fn lint_int_literal<'a, 'tcx>(
         if let Node::Expr(par_e) = cx.tcx.hir().get(par_id) {
             if let hir::ExprKind::Struct(..) = par_e.kind {
                 if is_range_literal(cx.sess(), par_e)
-                    && lint_overflowing_range_endpoint(cx, lit, v, max, e, par_e, t)
+                    && lint_overflowing_range_endpoint(cx, lit, v, max, e, par_e, t.name_str())
                 {
                     // The overflowing literal lint was overridden.
                     return;
@@ -292,7 +292,7 @@ fn lint_int_literal<'a, 'tcx>(
         cx.span_lint(
             OVERFLOWING_LITERALS,
             e.span,
-            &format!("literal out of range for `{:?}`", t),
+            &format!("literal out of range for `{}`", t.name_str()),
         );
     }
 }
@@ -338,6 +338,7 @@ fn lint_uint_literal<'a, 'tcx>(
                 }
                 hir::ExprKind::Struct(..)
                     if is_range_literal(cx.sess(), par_e) => {
+                        let t = t.name_str();
                         if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, par_e, t) {
                             // The overflowing literal lint was overridden.
                             return;
@@ -353,7 +354,7 @@ fn lint_uint_literal<'a, 'tcx>(
         cx.span_lint(
             OVERFLOWING_LITERALS,
             e.span,
-            &format!("literal out of range for `{:?}`", t),
+            &format!("literal out of range for `{}`", t.name_str()),
         );
     }
 }
@@ -379,8 +380,7 @@ fn lint_literal<'a, 'tcx>(
         }
         ty::Float(t) => {
             let is_infinite = match lit.node {
-                ast::LitKind::Float(v, _) |
-                ast::LitKind::FloatUnsuffixed(v) => {
+                ast::LitKind::Float(v, _) => {
                     match t {
                         ast::FloatTy::F32 => v.as_str().parse().map(f32::is_infinite),
                         ast::FloatTy::F64 => v.as_str().parse().map(f64::is_infinite),
@@ -389,9 +389,11 @@ fn lint_literal<'a, 'tcx>(
                 _ => bug!(),
             };
             if is_infinite == Ok(true) {
-                cx.span_lint(OVERFLOWING_LITERALS,
-                             e.span,
-                             &format!("literal out of range for `{:?}`", t));
+                cx.span_lint(
+                    OVERFLOWING_LITERALS,
+                    e.span,
+                    &format!("literal out of range for `{}`", t.name_str()),
+                );
             }
         }
         _ => {}
@@ -835,13 +837,16 @@ fn check_type_for_ffi(&self,
             ty::Array(ty, _) => self.check_type_for_ffi(cache, ty),
 
             ty::FnPtr(sig) => {
-                if self.is_internal_abi(sig.abi()) {
-                    return FfiUnsafe {
-                        ty,
-                        reason: "this function pointer has Rust-specific calling convention",
-                        help: Some("consider using an `extern fn(...) -> ...` \
-                                    function pointer instead"),
-                    };
+                match sig.abi() {
+                    Abi::Rust | Abi::RustIntrinsic | Abi::PlatformIntrinsic | Abi::RustCall => {
+                        return FfiUnsafe {
+                            ty,
+                            reason: "this function pointer has Rust-specific calling convention",
+                            help: Some("consider using an `extern fn(...) -> ...` \
+                                        function pointer instead"),
+                        }
+                    }
+                    _ => {}
                 }
 
                 let sig = cx.erase_late_bound_regions(&sig);
@@ -868,10 +873,7 @@ fn check_type_for_ffi(&self,
 
             ty::Foreign(..) => FfiSafe,
 
-            // `extern "C" fn` functions can have type parameters, which may or may not be FFI-safe,
-            //  so they are currently ignored for the purposes of this lint, see #65134.
-            ty::Param(..) | ty::Projection(..) => FfiSafe,
-
+            ty::Param(..) |
             ty::Infer(..) |
             ty::Bound(..) |
             ty::Error |
@@ -880,6 +882,7 @@ fn check_type_for_ffi(&self,
             ty::GeneratorWitness(..) |
             ty::Placeholder(..) |
             ty::UnnormalizedProjection(..) |
+            ty::Projection(..) |
             ty::Opaque(..) |
             ty::FnDef(..) => bug!("unexpected type in foreign function: {:?}", ty),
         }
@@ -891,16 +894,11 @@ fn emit_ffi_unsafe_type_lint(
         sp: Span,
         note: &str,
         help: Option<&str>,
-        is_foreign_item: bool,
     ) {
         let mut diag = self.cx.struct_span_lint(
             IMPROPER_CTYPES,
             sp,
-            &format!(
-                "`extern` {} uses type `{}`, which is not FFI-safe",
-                if is_foreign_item { "block" } else { "fn" },
-                ty,
-            ),
+            &format!("`extern` block uses type `{}`, which is not FFI-safe", ty),
         );
         diag.span_label(sp, "not FFI-safe");
         if let Some(help) = help {
@@ -915,7 +913,9 @@ fn emit_ffi_unsafe_type_lint(
         diag.emit();
     }
 
-    fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>, is_foreign_item: bool) -> bool {
+    fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool {
+        use crate::rustc::ty::TypeFoldable;
+
         struct ProhibitOpaqueTypes<'tcx> {
             ty: Option<Ty<'tcx>>,
         };
@@ -939,7 +939,6 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
                 sp,
                 "opaque types have no C equivalent",
                 None,
-                is_foreign_item,
             );
             true
         } else {
@@ -947,46 +946,42 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
         }
     }
 
-    fn check_type_for_ffi_and_report_errors(
-        &mut self,
-        sp: Span,
-        ty: Ty<'tcx>,
-        is_foreign_item: bool,
-    ) {
+    fn check_type_for_ffi_and_report_errors(&mut self, sp: Span, ty: Ty<'tcx>) {
         // We have to check for opaque types before `normalize_erasing_regions`,
         // which will replace opaque types with their underlying concrete type.
-        if self.check_for_opaque_ty(sp, ty, is_foreign_item) {
+        if self.check_for_opaque_ty(sp, ty) {
             // We've already emitted an error due to an opaque type.
             return;
         }
 
-        let ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, ty);
+        // it is only OK to use this function because extern fns cannot have
+        // any generic types right now:
+        let ty = self.cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
+
         match self.check_type_for_ffi(&mut FxHashSet::default(), ty) {
             FfiResult::FfiSafe => {}
             FfiResult::FfiPhantom(ty) => {
-                self.emit_ffi_unsafe_type_lint(
-                    ty, sp, "composed only of `PhantomData`", None, is_foreign_item);
+                self.emit_ffi_unsafe_type_lint(ty, sp, "composed only of `PhantomData`", None);
             }
             FfiResult::FfiUnsafe { ty, reason, help } => {
-                self.emit_ffi_unsafe_type_lint(
-                    ty, sp, reason, help, is_foreign_item);
+                self.emit_ffi_unsafe_type_lint(ty, sp, reason, help);
             }
         }
     }
 
-    fn check_foreign_fn(&mut self, id: hir::HirId, decl: &hir::FnDecl, is_foreign_item: bool) {
+    fn check_foreign_fn(&mut self, id: hir::HirId, decl: &hir::FnDecl) {
         let def_id = self.cx.tcx.hir().local_def_id(id);
         let sig = self.cx.tcx.fn_sig(def_id);
         let sig = self.cx.tcx.erase_late_bound_regions(&sig);
 
         for (input_ty, input_hir) in sig.inputs().iter().zip(&decl.inputs) {
-            self.check_type_for_ffi_and_report_errors(input_hir.span, input_ty, is_foreign_item);
+            self.check_type_for_ffi_and_report_errors(input_hir.span, input_ty);
         }
 
         if let hir::Return(ref ret_hir) = decl.output {
             let ret_ty = sig.output();
             if !ret_ty.is_unit() {
-                self.check_type_for_ffi_and_report_errors(ret_hir.span, ret_ty, is_foreign_item);
+                self.check_type_for_ffi_and_report_errors(ret_hir.span, ret_ty);
             }
         }
     }
@@ -994,15 +989,7 @@ fn check_foreign_fn(&mut self, id: hir::HirId, decl: &hir::FnDecl, is_foreign_it
     fn check_foreign_static(&mut self, id: hir::HirId, span: Span) {
         let def_id = self.cx.tcx.hir().local_def_id(id);
         let ty = self.cx.tcx.type_of(def_id);
-        self.check_type_for_ffi_and_report_errors(span, ty, true);
-    }
-
-    fn is_internal_abi(&self, abi: Abi) -> bool {
-        if let Abi::Rust | Abi::RustCall | Abi::RustIntrinsic | Abi::PlatformIntrinsic = abi {
-            true
-        } else {
-            false
-        }
+        self.check_type_for_ffi_and_report_errors(span, ty);
     }
 }
 
@@ -1010,10 +997,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypes {
     fn check_foreign_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::ForeignItem) {
         let mut vis = ImproperCTypesVisitor { cx };
         let abi = cx.tcx.hir().get_foreign_abi(it.hir_id);
-        if !vis.is_internal_abi(abi) {
+        if let Abi::Rust | Abi::RustCall | Abi::RustIntrinsic | Abi::PlatformIntrinsic = abi {
+            // Don't worry about types in internal ABIs.
+        } else {
             match it.kind {
                 hir::ForeignItemKind::Fn(ref decl, _, _) => {
-                    vis.check_foreign_fn(it.hir_id, decl, true);
+                    vis.check_foreign_fn(it.hir_id, decl);
                 }
                 hir::ForeignItemKind::Static(ref ty, _) => {
                     vis.check_foreign_static(it.hir_id, ty.span);
@@ -1022,29 +1011,6 @@ fn check_foreign_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::ForeignItem
             }
         }
     }
-
-    fn check_fn(
-        &mut self,
-        cx: &LateContext<'a, 'tcx>,
-        kind: hir::intravisit::FnKind<'tcx>,
-        decl: &'tcx hir::FnDecl,
-        _: &'tcx hir::Body,
-        _: Span,
-        hir_id: hir::HirId,
-    ) {
-        use hir::intravisit::FnKind;
-
-        let abi = match kind {
-            FnKind::ItemFn(_, _, header, ..) => (header.abi),
-            FnKind::Method(_, sig, ..) => (sig.header.abi),
-            _ => return,
-        };
-
-        let mut vis = ImproperCTypesVisitor { cx };
-        if !vis.is_internal_abi(abi) {
-            vis.check_foreign_fn(hir_id, decl, false);
-        }
-    }
 }
 
 declare_lint_pass!(VariantSizeDifferences => [VARIANT_SIZE_DIFFERENCES]);