Change:
<!-- Thank you for finding an Internal Compiler Error! If possible, try to provide a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for how to create smaller examples. --<!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongBacktrace</strong</summary<p</p</details<!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
cc for ClashingExternDeclarations in backtrace.
claim
Thank you for fixing it! There is nothing better than software with only a few open issues.
Not a problem! Thank you for the report, and especially for taking the time to make a minimal example :)

Discussion:
use rustc_hir::{HirId, HirIdSet, Node}; use rustc_middle::lint::LintDiagnosticBuilder; use rustc_middle::ty::subst::{GenericArgKind, Subst}; <del> use rustc_middle::ty::{self, Ty, TyCtxt}; </del> <ins> use rustc_middle::ty::{self, layout::LayoutError, Ty, TyCtxt}; </ins> use rustc_session::lint::FutureIncompatibleInfo; use rustc_session::Session; use rustc_span::edition::Edition;

let a_kind = &a.kind; let b_kind = &b.kind; <del> 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 </del> <ins> 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) </ins> }; #[allow(rustc::usage_of_ty_tykind)]

let b = b.subst(cx.tcx, b_substs); debug!("Comparing {:?} and {:?}", a, b); <ins> // 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 } </ins> // 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()); <del> compare_layouts(a, b) && a_fields.eq_by( </del> <ins> // Perform a structural comparison for each field. a_fields.eq_by( </ins> b_fields, |&ty::FieldDef { did: a_did, .. }, &ty::FieldDef { did: b_did, .. }| {

if let Some(ty) = crate::types::repr_nullable_ptr(cx, adt, ckind) { ty == primitive } else { <del> compare_layouts(a, b) </del> <ins> compare_layouts(a, b).unwrap_or(false) </ins> } } // 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. <del> _ => compare_layouts(a, b), </del> <ins> _ => compare_layouts(a, b).unwrap_or(false), </ins> } }) }

} } } <ins> #[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>, } } } </ins>