1
Fork 0

Auto merge of #111671 - Dylan-DPC:rollup-1jy5r16, r=Dylan-DPC

Rollup of 6 pull requests

Successful merges:

 - #110145 (Share slice of bytes)
 - #111043 (Stabilize feature `cstr_is_empty`)
 - #111648 (Remove `LangItems::require`)
 - #111649 (Add derive for `core::marker::ConstParamTy`)
 - #111654 (Add a conversion from `&mut T` to `&mut UnsafeCell<T>`)
 - #111661 (Erase regions of type in `offset_of!`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-05-17 06:42:07 +00:00
commit c2ccc855e7
34 changed files with 232 additions and 83 deletions

View file

@ -27,3 +27,26 @@ pub fn expand_deriving_copy(
trait_def.expand(cx, mitem, item, push); trait_def.expand(cx, mitem, item, push);
} }
pub fn expand_deriving_const_param_ty(
cx: &mut ExtCtxt<'_>,
span: Span,
mitem: &MetaItem,
item: &Annotatable,
push: &mut dyn FnMut(Annotatable),
is_const: bool,
) {
let trait_def = TraitDef {
span,
path: path_std!(marker::ConstParamTy),
skip_path_as_bound: false,
needs_copy_as_bound_if_packed: false,
additional_bounds: Vec::new(),
supports_unions: false,
methods: Vec::new(),
associated_types: Vec::new(),
is_const,
};
trait_def.expand(cx, mitem, item, push);
}

View file

@ -115,6 +115,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
register_derive! { register_derive! {
Clone: clone::expand_deriving_clone, Clone: clone::expand_deriving_clone,
Copy: bounds::expand_deriving_copy, Copy: bounds::expand_deriving_copy,
ConstParamTy: bounds::expand_deriving_const_param_ty,
Debug: debug::expand_deriving_debug, Debug: debug::expand_deriving_debug,
Default: default::expand_deriving_default, Default: default::expand_deriving_default,
Eq: eq::expand_deriving_eq, Eq: eq::expand_deriving_eq,

View file

@ -966,11 +966,7 @@ fn codegen_panic_inner<'tcx>(
args: &[Value], args: &[Value],
span: Span, span: Span,
) { ) {
let def_id = fx let def_id = fx.tcx.require_lang_item(lang_item, Some(span));
.tcx
.lang_items()
.require(lang_item)
.unwrap_or_else(|e| fx.tcx.sess.span_fatal(span, e.to_string()));
let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx); let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx);
let symbol_name = fx.tcx.symbol_name(instance).name; let symbol_name = fx.tcx.symbol_name(instance).name;

View file

