about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-01-03 08:48:05 +0000
committerbors <bors@rust-lang.org>2020-01-03 08:48:05 +0000
commit2e8c3c3e9eb81bc2be047b1d4b2f9f31b869b6f5 (patch)
tree920b722eac49b8415c45fed685b42e80584d2de0
parent304edf39c3ebb6fac9b4db3c8e05fee1bbc1543b (diff)
parentc6aeda7bd52e490148ae34242f09de66d0af9841 (diff)
downloadrust-2e8c3c3e9eb81bc2be047b1d4b2f9f31b869b6f5.tar.gz
rust-2e8c3c3e9eb81bc2be047b1d4b2f9f31b869b6f5.zip
Auto merge of #4975 - JohnTitor:fix-4968, r=phansch
Fix ICE on `unsound_collection_transmute`

Fixes #4968

Check if `Ty`s are normalizable. It might show hidden false negative, I'm not sure.
Also, the regression tests are placed on two dirs, so move them to `/crashes`. I think it will be easier to find the right place.

changelog: Fix ICE on `unsound_collection_transmute`
-rw-r--r--clippy_lints/src/transmute.rs13
-rw-r--r--clippy_lints/src/utils/mod.rs9
-rw-r--r--tests/ui/crashes/auxiliary/use_self_macro.rs15
-rw-r--r--tests/ui/crashes/ice-2636.rs (renamed from tests/ui/ice-2636.rs)0
-rw-r--r--tests/ui/crashes/ice-2636.stderr (renamed from tests/ui/ice-2636.stderr)0
-rw-r--r--tests/ui/crashes/ice-2862.rs (renamed from tests/ui/crashes/issue-2862.rs)2
-rw-r--r--tests/ui/crashes/ice-360.rs (renamed from tests/ui/ice-360.rs)0
-rw-r--r--tests/ui/crashes/ice-360.stderr (renamed from tests/ui/ice-360.stderr)0
-rw-r--r--tests/ui/crashes/ice-3717.rs (renamed from tests/ui/ice-3717.rs)0
-rw-r--r--tests/ui/crashes/ice-3717.stderr (renamed from tests/ui/ice-3717.stderr)0
-rw-r--r--tests/ui/crashes/ice-4121.rs (renamed from tests/ui/ice-4121.rs)0
-rw-r--r--tests/ui/crashes/ice-4545.rs (renamed from tests/ui/ice-4545.rs)0
-rw-r--r--tests/ui/crashes/ice-4579.rs (renamed from tests/ui/ice-4579.rs)0
-rw-r--r--tests/ui/crashes/ice-4671.rs (renamed from tests/ui/ice-4671.rs)0
-rw-r--r--tests/ui/crashes/ice-4775.rs (renamed from tests/ui/ice-4775.rs)0
-rw-r--r--tests/ui/crashes/ice-4968.rs20
16 files changed, 55 insertions, 4 deletions
diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs
index b4fed7ae812..b6ae611da12 100644
--- a/clippy_lints/src/transmute.rs
+++ b/clippy_lints/src/transmute.rs
@@ -1,4 +1,6 @@
-use crate::utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then, sugg};
+use crate::utils::{
+    is_normalizable, last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then, sugg,
+};
 use if_chain::if_chain;
 use rustc::declare_lint_pass;
 use rustc::hir::*;
