Skip to content

Commit 2e8c3c3

Browse files
committed
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`
2 parents 304edf3 + c6aeda7 commit 2e8c3c3

16 files changed

+55
-4
lines changed

clippy_lints/src/transmute.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
use crate::utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then, sugg};
1+
use crate::utils::{
2+
is_normalizable, last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then, sugg,
3+
};
24
use if_chain::if_chain;
35
use rustc::declare_lint_pass;
46
use rustc::hir::*;
@@ -639,8 +641,13 @@ fn get_type_snippet(cx: &LateContext<'_, '_>, path: &QPath<'_>, to_ref_ty: Ty<'_
639641
// check if the component types of the transmuted collection and the result have different ABI,
640642
// size or alignment
641643
fn is_layout_incompatible<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, from: Ty<'tcx>, to: Ty<'tcx>) -> bool {
642-
let from_ty_layout = cx.tcx.layout_of(ty::ParamEnv::empty().and(from));
643-
let to_ty_layout = cx.tcx.layout_of(ty::ParamEnv::empty().and(to));
644+
let empty_param_env = ty::ParamEnv::empty();
645+
// check if `from` and `to` are normalizable to avoid ICE (#4968)
646+
if !(is_normalizable(cx, empty_param_env, from) && is_normalizable(cx, empty_param_env, to)) {
647+
return false;
648+
}
649+
let from_ty_layout = cx.tcx.layout_of(empty_param_env.and(from));
650+
let to_ty_layout = cx.tcx.layout_of(empty_param_env.and(to));
644651
if let (Ok(from_layout), Ok(to_layout)) = (from_ty_layout, to_ty_layout) {
645652
from_layout.size != to_layout.size || from_layout.align != to_layout.align || from_layout.abi != to_layout.abi
646653
} else {

clippy_lints/src/utils/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,15 @@ pub fn match_function_call<'a, 'tcx>(
11111111
None
11121112
}
11131113

1114+
/// Checks if `Ty` is normalizable. This function is useful
1115+
/// to avoid crashes on `layout_of`.
1116+
pub fn is_normalizable<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
1117+
cx.tcx.infer_ctxt().enter(|infcx| {
1118+
let cause = rustc::traits::ObligationCause::dummy();
1119+
infcx.at(&cause, param_env).normalize(&ty).is_ok()
1120+
})
1121+
}
1122+
11141123
#[cfg(test)]
11151124
mod test {
11161125
use super::{trim_multiline, without_block_comments};
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
macro_rules! use_self {
2+
(
3+
impl $ty:ident {
4+
fn func(&$this:ident) {
5+
[fields($($field:ident)*)]
6+
}
7+
}
8+
) => (
9+
impl $ty {
10+
fn func(&$this) {
11+
let $ty { $($field),* } = $this;
12+
}
13+
}
14+
)
15+
}
File renamed without changes.
File renamed without changes.

tests/ui/crashes/issue-2862.rs renamed to tests/ui/crashes/ice-2862.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// run-pass
22

3-
/// Test for https://github.com/rust-lang/rust-clippy/issues/2826
3+
/// Test for https://github.com/rust-lang/rust-clippy/issues/2862
44
55
pub trait FooMap {
66
fn map<B, F: Fn() -> B>(&self, f: F) -> B;
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

tests/ui/crashes/ice-4968.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// check-pass
2+
3+
// Test for https://github.com/rust-lang/rust-clippy/issues/4968
4+
5+
#![warn(clippy::unsound_collection_transmute)]
6+
7+
trait Trait {
8+
type Assoc;
9+
}
10+
11+
use std::mem::{self, ManuallyDrop};
12+
13+
#[allow(unused)]
14+
fn func<T: Trait>(slice: Vec<T::Assoc>) {
15+
unsafe {
16+
let _: Vec<ManuallyDrop<T::Assoc>> = mem::transmute(slice);
17+
}
18+
}
19+
20+
fn main() {}

0 commit comments

Comments
 (0)