diff options
| author | bors <bors@rust-lang.org> | 2020-08-26 20:31:44 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2020-08-26 20:31:44 +0000 |
| commit | 2d8a3b9181f41d3af9b9f016c5d73b2553e344bf (patch) | |
| tree | e165cb7eae6fe81601f57b91f8672d1866ec9743 | |
| parent | 48717b6f3ce661d2a0d64f7bdfdfb5fd3484ee5b (diff) | |
| parent | 8c0128bb02ef528588777bda1e818e72749a7006 (diff) | |
| download | rust-2d8a3b9181f41d3af9b9f016c5d73b2553e344bf.tar.gz rust-2d8a3b9181f41d3af9b9f016c5d73b2553e344bf.zip | |
Auto merge of #75944 - jumbatm:issue-75924-clashing-extern-decl-ice, r=spastorino
Fix ICE on unwrap of unknown layout in ClashingExternDeclarations. Fixes #75924.
| -rw-r--r-- | src/librustc_lint/builtin.rs | 34 | ||||
| -rw-r--r-- | src/test/ui/lint/clashing-extern-fn.rs | 23 |
2 files changed, 47 insertions, 10 deletions
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index b337bf0a3f9..4bcf31ef0bf 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -40,7 +40,7 @@ use rustc_hir::{ForeignItemKind, GenericParamKind, PatKind}; use rustc_hir::{HirId, HirIdSet, Node}; use rustc_middle::lint::LintDiagnosticBuilder; use rustc_middle::ty::subst::{GenericArgKind, Subst}; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, layout::LayoutError, Ty, TyCtxt}; use rustc_session::lint::FutureIncompatibleInfo; use rustc_session::Session; use rustc_span::edition::Edition; @@ -2177,11 +2177,17 @@ impl ClashingExternDeclarations { let a_kind = &a.kind; let b_kind = &b.kind; - let compare_layouts = |a, b| -> bool { - let a_layout = &cx.layout_of(a).unwrap().layout.abi; - let b_layout = &cx.layout_of(b).unwrap().layout.abi; - debug!("{:?} == {:?} = {}", a_layout, b_layout, a_layout == b_layout); - a_layout == b_layout + let compare_layouts = |a, b| -> Result<bool, LayoutError<'tcx>> { + debug!("compare_layouts({:?}, {:?})", a, b); + let a_layout = &cx.layout_of(a)?.layout.abi; + let b_layout = &cx.layout_of(b)?.layout.abi; + debug!( + "comparing layouts: {:?} == {:?} = {}", + a_layout, + b_layout, + a_layout == b_layout + ); + Ok(a_layout == b_layout) }; #[allow(rustc::usage_of_ty_tykind)] @@ -2196,11 +2202,19 @@ impl ClashingExternDeclarations { let b = b.subst(cx.tcx, b_substs); debug!("Comparing {:?} and {:?}", a, b); + // We can immediately rule out these types as structurally same if + // their layouts differ. + match compare_layouts(a, b) { + Ok(false) => return false, + _ => (), // otherwise, continue onto the full, fields comparison + } + // Grab a flattened representation of all fields. let a_fields = a_def.variants.iter().flat_map(|v| v.fields.iter()); let b_fields = b_def.variants.iter().flat_map(|v| v.fields.iter()); - compare_layouts(a, b) - && a_fields.eq_by( + + // Perform a structural comparison for each field. + a_fields.eq_by( b_fields, |&ty::FieldDef { did: a_did, .. }, &ty::FieldDef { did: b_did, .. }| { @@ -2287,13 +2301,13 @@ impl ClashingExternDeclarations { if let Some(ty) = crate::types::repr_nullable_ptr(cx, adt, ckind) { ty == primitive } else { - compare_layouts(a, b) + compare_layouts(a, b).unwrap_or(false) } } // Otherwise, just compare the layouts. This may fail to lint for some // incompatible types, but at the very least, will stop reads into // uninitialised memory. - _ => compare_layouts(a, b), + _ => compare_layouts(a, b).unwrap_or(false), } }) } diff --git a/src/test/ui/lint/clashing-extern-fn.rs b/src/test/ui/lint/clashing-extern-fn.rs index d6ac7ccccc7..44cef19b0d3 100644 --- a/src/test/ui/lint/clashing-extern-fn.rs +++ b/src/test/ui/lint/clashing-extern-fn.rs @@ -285,3 +285,26 @@ mod null_optimised_enums { } } } + +#[allow(improper_ctypes)] +mod unknown_layout { + mod a { + extern "C" { + pub fn generic(l: Link<u32>); + } + pub struct Link<T> { + pub item: T, + pub next: *const Link<T>, + } + } + + mod b { + extern "C" { + pub fn generic(l: Link<u32>); + } + pub struct Link<T> { + pub item: T, + pub next: *const Link<T>, + } + } +} |
