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);
}
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! {
Clone: clone::expand_deriving_clone,
Copy: bounds::expand_deriving_copy,
ConstParamTy: bounds::expand_deriving_const_param_ty,
Debug: debug::expand_deriving_debug,
Default: default::expand_deriving_default,
Eq: eq::expand_deriving_eq,

View File

@ -966,11 +966,7 @@ fn codegen_panic_inner<'tcx>(
args: &[Value],
span: Span,
) {
let def_id = fx
.tcx
.lang_items()
.require(lang_item)
.unwrap_or_else(|e| fx.tcx.sess.span_fatal(span, e.to_string()));
let def_id = fx.tcx.require_lang_item(lang_item, Some(span));
let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx);
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 rustc_data_structures::memmap::Mmap;
use rustc_data_structures::owned_slice::try_slice_owned;
use rustc_data_structures::sync::MetadataRef;
use rustc_data_structures::owned_slice::{try_slice_owned, OwnedSlice};
use rustc_metadata::fs::METADATA_FILENAME;
use rustc_metadata::EncodedMetadata;
use rustc_session::cstore::MetadataLoader;
@ -39,7 +38,7 @@ pub struct DefaultMetadataLoader;
fn load_metadata_with(
path: &Path,
f: impl for<'a> FnOnce(&'a [u8]) -> Result<&'a [u8], String>,
) -> Result<MetadataRef, String> {
) -> Result<OwnedSlice, String> {
let file =
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 {
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| {
let archive = object::read::archive::ArchiveFile::parse(&*data)
.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"))
}
}

View File

@ -1,3 +1,5 @@
use std::any::Any;
use super::write::WriteBackendMethods;
use super::CodegenObject;
use crate::back::write::TargetMachineFactoryFn;
@ -5,6 +7,7 @@ use crate::{CodegenResults, ModuleCodegen};
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::{DynSend, DynSync};
use rustc_errors::ErrorGuaranteed;
use rustc_metadata::EncodedMetadata;
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::spec::Target;
pub use rustc_data_structures::sync::MetadataRef;
use rustc_data_structures::sync::{DynSend, DynSync};
use std::any::Any;
pub trait BackendTypes {
type Value: CodegenObject;
type Function: CodegenObject;

View File

@ -1,5 +1,6 @@
use std::{borrow::Borrow, ops::Deref};
use crate::sync::Lrc;
// Use our fake Send/Sync traits when on not parallel compiler,
// so that `OwnedSlice` only implements/requires Send/Sync
// for parallel compiler builds.
@ -7,7 +8,7 @@ use crate::sync::{Send, Sync};
/// 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.
///
/// 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
/// and even sound! 🌸
#[derive(Clone)]
pub struct OwnedSlice {
/// This is conceptually a `&'self.owner [u8]`.
bytes: *const [u8],
@ -31,7 +33,7 @@ pub struct OwnedSlice {
// \/
// ⊂(´・◡・⊂ )∘˚˳° (I am the phantom remnant of #97770)
#[expect(dead_code)]
owner: Box<dyn Send + Sync>,
owner: Lrc<dyn Send + Sync>,
}
/// Makes an [`OwnedSlice`] out of an `owner` and a `slicer` function.
@ -72,10 +74,10 @@ where
O: Send + Sync + 'static,
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
// 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.
// 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
// a short lived slice, unrelated to the owner.
let owner = Box::new(owner);
let owner = Lrc::new(owner);
let bytes = slicer(&*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 {
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)]
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)]
unsafe impl Sync for OwnedSlice {}

View File

@ -26,7 +26,7 @@ fn static_storage() {
}
#[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(slice, |s| &s[1..][..4]);
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..]);
}
#[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]
fn try_and_fail() {
let res = try_slice_owned(vec![0], |v| v.get(12..).ok_or(()));

View File

@ -40,7 +40,6 @@
//! [^2] `MTLockRef` is a typedef.
pub use crate::marker::*;
use crate::owned_slice::OwnedSlice;
use std::collections::HashMap;
use std::hash::{BuildHasher, Hash};
use std::ops::{Deref, DerefMut};
@ -92,6 +91,7 @@ mod mode {
}
pub use mode::{is_dyn_thread_safe, set_dyn_thread_safe_mode};
cfg_if! {
if #[cfg(not(parallel_compiler))] {
pub unsafe auto trait Send {}
@ -244,8 +244,6 @@ cfg_if! {
r
}
pub type MetadataRef = OwnedSlice;
pub use std::rc::Rc as Lrc;
pub use std::rc::Weak as Weak;
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.
/// It is only useful when you are running in a single thread
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.
use crate::def_id::DefId;
use crate::errors::LangItemError;
use crate::{MethodKind, Target};
use rustc_ast as ast;
@ -42,13 +41,6 @@ impl LanguageItems {
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)> + '_ {
self.items
.iter()

View File

@ -30,7 +30,6 @@ pub mod def;
pub mod def_path_hash_map;
pub mod definitions;
pub mod diagnostic_items;
pub mod errors;
pub use rustc_span::def_id;
mod hir;
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 unsize_trait = tcx.lang_items().require(LangItem::Unsize).unwrap_or_else(|err| {
tcx.sess.fatal(format!("`CoerceUnsized` implementation {}", err.to_string()));
});
let unsize_trait = tcx.require_lang_item(LangItem::Unsize, Some(span));
let source = tcx.type_of(impl_did).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::owned_slice::slice_owned;
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::MetadataRef;
use rustc_errors::{DiagnosticArgValue, FatalError, IntoDiagnosticArg};
use rustc_fs_util::try_canonicalize;
use rustc_session::config::{self, CrateType};
@ -782,7 +781,7 @@ fn get_metadata_section<'p>(
if !filename.exists() {
return Err(MetadataError::NotPresent(filename));
}
let raw_bytes: MetadataRef = match flavor {
let raw_bytes = match flavor {
CrateFlavor::Rlib => {
loader.get_rlib_metadata(target, filename).map_err(MetadataError::LoadFailure)?
}
@ -843,7 +842,7 @@ fn get_metadata_section<'p>(
slice_owned(mmap, Deref::deref)
}
};
let blob = MetadataBlob::new(raw_bytes);
let blob = MetadataBlob(raw_bytes);
if blob.is_compatible() {
Ok(blob)
} else {

View File

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

View File

@ -1,6 +1,5 @@
use crate::rmeta::DecodeContext;
use crate::rmeta::EncodeContext;
use rustc_data_structures::owned_slice::slice_owned;
use rustc_data_structures::owned_slice::OwnedSlice;
use rustc_hir::def_path_hash_map::{Config as HashMapConfig, DefPathHashMap};
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> {
let len = d.read_usize();
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
// 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_attr as attr;
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::MetadataRef;
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, DocLinkResMap};
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
.label = due to this attribute
middle_requires_lang_item = requires `{$name}` lang_item
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

View File

@ -1,5 +1,5 @@
use rustc_macros::Diagnostic;
use rustc_span::Span;
use rustc_span::{Span, Symbol};
use crate::ty::Ty;
@ -73,6 +73,14 @@ pub(crate) struct StrictCoherenceNeedsNegativeCoherence {
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)]
#[diag(middle_const_not_used_in_type_alias)]
pub(super) struct ConstNotUsedTraitAlias {

View File

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

View File

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

View File

@ -6,7 +6,8 @@ use crate::search_paths::PathKind;
use crate::utils::NativeLibKind;
use crate::Session;
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::definitions::{DefKey, DefPath, DefPathHash, Definitions};
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
/// the archive reader, which depends on LLVM.
pub trait MetadataLoader: std::fmt::Debug {
fn get_rlib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String>;
fn get_dylib_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<OwnedSlice, String>;
}
pub type MetadataLoaderDyn = dyn MetadataLoader + Send + Sync + sync::DynSend + sync::DynSync;

View File

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

View File

@ -2030,6 +2030,27 @@ impl<T> 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.
///
/// This can be cast to a pointer of any kind.

View File

@ -517,8 +517,6 @@ impl CStr {
/// # Examples
///
/// ```
/// #![feature(cstr_is_empty)]
///
/// use std::ffi::CStr;
/// # use std::ffi::FromBytesWithNulError;
///
@ -533,7 +531,8 @@ impl CStr {
/// # }
/// ```
#[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 {
// SAFETY: We know there is at least one byte; for empty strings it
// 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")]
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::Tuple`
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 };
match expected_item {
Item::Lang(expected_lang_item) => {
let expected_id = cx.tcx.lang_items().require(expected_lang_item).unwrap();
cx.tcx.parent(id) == expected_id
},
Item::Lang(expected_lang_item) => cx
.tcx
.lang_items()
.get(expected_lang_item)
.map_or(false, |expected_id| cx.tcx.parent(id) == expected_id),
Item::Diag(expected_ty, expected_variant) => {
let ty = cx.typeck_results().pat_ty(pat);

View File

@ -11,6 +11,13 @@ struct 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 main() {
@ -39,5 +46,8 @@ fn main() {
check::<S<u8>>();
check::<S<[&[bool]; 8]>>();
check::<D<u8>>();
check::<D<[&[bool]; 8]>>();
// FIXME: test tuples
}

View File

@ -10,4 +10,8 @@ struct CantParam(NotParam);
impl std::marker::ConstParamTy for CantParam {}
//~^ 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() {}

View File

@ -7,6 +7,17 @@ LL |
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`.

View File

@ -10,6 +10,10 @@ struct CantParam(ImplementsConstParamTy);
impl std::marker::ConstParamTy for CantParam {}
//~^ 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 main() {

View File

@ -7,6 +7,16 @@ LL | impl std::marker::ConstParamTy for CantParam {}
note: required by a bound in `ConstParamTy`
--> $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`.

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 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 Lt<'a> {
bar: &'a (),
}