@@ -639,8 +641,13 @@ fn get_type_snippet(cx: &LateContext<'_, '_>, path: &QPath<'_>, to_ref_ty: Ty<'_
 // check if the component types of the transmuted collection and the result have different ABI,
 // size or alignment
 fn is_layout_incompatible<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, from: Ty<'tcx>, to: Ty<'tcx>) -> bool {
-    let from_ty_layout = cx.tcx.layout_of(ty::ParamEnv::empty().and(from));
-    let to_ty_layout = cx.tcx.layout_of(ty::ParamEnv::empty().and(to));
+    let empty_param_env = ty::ParamEnv::empty();
+    // check if `from` and `to` are normalizable to avoid ICE (#4968)
+    if !(is_normalizable(cx, empty_param_env, from) && is_normalizable(cx, empty_param_env, to)) {
+        return false;
+    }
+    let from_ty_layout = cx.tcx.layout_of(empty_param_env.and(from));
+    let to_ty_layout = cx.tcx.layout_of(empty_param_env.and(to));
     if let (Ok(from_layout), Ok(to_layout)) = (from_ty_layout, to_ty_layout) {
         from_layout.size != to_layout.size || from_layout.align != to_layout.align || from_layout.abi != to_layout.abi
     } else {
diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs
index ebfa88fabfd..0680f627bbb 100644
--- a/clippy_lints/src/utils/mod.rs
+++ b/clippy_lints/src/utils/mod.rs
@@ -1111,6 +1111,15 @@ pub fn match_function_call<'a, 'tcx>(
     None
 }
 
+/// Checks if `Ty` is normalizable. This function is useful
+/// to avoid crashes on `layout_of`.
+pub fn is_normalizable<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
+    cx.tcx.infer_ctxt().enter(|infcx| {
+        let cause = rustc::traits::ObligationCause::dummy();
+        infcx.at(&cause, param_env).normalize(&ty).is_ok()
+    })
+}
+
 #[cfg(test)]
 mod test {
     use super::{trim_multiline, without_block_comments};
diff --git a/tests/ui/crashes/auxiliary/use_self_macro.rs b/tests/ui/crashes/auxiliary/use_self_macro.rs
new file mode 100644
index 00000000000..a8a85b4baef
--- /dev/null
+++ b/tests/ui/crashes/auxiliary/use_self_macro.rs
@@ -0,0 +1,15 @@
+macro_rules! use_self {
+    (
+        impl $ty:ident {
+            fn func(&$this:ident) {
+                [fields($($field:ident)*)]
+            }
+        }
+    ) => (
+        impl  $ty {
+            fn func(&$this) {
+                let $ty { $($field),* } = $this;
+            }
+        }
+    )
+}
diff --git a/tests/ui/ice-2636.rs b/tests/ui/crashes/ice-2636.rs
index e0b58157590..e0b58157590 100644
--- a/tests/ui/ice-2636.rs
+++ b/tests/ui/crashes/ice-2636.rs
diff --git a/tests/ui/ice-2636.stderr b/tests/ui/crashes/ice-2636.stderr
index aba8be4adcc..aba8be4adcc 100644
--- a/tests/ui/ice-2636.stderr
+++ b/tests/ui/crashes/ice-2636.stderr
diff --git a/tests/ui/crashes/issue-2862.rs b/tests/ui/crashes/ice-2862.rs
index 3587a08eab7..47324ce1831 100644
--- a/tests/ui/crashes/issue-2862.rs
+++ b/tests/ui/crashes/ice-2862.rs
@@ -1,6 +1,6 @@
 // run-pass
 
-/// Test for https://github.com/rust-lang/rust-clippy/issues/2826
+/// Test for https://github.com/rust-lang/rust-clippy/issues/2862
 
 pub trait FooMap {
     fn map<B, F: Fn() -> B>(&self, f: F) -> B;
diff --git a/tests/ui/ice-360.rs b/tests/ui/crashes/ice-360.rs
index 6555c19ca6a..6555c19ca6a 100644
--- a/tests/ui/ice-360.rs
+++ b/tests/ui/crashes/ice-360.rs
diff --git a/tests/ui/ice-360.stderr b/tests/ui/crashes/ice-360.stderr
index 84e31eaf2e9..84e31eaf2e9 100644
--- a/tests/ui/ice-360.stderr
+++ b/tests/ui/crashes/ice-360.stderr
diff --git a/tests/ui/ice-3717.rs b/tests/ui/crashes/ice-3717.rs
index 21c48f4749c..21c48f4749c 100644
--- a/tests/ui/ice-3717.rs
+++ b/tests/ui/crashes/ice-3717.rs
diff --git a/tests/ui/ice-3717.stderr b/tests/ui/crashes/ice-3717.stderr
index 08c53c399c2..08c53c399c2 100644
--- a/tests/ui/ice-3717.stderr
+++ b/tests/ui/crashes/ice-3717.stderr
diff --git a/tests/ui/ice-4121.rs b/tests/ui/crashes/ice-4121.rs
index e1a142fdcb6..e1a142fdcb6 100644
--- a/tests/ui/ice-4121.rs
+++ b/tests/ui/crashes/ice-4121.rs
diff --git a/tests/ui/ice-4545.rs b/tests/ui/crashes/ice-4545.rs
index d9c9c2096d9..d9c9c2096d9 100644
--- a/tests/ui/ice-4545.rs
+++ b/tests/ui/crashes/ice-4545.rs
diff --git a/tests/ui/ice-4579.rs b/tests/ui/crashes/ice-4579.rs
index 2e7e279f847..2e7e279f847 100644
--- a/tests/ui/ice-4579.rs
+++ b/tests/ui/crashes/ice-4579.rs
diff --git a/tests/ui/ice-4671.rs b/tests/ui/crashes/ice-4671.rs
index 64e8e776941..64e8e776941 100644
--- a/tests/ui/ice-4671.rs
+++ b/tests/ui/crashes/ice-4671.rs
diff --git a/tests/ui/ice-4775.rs b/tests/ui/crashes/ice-4775.rs
index 31e53e846d5..31e53e846d5 100644
--- a/tests/ui/ice-4775.rs
+++ b/tests/ui/crashes/ice-4775.rs
diff --git a/tests/ui/crashes/ice-4968.rs b/tests/ui/crashes/ice-4968.rs
new file mode 100644
index 00000000000..3822f174598
--- /dev/null
+++ b/tests/ui/crashes/ice-4968.rs
@@ -0,0 +1,20 @@
+// check-pass
+
+// Test for https://github.com/rust-lang/rust-clippy/issues/4968
+
+#![warn(clippy::unsound_collection_transmute)]
+
+trait Trait {
+    type Assoc;
+}
+
+use std::mem::{self, ManuallyDrop};
+
+#[allow(unused)]
+fn func<T: Trait>(slice: Vec<T::Assoc>) {
+    unsafe {
+        let _: Vec<ManuallyDrop<T::Assoc>> = mem::transmute(slice);
+    }
+}
+
+fn main() {}