diff options
| author | Erik Desjardins <erikdesjardins@users.noreply.github.com> | 2022-04-18 21:28:53 -0400 |
|---|---|---|
| committer | Erik Desjardins <erikdesjardins@users.noreply.github.com> | 2022-04-18 21:43:20 -0400 |
| commit | 1bbae507d4aeb4e1733aaf875246b95e8b08f8a8 (patch) | |
| tree | c86920fd63f1bfb5dbc09ce44e45c7ee5b0841e5 /compiler/rustc_middle/src | |
| parent | 311e2683e1bad87715b1558f7900e294d24ce491 (diff) | |
| download | rust-1bbae507d4aeb4e1733aaf875246b95e8b08f8a8.tar.gz rust-1bbae507d4aeb4e1733aaf875246b95e8b08f8a8.zip | |
mark payload fields of ScalarPair enums as Scalar::Union when they're not always initialized
Diffstat (limited to 'compiler/rustc_middle/src')
| -rw-r--r-- | compiler/rustc_middle/src/ty/layout.rs | 37 |
1 files changed, 21 insertions, 16 deletions
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index f6d139fe59d..7cf2984a63f 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1120,21 +1120,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { match st[i].abi() { Abi::Scalar(_) => Abi::Scalar(niche_scalar), Abi::ScalarPair(first, second) => { - // We need to use scalar_unit to reset the - // valid range to the maximal one for that - // primitive, because only the niche is - // guaranteed to be initialised, not the - // other primitive. + // Only the niche is guaranteed to be initialised, + // so use union layout for the other primitive. if offset.bytes() == 0 { - Abi::ScalarPair( - niche_scalar, - scalar_unit(second.primitive()), - ) + Abi::ScalarPair(niche_scalar, second.to_union()) } else { - Abi::ScalarPair( - scalar_unit(first.primitive()), - niche_scalar, - ) + Abi::ScalarPair(first.to_union(), niche_scalar) } } _ => Abi::Aggregate { sized: true }, @@ -1329,6 +1320,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } else { // Try to use a ScalarPair for all tagged enums. let mut common_prim = None; + let mut common_prim_initialized_in_all_variants = true; for (field_layouts, layout_variant) in iter::zip(&variants, &layout_variants) { let FieldsShape::Arbitrary { ref offsets, .. } = layout_variant.fields else { bug!(); @@ -1336,7 +1328,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let mut fields = iter::zip(field_layouts, offsets).filter(|p| !p.0.is_zst()); let (field, offset) = match (fields.next(), fields.next()) { - (None, None) => continue, + (None, None) => { + common_prim_initialized_in_all_variants = false; + continue; + } (Some(pair), None) => pair, _ => { common_prim = None; @@ -1344,7 +1339,11 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } }; let prim = match field.abi { - Abi::Scalar(scalar) => scalar.primitive(), + Abi::Scalar(scalar) => { + common_prim_initialized_in_all_variants &= + matches!(scalar, Scalar::Initialized { .. }); + scalar.primitive() + } _ => { common_prim = None; break; @@ -1364,7 +1363,13 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } } if let Some((prim, offset)) = common_prim { - let pair = self.scalar_pair(tag, scalar_unit(prim)); + let prim_scalar = if common_prim_initialized_in_all_variants { + scalar_unit(prim) + } else { + // Common prim might be uninit. + Scalar::Union { value: prim } + }; + let pair = self.scalar_pair(tag, prim_scalar); let pair_offsets = match pair.fields { FieldsShape::Arbitrary { ref offsets, ref memory_index } => { assert_eq!(memory_index, &[0, 1]); |