@ -14,8 +14,7 @@ use snap::write::FrameEncoder;
use object::elf::NT_GNU_PROPERTY_TYPE_0; use object::elf::NT_GNU_PROPERTY_TYPE_0;
use rustc_data_structures::memmap::Mmap; use rustc_data_structures::memmap::Mmap;
use rustc_data_structures::owned_slice::try_slice_owned; use rustc_data_structures::owned_slice::{try_slice_owned, OwnedSlice};
use rustc_data_structures::sync::MetadataRef;
use rustc_metadata::fs::METADATA_FILENAME; use rustc_metadata::fs::METADATA_FILENAME;
use rustc_metadata::EncodedMetadata; use rustc_metadata::EncodedMetadata;
use rustc_session::cstore::MetadataLoader; use rustc_session::cstore::MetadataLoader;
@ -39,7 +38,7 @@ pub struct DefaultMetadataLoader;
fn load_metadata_with( fn load_metadata_with(
path: &Path, path: &Path,
f: impl for<'a> FnOnce(&'a [u8]) -> Result<&'a [u8], String>, f: impl for<'a> FnOnce(&'a [u8]) -> Result<&'a [u8], String>,
) -> Result<MetadataRef, String> { ) -> Result<OwnedSlice, String> {
let file = let file =
File::open(path).map_err(|e| format!("failed to open file '{}': {}", path.display(), e))?; File::open(path).map_err(|e| format!("failed to open file '{}': {}", path.display(), e))?;
@ -49,7 +48,7 @@ fn load_metadata_with(
} }
impl MetadataLoader for DefaultMetadataLoader { impl MetadataLoader for DefaultMetadataLoader {
fn get_rlib_metadata(&self, _target: &Target, path: &Path) -> Result<MetadataRef, String> { fn get_rlib_metadata(&self, _target: &Target, path: &Path) -> Result<OwnedSlice, String> {
load_metadata_with(path, |data| { load_metadata_with(path, |data| {
let archive = object::read::archive::ArchiveFile::parse(&*data) let archive = object::read::archive::ArchiveFile::parse(&*data)
.map_err(|e| format!("failed to parse rlib '{}': {}", path.display(), e))?; .map_err(|e| format!("failed to parse rlib '{}': {}", path.display(), e))?;
@ -69,7 +68,7 @@ impl MetadataLoader for DefaultMetadataLoader {
}) })
} }
fn get_dylib_metadata(&self, _target: &Target, path: &Path) -> Result<MetadataRef, String> { fn get_dylib_metadata(&self, _target: &Target, path: &Path) -> Result<OwnedSlice, String> {
load_metadata_with(path, |data| search_for_section(path, data, ".rustc")) load_metadata_with(path, |data| search_for_section(path, data, ".rustc"))
} }
} }

View file

@ -1,3 +1,5 @@
use std::any::Any;
use super::write::WriteBackendMethods; use super::write::WriteBackendMethods;
use super::CodegenObject; use super::CodegenObject;
use crate::back::write::TargetMachineFactoryFn; use crate::back::write::TargetMachineFactoryFn;
@ -5,6 +7,7 @@ use crate::{CodegenResults, ModuleCodegen};
use rustc_ast::expand::allocator::AllocatorKind; use rustc_ast::expand::allocator::AllocatorKind;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::{DynSend, DynSync};
use rustc_errors::ErrorGuaranteed; use rustc_errors::ErrorGuaranteed;
use rustc_metadata::EncodedMetadata; use rustc_metadata::EncodedMetadata;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
@ -20,11 +23,6 @@ use rustc_span::symbol::Symbol;
use rustc_target::abi::call::FnAbi; use rustc_target::abi::call::FnAbi;
use rustc_target::spec::Target; use rustc_target::spec::Target;
pub use rustc_data_structures::sync::MetadataRef;
use rustc_data_structures::sync::{DynSend, DynSync};
use std::any::Any;
pub trait BackendTypes { pub trait BackendTypes {
type Value: CodegenObject; type Value: CodegenObject;
type Function: CodegenObject; type Function: CodegenObject;

View file

@ -1,5 +1,6 @@
use std::{borrow::Borrow, ops::Deref}; use std::{borrow::Borrow, ops::Deref};
use crate::sync::Lrc;
// Use our fake Send/Sync traits when on not parallel compiler, // Use our fake Send/Sync traits when on not parallel compiler,
// so that `OwnedSlice` only implements/requires Send/Sync // so that `OwnedSlice` only implements/requires Send/Sync
// for parallel compiler builds. // for parallel compiler builds.
@ -7,7 +8,7 @@ use crate::sync::{Send, Sync};
/// An owned slice. /// An owned slice.
/// ///
/// This is similar to `Box<[u8]>` but allows slicing and using anything as the /// This is similar to `Lrc<[u8]>` but allows slicing and using anything as the
/// backing buffer. /// backing buffer.
/// ///
/// See [`slice_owned`] for `OwnedSlice` construction and examples. /// See [`slice_owned`] for `OwnedSlice` construction and examples.
@ -16,6 +17,7 @@ use crate::sync::{Send, Sync};
/// ///
/// This is essentially a replacement for `owning_ref` which is a lot simpler /// This is essentially a replacement for `owning_ref` which is a lot simpler
/// and even sound! 🌸 /// and even sound! 🌸
#[derive(Clone)]
pub struct OwnedSlice { pub struct OwnedSlice {
/// This is conceptually a `&'self.owner [u8]`. /// This is conceptually a `&'self.owner [u8]`.
bytes: *const [u8], bytes: *const [u8],
@ -31,7 +33,7 @@ pub struct OwnedSlice {
// \/ // \/
// ⊂(´・◡・⊂ )∘˚˳° (I am the phantom remnant of #97770) // ⊂(´・◡・⊂ )∘˚˳° (I am the phantom remnant of #97770)
#[expect(dead_code)] #[expect(dead_code)]
owner: Box<dyn Send + Sync>, owner: Lrc<dyn Send + Sync>,
} }
/// Makes an [`OwnedSlice`] out of an `owner` and a `slicer` function. /// Makes an [`OwnedSlice`] out of an `owner` and a `slicer` function.
@ -72,10 +74,10 @@ where
O: Send + Sync + 'static, O: Send + Sync + 'static,
F: FnOnce(&O) -> Result<&[u8], E>, F: FnOnce(&O) -> Result<&[u8], E>,
{ {
// We box the owner of the bytes, so it doesn't move. // We wrap the owner of the bytes in, so it doesn't move.
// //
// Since the owner does not move and we don't access it in any way // Since the owner does not move and we don't access it in any way
// before drop, there is nothing that can invalidate the bytes pointer. // before dropping, there is nothing that can invalidate the bytes pointer.
// //
// Thus, "extending" the lifetime of the reference returned from `F` is fine. // Thus, "extending" the lifetime of the reference returned from `F` is fine.
// We pretend that we pass it a reference that lives as long as the returned slice. // We pretend that we pass it a reference that lives as long as the returned slice.
@ -83,12 +85,39 @@ where
// N.B. the HRTB on the `slicer` is important — without it the caller could provide // N.B. the HRTB on the `slicer` is important — without it the caller could provide
// a short lived slice, unrelated to the owner. // a short lived slice, unrelated to the owner.
let owner = Box::new(owner); let owner = Lrc::new(owner);
let bytes = slicer(&*owner)?; let bytes = slicer(&*owner)?;
Ok(OwnedSlice { bytes, owner }) Ok(OwnedSlice { bytes, owner })
} }
impl OwnedSlice {
/// Slice this slice by `slicer`.
///
/// # Examples
///
/// ```rust
/// # use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned};
/// let vec = vec![1, 2, 3, 4];
///
/// // Identical to slicing via `&v[1..3]` but produces an owned slice
/// let slice: OwnedSlice = slice_owned(vec, |v| &v[..]);
/// assert_eq!(&*slice, [1, 2, 3, 4]);
///
/// let slice = slice.slice(|slice| &slice[1..][..2]);
/// assert_eq!(&*slice, [2, 3]);
/// ```
///
pub fn slice(self, slicer: impl FnOnce(&[u8]) -> &[u8]) -> OwnedSlice {
// This is basically identical to `try_slice_owned`,
// `slicer` can only return slices of its argument or some static data,
// both of which are valid while `owner` is alive.
let bytes = slicer(&self);
OwnedSlice { bytes, ..self }
}
}
impl Deref for OwnedSlice { impl Deref for OwnedSlice {
type Target = [u8]; type Target = [u8];
@ -108,11 +137,11 @@ impl Borrow<[u8]> for OwnedSlice {
} }
} }
// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Box<dyn Send + Sync>)`, which is `Send` // Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Arc<dyn Send + Sync>)`, which is `Send`
#[cfg(parallel_compiler)] #[cfg(parallel_compiler)]
unsafe impl Send for OwnedSlice {} unsafe impl Send for OwnedSlice {}
// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Box<dyn Send + Sync>)`, which is `Sync` // Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Arc<dyn Send + Sync>)`, which is `Sync`
#[cfg(parallel_compiler)] #[cfg(parallel_compiler)]
unsafe impl Sync for OwnedSlice {} unsafe impl Sync for OwnedSlice {}

View file

@ -26,7 +26,7 @@ fn static_storage() {
} }
#[test] #[test]
fn slice_the_slice() { fn slice_owned_the_slice() {
let slice = slice_owned(vec![1, 2, 3, 4, 5, 6], Vec::as_slice); let slice = slice_owned(vec![1, 2, 3, 4, 5, 6], Vec::as_slice);
let slice = slice_owned(slice, |s| &s[1..][..4]); let slice = slice_owned(slice, |s| &s[1..][..4]);
let slice = slice_owned(slice, |s| s); let slice = slice_owned(slice, |s| s);
@ -35,6 +35,16 @@ fn slice_the_slice() {
assert_eq!(&*slice, &[1, 2, 3, 4, 5, 6][1..][..4][1..]); assert_eq!(&*slice, &[1, 2, 3, 4, 5, 6][1..][..4][1..]);
} }
#[test]
fn slice_the_slice() {
let slice = slice_owned(vec![1, 2, 3, 4, 5, 6], Vec::as_slice)
.slice(|s| &s[1..][..4])
.slice(|s| s)
.slice(|s| &s[1..]);
assert_eq!(&*slice, &[1, 2, 3, 4, 5, 6][1..][..4][1..]);
}
#[test] #[test]
fn try_and_fail() { fn try_and_fail() {
let res = try_slice_owned(vec![0], |v| v.get(12..).ok_or(())); let res = try_slice_owned(vec![0], |v| v.get(12..).ok_or(()));

View file

@ -40,7 +40,6 @@
//! [^2] `MTLockRef` is a typedef. //! [^2] `MTLockRef` is a typedef.
pub use crate::marker::*; pub use crate::marker::*;
use crate::owned_slice::OwnedSlice;
use std::collections::HashMap; use std::collections::HashMap;
use std::hash::{BuildHasher, Hash}; use std::hash::{BuildHasher, Hash};
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
@ -92,6 +91,7 @@ mod mode {
} }
pub use mode::{is_dyn_thread_safe, set_dyn_thread_safe_mode}; pub use mode::{is_dyn_thread_safe, set_dyn_thread_safe_mode};
cfg_if! { cfg_if! {
if #[cfg(not(parallel_compiler))] { if #[cfg(not(parallel_compiler))] {
pub unsafe auto trait Send {} pub unsafe auto trait Send {}
@ -244,8 +244,6 @@ cfg_if! {
r r
} }
pub type MetadataRef = OwnedSlice;
pub use std::rc::Rc as Lrc; pub use std::rc::Rc as Lrc;
pub use std::rc::Weak as Weak; pub use std::rc::Weak as Weak;
pub use std::cell::Ref as ReadGuard; pub use std::cell::Ref as ReadGuard;
@ -517,8 +515,6 @@ cfg_if! {
} }
} }
pub type MetadataRef = OwnedSlice;
/// This makes locks panic if they are already held. /// This makes locks panic if they are already held.
/// It is only useful when you are running in a single thread /// It is only useful when you are running in a single thread
const ERROR_CHECKING: bool = false; const ERROR_CHECKING: bool = false;

View file

@ -1,10 +0,0 @@
use crate::LangItem;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable)]
pub struct LangItemError(pub LangItem);
impl ToString for LangItemError {
fn to_string(&self) -> String {
format!("requires `{}` lang_item", self.0.name())
}
}

View file

@ -8,7 +8,6 @@
//! * Functions called by the compiler itself. //! * Functions called by the compiler itself.
use crate::def_id::DefId; use crate::def_id::DefId;
use crate::errors::LangItemError;
use crate::{MethodKind, Target}; use crate::{MethodKind, Target};
use rustc_ast as ast; use rustc_ast as ast;
@ -42,13 +41,6 @@ impl LanguageItems {
self.items[item as usize] = Some(def_id); self.items[item as usize] = Some(def_id);
} }
/// Requires that a given `LangItem` was bound and returns the corresponding `DefId`.
/// If it wasn't bound, e.g. due to a missing `#[lang = "<it.name()>"]`,
/// returns an error encapsulating the `LangItem`.
pub fn require(&self, it: LangItem) -> Result<DefId, LangItemError> {
self.get(it).ok_or_else(|| LangItemError(it))
}
pub fn iter(&self) -> impl Iterator<Item = (LangItem, DefId)> + '_ { pub fn iter(&self) -> impl Iterator<Item = (LangItem, DefId)> + '_ {
self.items self.items
.iter() .iter()

View file

@ -30,7 +30,6 @@ pub mod def;
pub mod def_path_hash_map; pub mod def_path_hash_map;
pub mod definitions; pub mod definitions;
pub mod diagnostic_items; pub mod diagnostic_items;
pub mod errors;
pub use rustc_span::def_id; pub use rustc_span::def_id;
mod hir; mod hir;
pub mod hir_id; pub mod hir_id;

View file

@ -298,9 +298,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, Some(span)); let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, Some(span));
let unsize_trait = tcx.lang_items().require(LangItem::Unsize).unwrap_or_else(|err| { let unsize_trait = tcx.require_lang_item(LangItem::Unsize, Some(span));
tcx.sess.fatal(format!("`CoerceUnsized` implementation {}", err.to_string()));
});
let source = tcx.type_of(impl_did).subst_identity(); let source = tcx.type_of(impl_did).subst_identity();
let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().subst_identity(); let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().subst_identity();

