diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/ty/layout.rs | 25 | ||||
| -rw-r--r-- | src/librustc/ty/mod.rs | 8 | ||||
| -rw-r--r-- | src/librustc_attr/builtin.rs | 2 | ||||
| -rw-r--r-- | src/librustc_builtin_macros/deriving/generic/mod.rs | 3 | ||||
| -rw-r--r-- | src/librustc_feature/active.rs | 4 | ||||
| -rw-r--r-- | src/librustc_passes/check_attr.rs | 24 | ||||
| -rw-r--r-- | src/librustc_span/symbol.rs | 2 |
7 files changed, 56 insertions, 12 deletions
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index dbf421d26cb..e8bf2eb9a12 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -356,12 +356,14 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { debug!("univariant offset: {:?} field: {:#?}", offset, field); offsets[i as usize] = offset; - if let Some(mut niche) = field.largest_niche.clone() { - let available = niche.available(dl); - if available > largest_niche_available { - largest_niche_available = available; - niche.offset += offset; - largest_niche = Some(niche); + if !repr.hide_niche() { + if let Some(mut niche) = field.largest_niche.clone() { + let available = niche.available(dl); + if available > largest_niche_available { + largest_niche_available = available; + niche.offset += offset; + largest_niche = Some(niche); + } } } @@ -838,7 +840,11 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } // Update `largest_niche` if we have introduced a larger niche. - let niche = Niche::from_scalar(dl, Size::ZERO, scalar.clone()); + let niche = if def.repr.hide_niche() { + None + } else { + Niche::from_scalar(dl, Size::ZERO, scalar.clone()) + }; if let Some(niche) = niche { match &st.largest_niche { Some(largest_niche) => { @@ -863,6 +869,11 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { return Ok(tcx.intern_layout(st)); } + // At this point, we have handled all unions and + // structs. (We have also handled univariant enums + // that allow representation optimization.) + assert!(def.is_enum()); + // The current code for niche-filling relies on variant indices // instead of actual discriminants, so dataful enums with // explicit discriminants (RFC #2363) would misbehave. diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 0118fc4c8ac..60296b8116d 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2041,7 +2041,8 @@ 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; // Any of these flags being set prevent field reordering optimisation. const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits | ReprFlags::IS_SIMD.bits | @@ -2078,6 +2079,7 @@ 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); @@ -2118,6 +2120,10 @@ impl ReprOptions { pub fn linear(&self) -> bool { self.flags.contains(ReprFlags::IS_LINEAR) } + #[inline] + pub fn hide_niche(&self) -> bool { + self.flags.contains(ReprFlags::HIDE_NICHE) + } pub fn discr_type(&self) -> attr::IntType { self.int.unwrap_or(attr::SignedInt(ast::IntTy::Isize)) diff --git a/src/librustc_attr/builtin.rs b/src/librustc_attr/builtin.rs index ab03297fffe..b9646cbbe6e 100644 --- a/src/librustc_attr/builtin.rs +++ b/src/librustc_attr/builtin.rs @@ -838,6 +838,7 @@ pub enum ReprAttr { ReprSimd, ReprTransparent, ReprAlign(u32), + ReprNoNiche, } #[derive(Eq, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone, HashStable_Generic)] @@ -893,6 +894,7 @@ pub fn find_repr_attrs(sess: &ParseSess, attr: &Attribute) -> Vec<ReprAttr> { sym::packed => Some(ReprPacked(1)), sym::simd => Some(ReprSimd), sym::transparent => Some(ReprTransparent), + sym::no_niche => Some(ReprNoNiche), name => int_type_of_word(name).map(ReprInt), }; diff --git a/src/librustc_builtin_macros/deriving/generic/mod.rs b/src/librustc_builtin_macros/deriving/generic/mod.rs index 364d8ff8e22..f99008a6d5c 100644 --- a/src/librustc_builtin_macros/deriving/generic/mod.rs +++ b/src/librustc_builtin_macros/deriving/generic/mod.rs @@ -825,7 +825,8 @@ fn find_repr_type_name(sess: &ParseSess, type_attrs: &[ast::Attribute]) -> &'sta attr::ReprPacked(_) | attr::ReprSimd | attr::ReprAlign(_) - | attr::ReprTransparent => continue, + | attr::ReprTransparent + | attr::ReprNoNiche => continue, attr::ReprC => "i32", diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 135500c0a8d..0082f4f1a6e 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -204,6 +204,10 @@ declare_features! ( /// Added for testing E0705; perma-unstable. (active, test_2018_feature, "1.31.0", None, Some(Edition::Edition2018)), + /// Allows `#[repr(no_niche)]` (an implementation detail of `rustc`, + /// it is not on path for eventual stabilization). + (active, no_niche, "1.42.0", None, None), + // no-tracking-issue-end // ------------------------------------------------------------------------- diff --git a/src/librustc_passes/check_attr.rs b/src/librustc_passes/check_attr.rs index 3ff1ba3bbfc..81c5c3412b1 100644 --- a/src/librustc_passes/check_attr.rs +++ b/src/librustc_passes/check_attr.rs @@ -16,9 +16,10 @@ use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::DUMMY_HIR_ID; use rustc_hir::{self, HirId, Item, ItemKind, TraitItem}; use rustc_session::lint::builtin::{CONFLICTING_REPR_HINTS, UNUSED_ATTRIBUTES}; +use rustc_session::parse::feature_err; use rustc_span::symbol::sym; use rustc_span::Span; -use syntax::ast::Attribute; +use syntax::ast::{Attribute, NestedMetaItem}; use syntax::attr; fn target_from_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item: &hir::ImplItem<'_>) -> Target { @@ -287,6 +288,21 @@ impl CheckAttrVisitor<'tcx> { _ => ("a", "struct, enum, or union"), } } + sym::no_niche => { + if !self.tcx.features().enabled(sym::no_niche) { + feature_err( + &self.tcx.sess.parse_sess, + sym::no_niche, + hint.span(), + "the attribute `repr(no_niche)` is currently unstable", + ) + .emit(); + } + match target { + Target::Struct | Target::Enum => continue, + _ => ("a", "struct or enum"), + } + } sym::i8 | sym::u8 | sym::i16 @@ -314,8 +330,10 @@ impl CheckAttrVisitor<'tcx> { // This is not ideal, but tracking precisely which ones are at fault is a huge hassle. let hint_spans = hints.iter().map(|hint| hint.span()); - // Error on repr(transparent, <anything else>). - if is_transparent && hints.len() > 1 { + // Error on repr(transparent, <anything else apart from no_niche>). + let non_no_niche = |hint: &&NestedMetaItem| hint.name_or_empty() != sym::no_niche; + let non_no_niche_count = hints.iter().filter(non_no_niche).count(); + if is_transparent && non_no_niche_count > 1 { let hint_spans: Vec<_> = hint_spans.clone().collect(); struct_span_err!( self.tcx.sess, diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index 49582e064ea..1cc4a277880 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -491,6 +491,7 @@ symbols! { non_exhaustive, non_modrs_mods, no_sanitize, + no_niche, no_stack_check, no_start, no_std, @@ -587,6 +588,7 @@ symbols! { repr128, repr_align, repr_align_enum, + repr_no_niche, repr_packed, repr_simd, repr_transparent, |
