diff options
Diffstat (limited to 'compiler/rustc_middle')
| -rw-r--r-- | compiler/rustc_middle/src/thir.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/thir/visit.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/adt.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/layout.rs | 43 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/mod.rs | 10 |
5 files changed, 49 insertions, 22 deletions
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 3fe6394ad7e..3e5f6bb8f0b 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -182,6 +182,9 @@ pub enum StmtKind<'tcx> { /// `let pat: ty = <INIT>` initializer: Option<ExprId>, + /// `let pat: ty = <INIT> else { <ELSE> } + else_block: Option<Block>, + /// The lint level for this `let` statement. lint_level: LintLevel, }, diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index c8d09875c28..97249fdd175 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -167,11 +167,15 @@ pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stm init_scope: _, ref pattern, lint_level: _, + else_block, } => { if let Some(init) = initializer { visitor.visit_expr(&visitor.thir()[*init]); } visitor.visit_pat(pattern); + if let Some(block) = else_block { + visitor.visit_block(block) + } } } } diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 4cac7670735..809406aff18 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -52,6 +52,8 @@ bitflags! { /// Indicates whether the variant list of this ADT is `#[non_exhaustive]`. /// (i.e., this flag is never set unless this ADT is an enum). const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 8; + /// Indicates whether the type is `UnsafeCell`. + const IS_UNSAFE_CELL = 1 << 9; } } @@ -247,6 +249,9 @@ impl AdtDefData { if Some(did) == tcx.lang_items().manually_drop() { flags |= AdtFlags::IS_MANUALLY_DROP; } + if Some(did) == tcx.lang_items().unsafe_cell_type() { + flags |= AdtFlags::IS_UNSAFE_CELL; + } AdtDefData { did, variants, flags, repr } } @@ -333,6 +338,12 @@ impl<'tcx> AdtDef<'tcx> { self.flags().contains(AdtFlags::IS_BOX) } + /// Returns `true` if this is UnsafeCell<T>. + #[inline] + pub fn is_unsafe_cell(self) -> bool { + self.flags().contains(AdtFlags::IS_UNSAFE_CELL) + } + /// Returns `true` if this is `ManuallyDrop<T>`. #[inline] pub fn is_manually_drop(self) -> bool { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index f87b6e4212d..1ed41db099c 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -542,14 +542,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { debug!("univariant offset: {:?} field: {:#?}", offset, field); offsets[i as usize] = offset; - if !repr.hide_niche() { - if let Some(mut niche) = field.largest_niche { - let available = niche.available(dl); - if available > largest_niche_available { - largest_niche_available = available; - niche.offset += offset; - largest_niche = Some(niche); - } + if let Some(mut niche) = field.largest_niche { + let available = niche.available(dl); + if available > largest_niche_available { + largest_niche_available = available; + niche.offset += offset; + largest_niche = Some(niche); } } @@ -1078,6 +1076,29 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let mut st = self.univariant_uninterned(ty, &variants[v], &def.repr(), kind)?; st.variants = Variants::Single { index: v }; + + if def.is_unsafe_cell() { + let hide_niches = |scalar: &mut _| match scalar { + Scalar::Initialized { value, valid_range } => { + *valid_range = WrappingRange::full(value.size(dl)) + } + // Already doesn't have any niches + Scalar::Union { .. } => {} + }; + match &mut st.abi { + Abi::Uninhabited => {} + Abi::Scalar(scalar) => hide_niches(scalar), + Abi::ScalarPair(a, b) => { + hide_niches(a); + hide_niches(b); + } + Abi::Vector { element, count: _ } => hide_niches(element), + Abi::Aggregate { sized: _ } => {} + } + st.largest_niche = None; + return Ok(tcx.intern_layout(st)); + } + let (start, end) = self.tcx.layout_scalar_valid_range(def.did()); match st.abi { Abi::Scalar(ref mut scalar) | Abi::ScalarPair(ref mut scalar, _) => { @@ -1106,11 +1127,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } // Update `largest_niche` if we have introduced a larger niche. - let niche = if def.repr().hide_niche() { - None - } else { - Niche::from_scalar(dl, Size::ZERO, *scalar) - }; + let niche = Niche::from_scalar(dl, Size::ZERO, *scalar); if let Some(niche) = niche { match st.largest_niche { Some(largest_niche) => { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index f15108fb750..c2c7b3df844 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1720,11 +1720,9 @@ bitflags! { const IS_TRANSPARENT = 1 << 2; // Internal only for now. If true, don't reorder fields. const IS_LINEAR = 1 << 3; - // If true, don't expose any niche to type's context. - const HIDE_NICHE = 1 << 4; // If true, the type's layout can be randomized using // the seed stored in `ReprOptions.layout_seed` - const RANDOMIZE_LAYOUT = 1 << 5; + const RANDOMIZE_LAYOUT = 1 << 4; // Any of these flags being set prevent field reordering optimisation. const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits | ReprFlags::IS_SIMD.bits @@ -1781,7 +1779,6 @@ impl ReprOptions { ReprFlags::empty() } attr::ReprTransparent => ReprFlags::IS_TRANSPARENT, - attr::ReprNoNiche => ReprFlags::HIDE_NICHE, attr::ReprSimd => ReprFlags::IS_SIMD, attr::ReprInt(i) => { size = Some(i); @@ -1834,11 +1831,6 @@ impl ReprOptions { self.flags.contains(ReprFlags::IS_LINEAR) } - #[inline] - pub fn hide_niche(&self) -> bool { - self.flags.contains(ReprFlags::HIDE_NICHE) - } - /// Returns the discriminant type, given these `repr` options. /// This must only be called on enums! pub fn discr_type(&self) -> attr::IntType { |