View file

@ -220,7 +220,6 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::memmap::Mmap; use rustc_data_structures::memmap::Mmap;
use rustc_data_structures::owned_slice::slice_owned; use rustc_data_structures::owned_slice::slice_owned;
use rustc_data_structures::svh::Svh; use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::MetadataRef;
use rustc_errors::{DiagnosticArgValue, FatalError, IntoDiagnosticArg}; use rustc_errors::{DiagnosticArgValue, FatalError, IntoDiagnosticArg};
use rustc_fs_util::try_canonicalize; use rustc_fs_util::try_canonicalize;
use rustc_session::config::{self, CrateType}; use rustc_session::config::{self, CrateType};
@ -782,7 +781,7 @@ fn get_metadata_section<'p>(
if !filename.exists() { if !filename.exists() {
return Err(MetadataError::NotPresent(filename)); return Err(MetadataError::NotPresent(filename));
} }
let raw_bytes: MetadataRef = match flavor { let raw_bytes = match flavor {
CrateFlavor::Rlib => { CrateFlavor::Rlib => {
loader.get_rlib_metadata(target, filename).map_err(MetadataError::LoadFailure)? loader.get_rlib_metadata(target, filename).map_err(MetadataError::LoadFailure)?
} }
@ -843,7 +842,7 @@ fn get_metadata_section<'p>(
slice_owned(mmap, Deref::deref) slice_owned(mmap, Deref::deref)
} }
}; };
let blob = MetadataBlob::new(raw_bytes); let blob = MetadataBlob(raw_bytes);
if blob.is_compatible() { if blob.is_compatible() {
Ok(blob) Ok(blob)
} else { } else {

View file

@ -7,6 +7,7 @@ use crate::rmeta::*;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_data_structures::captures::Captures; use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::owned_slice::OwnedSlice;
use rustc_data_structures::svh::Svh; use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc, OnceCell}; use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc, OnceCell};
use rustc_data_structures::unhash::UnhashMap; use rustc_data_structures::unhash::UnhashMap;
@ -50,7 +51,7 @@ mod cstore_impl;
/// A `MetadataBlob` internally is just a reference counted pointer to /// A `MetadataBlob` internally is just a reference counted pointer to
/// the actual data, so cloning it is cheap. /// the actual data, so cloning it is cheap.
#[derive(Clone)] #[derive(Clone)]
pub(crate) struct MetadataBlob(Lrc<MetadataRef>); pub(crate) struct MetadataBlob(pub(crate) OwnedSlice);
impl std::ops::Deref for MetadataBlob { impl std::ops::Deref for MetadataBlob {
type Target = [u8]; type Target = [u8];
@ -660,10 +661,6 @@ impl<'a, 'tcx, I: Idx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyTable<I, T>
implement_ty_decoder!(DecodeContext<'a, 'tcx>); implement_ty_decoder!(DecodeContext<'a, 'tcx>);
impl MetadataBlob { impl MetadataBlob {
pub(crate) fn new(metadata_ref: MetadataRef) -> MetadataBlob {
MetadataBlob(Lrc::new(metadata_ref))
}
pub(crate) fn is_compatible(&self) -> bool { pub(crate) fn is_compatible(&self) -> bool {
self.blob().starts_with(METADATA_HEADER) self.blob().starts_with(METADATA_HEADER)
} }

View file

@ -1,6 +1,5 @@
use crate::rmeta::DecodeContext; use crate::rmeta::DecodeContext;
use crate::rmeta::EncodeContext; use crate::rmeta::EncodeContext;
use rustc_data_structures::owned_slice::slice_owned;
use rustc_data_structures::owned_slice::OwnedSlice; use rustc_data_structures::owned_slice::OwnedSlice;
use rustc_hir::def_path_hash_map::{Config as HashMapConfig, DefPathHashMap}; use rustc_hir::def_path_hash_map::{Config as HashMapConfig, DefPathHashMap};
use rustc_middle::parameterized_over_tcx; use rustc_middle::parameterized_over_tcx;
@ -47,7 +46,7 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for DefPathHashMapRef<'static>
fn decode(d: &mut DecodeContext<'a, 'tcx>) -> DefPathHashMapRef<'static> { fn decode(d: &mut DecodeContext<'a, 'tcx>) -> DefPathHashMapRef<'static> {
let len = d.read_usize(); let len = d.read_usize();
let pos = d.position(); let pos = d.position();
let o = slice_owned(d.blob().clone(), |blob| &blob[pos..pos + len]); let o = d.blob().clone().0.slice(|blob| &blob[pos..pos + len]);
// Although we already have the data we need via the `OwnedSlice`, we still need // Although we already have the data we need via the `OwnedSlice`, we still need
// to advance the `DecodeContext`'s position so it's in a valid state after // to advance the `DecodeContext`'s position so it's in a valid state after

View file

@ -7,7 +7,6 @@ use table::TableBuilder;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_attr as attr; use rustc_attr as attr;
use rustc_data_structures::svh::Svh; use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::MetadataRef;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, DocLinkResMap}; use rustc_hir::def::{CtorKind, DefKind, DocLinkResMap};
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, DefPathHash, StableCrateId}; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, DefPathHash, StableCrateId};

View file

@ -39,5 +39,7 @@ middle_strict_coherence_needs_negative_coherence =
to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled
.label = due to this attribute .label = due to this attribute
middle_requires_lang_item = requires `{$name}` lang_item
middle_const_not_used_in_type_alias = middle_const_not_used_in_type_alias =
const parameter `{$ct}` is part of concrete type but not used in parameter list for the `impl Trait` type alias const parameter `{$ct}` is part of concrete type but not used in parameter list for the `impl Trait` type alias

View file

@ -1,5 +1,5 @@
use rustc_macros::Diagnostic; use rustc_macros::Diagnostic;
use rustc_span::Span; use rustc_span::{Span, Symbol};
use crate::ty::Ty; use crate::ty::Ty;
@ -73,6 +73,14 @@ pub(crate) struct StrictCoherenceNeedsNegativeCoherence {
pub attr_span: Option<Span>, pub attr_span: Option<Span>,
} }
#[derive(Diagnostic)]
#[diag(middle_requires_lang_item)]
pub(crate) struct RequiresLangItem {
#[primary_span]
pub span: Option<Span>,
pub name: Symbol,
}
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(middle_const_not_used_in_type_alias)] #[diag(middle_const_not_used_in_type_alias)]
pub(super) struct ConstNotUsedTraitAlias { pub(super) struct ConstNotUsedTraitAlias {

View file

@ -18,12 +18,8 @@ impl<'tcx> TyCtxt<'tcx> {
/// Returns the `DefId` for a given `LangItem`. /// Returns the `DefId` for a given `LangItem`.
/// If not found, fatally aborts compilation. /// If not found, fatally aborts compilation.
pub fn require_lang_item(self, lang_item: LangItem, span: Option<Span>) -> DefId { pub fn require_lang_item(self, lang_item: LangItem, span: Option<Span>) -> DefId {
self.lang_items().require(lang_item).unwrap_or_else(|err| { self.lang_items().get(lang_item).unwrap_or_else(|| {
if let Some(span) = span { self.sess.emit_fatal(crate::error::RequiresLangItem { span, name: lang_item.name() });
self.sess.span_fatal(span, err.to_string())
} else {
self.sess.fatal(err.to_string())
}
}) })
} }

View file

@ -481,9 +481,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
})))) }))))
} }
ExprKind::OffsetOf { container, fields } => { ExprKind::OffsetOf { container, fields } => block.and(Rvalue::NullaryOp(
block.and(Rvalue::NullaryOp(NullOp::OffsetOf(fields), container)) NullOp::OffsetOf(fields),
} this.tcx.erase_regions(container),
)),
ExprKind::Literal { .. } ExprKind::Literal { .. }
| ExprKind::NamedConst { .. } | ExprKind::NamedConst { .. }

