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

File tree

16 files changed

+55
-4
lines changed

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.

0 commit comments

Comments
 (0)