View file

@ -6,7 +6,8 @@ use crate::search_paths::PathKind;
use crate::utils::NativeLibKind; use crate::utils::NativeLibKind;
use crate::Session; use crate::Session;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_data_structures::sync::{self, AppendOnlyIndexVec, MetadataRef, RwLock}; use rustc_data_structures::owned_slice::OwnedSlice;
use rustc_data_structures::sync::{self, AppendOnlyIndexVec, RwLock};
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, StableCrateId, LOCAL_CRATE}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, StableCrateId, LOCAL_CRATE};
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions};
use rustc_span::hygiene::{ExpnHash, ExpnId}; use rustc_span::hygiene::{ExpnHash, ExpnId};
@ -203,8 +204,8 @@ pub enum ExternCrateSource {
/// metadata in library -- this trait just serves to decouple rustc_metadata from /// metadata in library -- this trait just serves to decouple rustc_metadata from
/// the archive reader, which depends on LLVM. /// the archive reader, which depends on LLVM.
pub trait MetadataLoader: std::fmt::Debug { pub trait MetadataLoader: std::fmt::Debug {
fn get_rlib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String>; fn get_rlib_metadata(&self, target: &Target, filename: &Path) -> Result<OwnedSlice, String>;
fn get_dylib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String>; fn get_dylib_metadata(&self, target: &Target, filename: &Path) -> Result<OwnedSlice, String>;
} }
pub type MetadataLoaderDyn = dyn MetadataLoader + Send + Sync + sync::DynSend + sync::DynSync; pub type MetadataLoaderDyn = dyn MetadataLoader + Send + Sync + sync::DynSend + sync::DynSync;

View file

@ -164,6 +164,7 @@ symbols! {
Capture, Capture,
Center, Center,
Clone, Clone,
ConstParamTy,
Context, Context,
Continue, Continue,
Copy, Copy,
@ -1583,6 +1584,7 @@ symbols! {
unrestricted_attribute_tokens, unrestricted_attribute_tokens,
unsafe_block_in_unsafe_fn, unsafe_block_in_unsafe_fn,
unsafe_cell, unsafe_cell,
unsafe_cell_from_mut,
unsafe_no_drop_flag, unsafe_no_drop_flag,
unsafe_pin_internals, unsafe_pin_internals,
unsize, unsize,

View file

@ -2030,6 +2030,27 @@ impl<T> UnsafeCell<T> {
} }
impl<T: ?Sized> UnsafeCell<T> { impl<T: ?Sized> UnsafeCell<T> {
/// Converts from `&mut T` to `&mut UnsafeCell<T>`.
///
/// # Examples
///
/// ```
/// # #![feature(unsafe_cell_from_mut)]
/// use std::cell::UnsafeCell;
///
/// let mut val = 42;
/// let uc = UnsafeCell::from_mut(&mut val);
///
/// *uc.get_mut() -= 1;
/// assert_eq!(*uc.get_mut(), 41);
/// ```
#[inline(always)]
#[unstable(feature = "unsafe_cell_from_mut", issue = "111645")]
pub const fn from_mut(value: &mut T) -> &mut UnsafeCell<T> {
// SAFETY: `UnsafeCell<T>` has the same memory layout as `T` due to #[repr(transparent)].
unsafe { &mut *(value as *mut T as *mut UnsafeCell<T>) }
}
/// Gets a mutable pointer to the wrapped value. /// Gets a mutable pointer to the wrapped value.
/// ///
/// This can be cast to a pointer of any kind. /// This can be cast to a pointer of any kind.

View file

@ -517,8 +517,6 @@ impl CStr {
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// #![feature(cstr_is_empty)]
///
/// use std::ffi::CStr; /// use std::ffi::CStr;
/// # use std::ffi::FromBytesWithNulError; /// # use std::ffi::FromBytesWithNulError;
/// ///
@ -533,7 +531,8 @@ impl CStr {
/// # } /// # }
/// ``` /// ```
#[inline] #[inline]
#[unstable(feature = "cstr_is_empty", issue = "102444")] #[stable(feature = "cstr_is_empty", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "cstr_is_empty", since = "CURRENT_RUSTC_VERSION")]
pub const fn is_empty(&self) -> bool { pub const fn is_empty(&self) -> bool {
// SAFETY: We know there is at least one byte; for empty strings it // SAFETY: We know there is at least one byte; for empty strings it
// is the NUL terminator. // is the NUL terminator.

View file

@ -986,6 +986,14 @@ pub trait PointerLike {}
#[rustc_on_unimplemented(message = "`{Self}` can't be used as a const parameter type")] #[rustc_on_unimplemented(message = "`{Self}` can't be used as a const parameter type")]
pub trait ConstParamTy: StructuralEq {} pub trait ConstParamTy: StructuralEq {}
/// Derive macro generating an impl of the trait `Copy`.
#[rustc_builtin_macro]
#[unstable(feature = "adt_const_params", issue = "95174")]
#[cfg(not(bootstrap))]
pub macro ConstParamTy($item:item) {
/* compiler built-in */
}
// FIXME(generic_const_parameter_types): handle `ty::FnDef`/`ty::Closure` // FIXME(generic_const_parameter_types): handle `ty::FnDef`/`ty::Closure`
// FIXME(generic_const_parameter_types): handle `ty::Tuple` // FIXME(generic_const_parameter_types): handle `ty::Tuple`
marker_impls! { marker_impls! {

View file

@ -289,10 +289,11 @@ fn is_pat_variant(cx: &LateContext<'_>, pat: &Pat<'_>, path: &QPath<'_>, expecte
let Some(id) = cx.typeck_results().qpath_res(path, pat.hir_id).opt_def_id() else { return false }; let Some(id) = cx.typeck_results().qpath_res(path, pat.hir_id).opt_def_id() else { return false };
match expected_item { match expected_item {
Item::Lang(expected_lang_item) => { Item::Lang(expected_lang_item) => cx
let expected_id = cx.tcx.lang_items().require(expected_lang_item).unwrap(); .tcx
cx.tcx.parent(id) == expected_id .lang_items()
}, .get(expected_lang_item)
.map_or(false, |expected_id| cx.tcx.parent(id) == expected_id),
Item::Diag(expected_ty, expected_variant) => { Item::Diag(expected_ty, expected_variant) => {
let ty = cx.typeck_results().pat_ty(pat); let ty = cx.typeck_results().pat_ty(pat);

View file

@ -11,6 +11,13 @@ struct S<T> {
impl<T: ConstParamTy> ConstParamTy for S<T> {} impl<T: ConstParamTy> ConstParamTy for S<T> {}
#[derive(PartialEq, Eq, ConstParamTy)]
struct D<T> {
field: u8,
gen: T,
}
fn check<T: ConstParamTy + ?Sized>() {} fn check<T: ConstParamTy + ?Sized>() {}
fn main() { fn main() {
@ -39,5 +46,8 @@ fn main() {
check::<S<u8>>(); check::<S<u8>>();
check::<S<[&[bool]; 8]>>(); check::<S<[&[bool]; 8]>>();
check::<D<u8>>();
check::<D<[&[bool]; 8]>>();
// FIXME: test tuples // FIXME: test tuples
} }

View file

@ -10,4 +10,8 @@ struct CantParam(NotParam);
impl std::marker::ConstParamTy for CantParam {} impl std::marker::ConstParamTy for CantParam {}
//~^ error: the trait `ConstParamTy` cannot be implemented for this type //~^ error: the trait `ConstParamTy` cannot be implemented for this type
#[derive(std::marker::ConstParamTy, Eq, PartialEq)]
//~^ error: the trait `ConstParamTy` cannot be implemented for this type
struct CantParamDerive(NotParam);
fn main() {} fn main() {}

View file

@ -7,6 +7,17 @@ LL |
LL | impl std::marker::ConstParamTy for CantParam {} LL | impl std::marker::ConstParamTy for CantParam {}
| ^^^^^^^^^ | ^^^^^^^^^
error: aborting due to previous error error[E0204]: the trait `ConstParamTy` cannot be implemented for this type
--> $DIR/const_param_ty_impl_bad_field.rs:13:10
|
LL | #[derive(std::marker::ConstParamTy, Eq, PartialEq)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | struct CantParamDerive(NotParam);
| -------- this field does not implement `ConstParamTy`
|
= note: this error originates in the derive macro `std::marker::ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0204`. For more information about this error, try `rustc --explain E0204`.

View file

@ -10,6 +10,10 @@ struct CantParam(ImplementsConstParamTy);
impl std::marker::ConstParamTy for CantParam {} impl std::marker::ConstParamTy for CantParam {}
//~^ error: the type `CantParam` does not `#[derive(Eq)]` //~^ error: the type `CantParam` does not `#[derive(Eq)]`
#[derive(std::marker::ConstParamTy)]
//~^ error: the type `CantParamDerive` does not `#[derive(Eq)]`
struct CantParamDerive(ImplementsConstParamTy);
fn check<T: std::marker::ConstParamTy>() {} fn check<T: std::marker::ConstParamTy>() {}
fn main() { fn main() {

View file

@ -7,6 +7,16 @@ LL | impl std::marker::ConstParamTy for CantParam {}
note: required by a bound in `ConstParamTy` note: required by a bound in `ConstParamTy`
--> $SRC_DIR/core/src/marker.rs:LL:COL --> $SRC_DIR/core/src/marker.rs:LL:COL
error: aborting due to previous error error[E0277]: the type `CantParamDerive` does not `#[derive(Eq)]`
--> $DIR/const_param_ty_impl_no_structural_eq.rs:13:10
|
LL | #[derive(std::marker::ConstParamTy)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `StructuralEq` is not implemented for `CantParamDerive`
|
note: required by a bound in `ConstParamTy`
--> $SRC_DIR/core/src/marker.rs:LL:COL
= note: this error originates in the derive macro `std::marker::ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`. For more information about this error, try `rustc --explain E0277`.

View file

@ -0,0 +1,33 @@
#![allow(incomplete_features)]
#![feature(adt_const_params, structural_match)]
union Union {
a: u8,
}
impl PartialEq for Union {
fn eq(&self, other: &Union) -> bool {
true
}
}
impl Eq for Union {}
impl std::marker::StructuralEq for Union {}
impl std::marker::ConstParamTy for Union {}
#[derive(std::marker::ConstParamTy)]
//~^ ERROR this trait cannot be derived for unions
union UnionDerive {
a: u8,
}
impl PartialEq for UnionDerive {
fn eq(&self, other: &UnionDerive) -> bool {
true
}
}
impl Eq for UnionDerive {}
impl std::marker::StructuralEq for UnionDerive {}
fn main() {}

View file

@ -0,0 +1,8 @@
error: this trait cannot be derived for unions
--> $DIR/const_param_ty_impl_union.rs:18:10
|
LL | #[derive(std::marker::ConstParamTy)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error

View file

@ -12,6 +12,11 @@ fn main() {
offset_of!(S, f.,); //~ ERROR expected identifier offset_of!(S, f.,); //~ ERROR expected identifier
offset_of!(S, f..); //~ ERROR no rules expected the token offset_of!(S, f..); //~ ERROR no rules expected the token
offset_of!(S, f..,); //~ ERROR no rules expected the token offset_of!(S, f..,); //~ ERROR no rules expected the token
offset_of!(Lt<'static>, bar); // issue #111657
} }
struct S { f: u8, } struct S { f: u8, }
struct Lt<'a> {
bar: &'a (),
}