"compiletest_rs",
"env_logger 0.9.0",
"getrandom 0.2.0",
- "hex 0.4.2",
"libc",
"log",
"measureme 9.1.2",
let mut ty = local_decl.ty;
if local_decl.source_info.span.desugaring_kind() == Some(DesugaringKind::ForLoop) {
if let ty::Adt(adt, substs) = local_decl.ty.kind() {
- if tcx.is_diagnostic_item(sym::Option, adt.did) {
+ if tcx.is_diagnostic_item(sym::Option, adt.did()) {
// in for loop desugaring, only look at the `Some(..)` inner type
ty = substs.type_at(0);
}
// If type is an ADT that implements Drop, then
// simplify output by reporting just the ADT name.
ty::Adt(adt, _substs) if adt.has_dtor(tcx) && !adt.is_box() => {
- ("`Drop` code", format!("type `{}`", tcx.def_path_str(adt.did)))
+ ("`Drop` code", format!("type `{}`", tcx.def_path_str(adt.did())))
}
// Otherwise, just report the whole type (and use
ty::Adt(def, _) => {
let variant = if let Some(idx) = variant_index {
assert!(def.is_enum());
- &def.variants[idx]
+ &def.variant(idx)
} else {
def.non_enum_variant()
};
BorrowedContentSource::DerefMutableRef => "a mutable reference".to_string(),
BorrowedContentSource::OverloadedDeref(ty) => ty
.ty_adt_def()
- .and_then(|adt| match tcx.get_diagnostic_name(adt.did)? {
+ .and_then(|adt| match tcx.get_diagnostic_name(adt.did())? {
name @ (sym::Rc | sym::Arc) => Some(format!("an `{}`", name)),
_ => None,
})
}
BorrowedContentSource::OverloadedDeref(ty) => ty
.ty_adt_def()
- .and_then(|adt| match tcx.get_diagnostic_name(adt.did)? {
+ .and_then(|adt| match tcx.get_diagnostic_name(adt.did())? {
name @ (sym::Rc | sym::Arc) => Some(format!("an `{}`", name)),
_ => None,
})
};
let ty = move_place.ty(self.body, self.infcx.tcx).ty;
let def_id = match *ty.kind() {
- ty::Adt(self_def, _) => self_def.did,
+ ty::Adt(self_def, _) => self_def.did(),
ty::Foreign(def_id)
| ty::FnDef(def_id, _)
| ty::Closure(def_id, _)
ty::Adt(adt, substs) => {
let generic_arg = substs[param_index as usize];
let identity_substs =
- InternalSubsts::identity_for_item(self.infcx.tcx, adt.did);
- let base_ty = self.infcx.tcx.mk_adt(adt, identity_substs);
+ InternalSubsts::identity_for_item(self.infcx.tcx, adt.did());
+ let base_ty = self.infcx.tcx.mk_adt(*adt, identity_substs);
let base_generic_arg = identity_substs[param_index as usize];
let adt_desc = adt.descr();
"returns a closure that contains a reference to a captured variable, which then \
escapes the closure body"
}
- ty::Adt(def, _) if self.infcx.tcx.is_diagnostic_item(sym::gen_future, def.did) => {
+ ty::Adt(def, _) if self.infcx.tcx.is_diagnostic_item(sym::gen_future, def.did()) => {
"returns an `async` block that contains a reference to a captured variable, which then \
escapes the closure body"
}
}
ProjectionElem::Downcast(maybe_name, index) => match base_ty.kind() {
ty::Adt(adt_def, _substs) if adt_def.is_enum() => {
- if index.as_usize() >= adt_def.variants.len() {
+ if index.as_usize() >= adt_def.variants().len() {
PlaceTy::from_ty(span_mirbug_and_err!(
self,
place,
"cast to variant #{:?} but enum only has {:?}",
index,
- adt_def.variants.len()
+ adt_def.variants().len()
))
} else {
PlaceTy { ty: base_ty, variant_index: Some(index) }
let (variant, substs) = match base_ty {
PlaceTy { ty, variant_index: Some(variant_index) } => match *ty.kind() {
- ty::Adt(adt_def, substs) => (&adt_def.variants[variant_index], substs),
+ ty::Adt(adt_def, substs) => (adt_def.variant(variant_index), substs),
ty::Generator(def_id, substs, _) => {
let mut variants = substs.as_generator().state_tys(def_id, tcx);
let Some(mut variant) = variants.nth(variant_index.into()) else {
},
PlaceTy { ty, variant_index: None } => match *ty.kind() {
ty::Adt(adt_def, substs) if !adt_def.is_enum() => {
- (&adt_def.variants[VariantIdx::new(0)], substs)
+ (adt_def.variant(VariantIdx::new(0)), substs)
}
ty::Closure(_, substs) => {
return match substs
);
}
};
- if variant_index.as_usize() >= adt.variants.len() {
+ if variant_index.as_usize() >= adt.variants().len() {
span_bug!(
stmt.source_info.span,
"bad set discriminant ({:?} = {:?}): value of of range",
match *ak {
AggregateKind::Adt(adt_did, variant_index, substs, _, active_field_index) => {
let def = tcx.adt_def(adt_did);
- let variant = &def.variants[variant_index];
+ let variant = &def.variant(variant_index);
let adj_field_index = active_field_index.unwrap_or(field_index);
if let Some(field) = variant.fields.get(adj_field_index) {
Ok(self.normalize(field.ty(tcx, substs), location))
pointer_ty(tcx)
}
}
- ty::Adt(adt_def, _) if adt_def.repr.simd() => {
+ ty::Adt(adt_def, _) if adt_def.repr().simd() => {
let (element, count) = match &tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap().abi
{
Abi::Vector { element, count } => (element.clone(), *count),
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
assert_eq!(def_a, def_b);
- for i in 0..def_a.variants[VariantIdx::new(0)].fields.len() {
+ for i in 0..def_a.variant(VariantIdx::new(0)).fields.len() {
let src_f = src.value_field(fx, mir::Field::new(i));
let dst_f = dst.place_field(fx, mir::Field::new(i));
// Packed types ignore the alignment of their fields.
if let ty::Adt(def, _) = layout.ty.kind() {
- if def.repr.packed() {
+ if def.repr().packed() {
unsized_align = sized_align;
}
}
}
match field_layout.ty.kind() {
ty::Slice(..) | ty::Str | ty::Foreign(..) => simple(fx),
- ty::Adt(def, _) if def.repr.packed() => {
+ ty::Adt(def, _) if def.repr().packed() => {
assert_eq!(layout.align.abi.bytes(), 1);
simple(fx)
}
// dyn for<'r> Trait<'r> -> dyn Trait<'_> is allowed
}
(&ty::Adt(adt_def_a, substs_a), &ty::Adt(adt_def_b, substs_b))
- if adt_def_a.did == adt_def_b.did =>
+ if adt_def_a.did() == adt_def_b.did() =>
{
let mut types_a = substs_a.types();
let mut types_b = substs_b.types();
if let (&ty::Adt(def, _), &Variants::Single { index }) =
(layout.ty.kind(), &layout.variants)
{
- if def.is_enum() && !def.variants.is_empty() {
- write!(&mut name, "::{}", def.variants[index].name).unwrap();
+ if def.is_enum() && !def.variants().is_empty() {
+ write!(&mut name, "::{}", def.variant(index).name).unwrap();
}
}
if let (&ty::Generator(_, _, _), &Variants::Single { index }) =
AdtKind::Struct => prepare_struct_metadata(cx, t, unique_type_id).finalize(cx),
AdtKind::Union => prepare_union_metadata(cx, t, unique_type_id).finalize(cx),
AdtKind::Enum => {
- prepare_enum_metadata(cx, t, def.did, unique_type_id, vec![]).finalize(cx)
+ prepare_enum_metadata(cx, t, def.did(), unique_type_id, vec![]).finalize(cx)
}
},
ty::Tuple(tys) => {
let struct_name = compute_debuginfo_type_name(cx.tcx, struct_type, false);
let (struct_def_id, variant) = match struct_type.kind() {
- ty::Adt(def, _) => (def.did, def.non_enum_variant()),
+ ty::Adt(def, _) => (def.did(), def.non_enum_variant()),
_ => bug!("prepare_struct_metadata on a non-ADT"),
};
let union_name = compute_debuginfo_type_name(cx.tcx, union_type, false);
let (union_def_id, variant) = match union_type.kind() {
- ty::Adt(def, _) => (def.did, def.non_enum_variant()),
+ ty::Adt(def, _) => (def.did(), def.non_enum_variant()),
_ => bug!("prepare_union_metadata on a non-ADT"),
};
};
let variant_info_for = |index: VariantIdx| match *self.enum_type.kind() {
- ty::Adt(adt, _) => VariantInfo::Adt(&adt.variants[index], index),
+ ty::Adt(adt, _) => VariantInfo::Adt(&adt.variant(index), index),
ty::Generator(def_id, _, _) => {
let (generator_layout, generator_saved_local_names) =
generator_variant_info_data.as_ref().unwrap();
match self.layout.variants {
Variants::Single { index } => {
if let ty::Adt(adt, _) = self.enum_type.kind() {
- if adt.variants.is_empty() {
+ if adt.variants().is_empty() {
return vec![];
}
}
let discriminant_type_metadata = |discr: Primitive| {
let enumerators_metadata: Vec<_> = match enum_type.kind() {
- ty::Adt(def, _) => iter::zip(def.discriminants(tcx), &def.variants)
+ ty::Adt(def, _) => iter::zip(def.discriminants(tcx), def.variants())
.map(|((_, discr), v)| {
let name = v.name.as_str();
let is_unsigned = match discr.ty.kind() {
fn compute_type_parameters<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> &'ll DIArray {
if let ty::Adt(def, substs) = *ty.kind() {
if substs.types().next().is_some() {
- let generics = cx.tcx.generics_of(def.did);
+ let generics = cx.tcx.generics_of(def.did());
let names = get_parameter_names(cx, generics);
let template_params: Vec<_> = iter::zip(substs, names)
.filter_map(|(kind, name)| {
{
Some(type_metadata(cx, impl_self_ty))
} else {
- Some(namespace::item_namespace(cx, def.did))
+ Some(namespace::item_namespace(cx, def.did()))
}
}
_ => None,
if let (&ty::Adt(def, _), &Variants::Single { index }) =
(layout.ty.kind(), &layout.variants)
{
- if def.is_enum() && !def.variants.is_empty() {
- write!(&mut name, "::{}", def.variants[index].name).unwrap();
+ if def.is_enum() && !def.variants().is_empty() {
+ write!(&mut name, "::{}", def.variant(index).name).unwrap();
}
}
if let (&ty::Generator(_, _, _), &Variants::Single { index }) =
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
assert_eq!(def_a, def_b);
- for i in 0..def_a.variants[VariantIdx::new(0)].fields.len() {
+ for i in 0..def_a.variant(VariantIdx::new(0)).fields.len() {
let src_f = src.project_field(bx, i);
let dst_f = dst.project_field(bx, i);
if def.is_enum() && cpp_like_debuginfo {
msvc_enum_fallback(tcx, t, def, substs, output, visited);
} else {
- push_item_name(tcx, def.did, qualified, output);
+ push_item_name(tcx, def.did(), qualified, output);
push_generic_params_internal(tcx, substs, output, visited);
}
}
fn msvc_enum_fallback<'tcx>(
tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>,
- def: &AdtDef,
+ def: AdtDef<'tcx>,
substs: SubstsRef<'tcx>,
output: &mut String,
visited: &mut FxHashSet<Ty<'tcx>>,
) {
- let layout = tcx.layout_of(tcx.param_env(def.did).and(ty)).expect("layout error");
+ let layout = tcx.layout_of(tcx.param_env(def.did()).and(ty)).expect("layout error");
output.push_str("enum$<");
- push_item_name(tcx, def.did, true, output);
+ push_item_name(tcx, def.did(), true, output);
push_generic_params_internal(tcx, substs, output, visited);
if let Variants::Multiple {
let max = dataful_discriminant_range.end;
let max = tag.value.size(&tcx).truncate(max);
- let dataful_variant_name = def.variants[*dataful_variant].name.as_str();
+ let dataful_variant_name = def.variant(*dataful_variant).name.as_str();
output.push_str(&format!(", {}, {}, {}", min, max, dataful_variant_name));
} else if let Variants::Single { index: variant_idx } = &layout.variants {
// Uninhabited enums can't be constructed and should never need to be visualized so
// skip this step for them.
- if def.variants.len() != 0 {
- let variant = def.variants[*variant_idx].name.as_str();
+ if def.variants().len() != 0 {
+ let variant = def.variant(*variant_idx).name.as_str();
output.push_str(&format!(", {}", variant));
}
// Packed types ignore the alignment of their fields.
if let ty::Adt(def, _) = t.kind() {
- if def.repr.packed() {
+ if def.repr().packed() {
unsized_align = sized_align;
}
}
.ty;
let (llptr, llextra) = match self.val {
OperandValue::Immediate(llptr) => (llptr, None),
- OperandValue::Pair(llptr, llextra) => (llptr, Some(llextra)),
+ OperandValue::Pair(llptr, llextra) => {
+ // if the box's allocator isn't a ZST, then "llextra" is actually the allocator
+ if self.layout.ty.is_box() && !self.layout.field(cx, 1).is_zst() {
+ (llptr, None)
+ } else {
+ (llptr, Some(llextra))
+ }
+ }
OperandValue::Ref(..) => bug!("Deref of by-Ref operand {:?}", self),
};
let layout = cx.layout_of(projected_ty);
_ if !field.is_unsized() => return simple(),
ty::Slice(..) | ty::Str | ty::Foreign(..) => return simple(),
ty::Adt(def, _) => {
- if def.repr.packed() {
+ if def.repr().packed() {
// FIXME(eddyb) generalize the adjustment when we
// start supporting packing to larger alignments.
assert_eq!(self.layout.align.abi.bytes(), 1);
ty::Array(_, len) => branches(usize::try_from(len.eval_usize(ecx.tcx.tcx, ecx.param_env)).unwrap(), None),
ty::Adt(def, _) => {
- if def.variants.is_empty() {
+ if def.variants().is_empty() {
bug!("uninhabited types should have errored and never gotten converted to valtree")
}
let variant = ecx.read_discriminant(&place.into()).unwrap().1;
- branches(def.variants[variant].fields.len(), def.is_enum().then_some(variant))
+ branches(def.variant(variant).fields.len(), def.is_enum().then_some(variant))
}
ty::Never
// Checks if we have any variants, to avoid downcasting to a non-existing variant (when
// there are no variants `read_discriminant` successfully returns a non-existing variant
// index).
- ty::Adt(def, _) if def.variants.is_empty() => throw_ub!(Unreachable),
+ ty::Adt(def, _) if def.variants().is_empty() => throw_ub!(Unreachable),
ty::Adt(def, _) => {
let variant = ecx.read_discriminant(&op)?.1;
let down = ecx.operand_downcast(&op, variant)?;
- (def.variants[variant].fields.len(), Some(variant), down)
+ (def.variant(variant).fields.len(), Some(variant), down)
}
ty::Tuple(substs) => (substs.len(), None, op),
_ => bug!("cannot destructure constant {:?}", val),
}
if let Some(def) = mplace.layout.ty.ty_adt_def() {
- if Some(def.did) == self.ecx.tcx.lang_items().unsafe_cell_type() {
+ if Some(def.did()) == self.ecx.tcx.lang_items().unsafe_cell_type() {
// We are crossing over an `UnsafeCell`, we can mutate again. This means that
// References we encounter inside here are interned as pointing to mutable
// allocations.
}
sym::variant_count => match tp_ty.kind() {
// Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.
- ty::Adt(ref adt, _) => ConstValue::from_machine_usize(adt.variants.len() as u64, &tcx),
+ ty::Adt(ref adt, _) => {
+ ConstValue::from_machine_usize(adt.variants().len() as u64, &tcx)
+ }
ty::Projection(_)
| ty::Opaque(_, _)
| ty::Param(_)
self.write_pointer(offset_ptr, dest)?;
}
sym::ptr_offset_from => {
- let a = self.read_immediate(&args[0])?.to_scalar()?;
- let b = self.read_immediate(&args[1])?.to_scalar()?;
+ let a = self.read_pointer(&args[0])?;
+ let b = self.read_pointer(&args[1])?;
// Special case: if both scalars are *equal integers*
// and not null, we pretend there is an allocation of size 0 right there,
// and their offset is 0. (There's never a valid object at null, making it an
// exception from the exception.)
// This is the dual to the special exception for offset-by-0
- // in the inbounds pointer offset operation (see the Miri code, `src/operator.rs`).
- //
- // Control flow is weird because we cannot early-return (to reach the
- // `go_to_block` at the end).
- let done = if let (Ok(a), Ok(b)) = (a.try_to_int(), b.try_to_int()) {
- let a = a.try_to_machine_usize(*self.tcx).unwrap();
- let b = b.try_to_machine_usize(*self.tcx).unwrap();
- if a == b && a != 0 {
+ // in the inbounds pointer offset operation (see `ptr_offset_inbounds` below).
+ match (self.memory.ptr_try_get_alloc(a), self.memory.ptr_try_get_alloc(b)) {
+ (Err(a), Err(b)) if a == b && a != 0 => {
+ // Both are the same non-null integer.
self.write_scalar(Scalar::from_machine_isize(0, self), dest)?;
- true
- } else {
- false
}
- } else {
- false
- };
-
- if !done {
- // General case: we need two pointers.
- let a = self.scalar_to_ptr(a);
- let b = self.scalar_to_ptr(b);
- let (a_alloc_id, a_offset, _) = self.memory.ptr_get_alloc(a)?;
- let (b_alloc_id, b_offset, _) = self.memory.ptr_get_alloc(b)?;
- if a_alloc_id != b_alloc_id {
- throw_ub_format!(
- "ptr_offset_from cannot compute offset of pointers into different \
- allocations.",
- );
+ (Err(offset), _) | (_, Err(offset)) => {
+ throw_ub!(DanglingIntPointer(offset, CheckInAllocMsg::OffsetFromTest));
+ }
+ (Ok((a_alloc_id, a_offset, _)), Ok((b_alloc_id, b_offset, _))) => {
+ // Both are pointers. They must be into the same allocation.
+ if a_alloc_id != b_alloc_id {
+ throw_ub_format!(
+ "ptr_offset_from cannot compute offset of pointers into different \
+ allocations.",
+ );
+ }
+ // And they must both be valid for zero-sized accesses ("in-bounds or one past the end").
+ self.memory.check_ptr_access_align(
+ a,
+ Size::ZERO,
+ Align::ONE,
+ CheckInAllocMsg::OffsetFromTest,
+ )?;
+ self.memory.check_ptr_access_align(
+ b,
+ Size::ZERO,
+ Align::ONE,
+ CheckInAllocMsg::OffsetFromTest,
+ )?;
+
+ // Compute offset.
+ let usize_layout = self.layout_of(self.tcx.types.usize)?;
+ let isize_layout = self.layout_of(self.tcx.types.isize)?;
+ let a_offset = ImmTy::from_uint(a_offset.bytes(), usize_layout);
+ let b_offset = ImmTy::from_uint(b_offset.bytes(), usize_layout);
+ let (val, _overflowed, _ty) =
+ self.overflowing_binary_op(BinOp::Sub, &a_offset, &b_offset)?;
+ let pointee_layout = self.layout_of(substs.type_at(0))?;
+ let val = ImmTy::from_scalar(val, isize_layout);
+ let size = ImmTy::from_int(pointee_layout.size.bytes(), isize_layout);
+ self.exact_div(&val, &size, dest)?;
}
- let usize_layout = self.layout_of(self.tcx.types.usize)?;
- let isize_layout = self.layout_of(self.tcx.types.isize)?;
- let a_offset = ImmTy::from_uint(a_offset.bytes(), usize_layout);
- let b_offset = ImmTy::from_uint(b_offset.bytes(), usize_layout);
- let (val, _overflowed, _ty) =
- self.overflowing_binary_op(BinOp::Sub, &a_offset, &b_offset)?;
- let pointee_layout = self.layout_of(substs.type_at(0))?;
- let val = ImmTy::from_scalar(val, isize_layout);
- let size = ImmTy::from_int(pointee_layout.size.bytes(), isize_layout);
- self.exact_div(&val, &size, dest)?;
}
}
+use rustc_data_structures::intern::Interned;
use rustc_hir::def_id::CrateNum;
use rustc_hir::definitions::DisambiguatedDefPathData;
use rustc_middle::mir::interpret::{Allocation, ConstAllocation};
}
// Types with identity (print the module path).
- ty::Adt(&ty::AdtDef { did: def_id, .. }, substs)
+ ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), substs)
| ty::FnDef(def_id, substs)
| ty::Opaque(def_id, substs)
| ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs })
CheckInAllocMsg::DerefTest | CheckInAllocMsg::MemoryAccessTest => {
AllocCheck::Dereferenceable
}
- CheckInAllocMsg::PointerArithmeticTest | CheckInAllocMsg::InboundsTest => {
- AllocCheck::Live
- }
+ CheckInAllocMsg::PointerArithmeticTest
+ | CheckInAllocMsg::OffsetFromTest
+ | CheckInAllocMsg::InboundsTest => AllocCheck::Live,
};
let (size, align) = self.get_size_and_align(alloc_id, check)?;
Ok((size, align, ()))
.ty
.ty_adt_def()
.expect("tagged layout for non adt")
- .variants
+ .variants()
.len();
assert!(usize::try_from(variant_index).unwrap() < variants_len);
VariantIdx::from_u32(variant_index)
match layout.variants {
Variants::Single { index } => {
// Inside a variant
- PathElem::Field(def.variants[index].fields[field].name)
+ PathElem::Field(def.variant(index).fields[field].name)
}
Variants::Multiple { .. } => bug!("we handled variants above"),
}
new_op: &OpTy<'tcx, M::PointerTag>,
) -> InterpResult<'tcx> {
let name = match old_op.layout.ty.kind() {
- ty::Adt(adt, _) => PathElem::Variant(adt.variants[variant_id].name),
+ ty::Adt(adt, _) => PathElem::Variant(adt.variant(variant_id).name),
// Generators also have variants
ty::Generator(..) => PathElem::GeneratorState(variant_id),
_ => bug!("Unexpected type with variant: {:?}", old_op.layout.ty),
// Special check preventing `UnsafeCell` in the inner part of constants
if let Some(def) = op.layout.ty.ty_adt_def() {
if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { inner: true, .. }))
- && Some(def.did) == self.ecx.tcx.lang_items().unsafe_cell_type()
+ && Some(def.did()) == self.ecx.tcx.lang_items().unsafe_cell_type()
{
throw_validation_failure!(self.path, { "`UnsafeCell` in a `const`" });
}
/// Returning `true` for `in_adt_inherently` but `false` for `in_any_value_of_ty` is unsound.
fn in_adt_inherently<'tcx>(
cx: &ConstCx<'_, 'tcx>,
- adt: &'tcx AdtDef,
+ adt: AdtDef<'tcx>,
substs: SubstsRef<'tcx>,
) -> bool;
}
fn in_adt_inherently<'tcx>(
cx: &ConstCx<'_, 'tcx>,
- adt: &'tcx AdtDef,
+ adt: AdtDef<'tcx>,
_: SubstsRef<'tcx>,
) -> bool {
// Exactly one type, `UnsafeCell`, has the `HasMutInterior` qualif inherently.
// It arises structurally for all other types.
- Some(adt.did) == cx.tcx.lang_items().unsafe_cell_type()
+ Some(adt.did()) == cx.tcx.lang_items().unsafe_cell_type()
}
}
fn in_adt_inherently<'tcx>(
cx: &ConstCx<'_, 'tcx>,
- adt: &'tcx AdtDef,
+ adt: AdtDef<'tcx>,
_: SubstsRef<'tcx>,
) -> bool {
adt.has_dtor(cx.tcx)
fn in_adt_inherently<'tcx>(
cx: &ConstCx<'_, 'tcx>,
- adt: &'tcx AdtDef,
+ adt: AdtDef<'tcx>,
_: SubstsRef<'tcx>,
) -> bool {
adt.has_non_const_dtor(cx.tcx)
fn in_adt_inherently<'tcx>(
cx: &ConstCx<'_, 'tcx>,
- adt: &'tcx AdtDef,
+ adt: AdtDef<'tcx>,
substs: SubstsRef<'tcx>,
) -> bool {
let ty = cx.tcx.mk_ty(ty::Adt(adt, substs));
ProjectionElem::Field(..) => {
let ty = place_base.ty(local_decls, tcx).ty;
match ty.kind() {
- ty::Adt(def, _) => return def.repr.pack,
+ ty::Adt(def, _) => return def.repr().pack,
_ => {}
}
}
.parent(method_did)
.filter(|did| tcx.def_kind(*did) == rustc_hir::def::DefKind::Impl)
.and_then(|did| match tcx.type_of(did).kind() {
- ty::Adt(def, ..) => Some(def.did),
+ ty::Adt(def, ..) => Some(def.did()),
_ => None,
});
let is_option_or_result = parent_self_ty.map_or(false, |def_id| {
/// An unzipping of `TokenTree`s... see the `stack` field of `MatcherPos`.
///
-/// This is used by `inner_parse_loop` to keep track of delimited submatchers that we have
+/// This is used by `parse_tt_inner` to keep track of delimited submatchers that we have
/// descended into.
#[derive(Clone)]
struct MatcherTtFrame<'tt> {
}
Occupied(..) => return Err((sp, format!("duplicated bind name: {}", bind_name))),
},
- // FIXME(c410-f3r) MetaVar and MetaVarExpr should be handled instead of being ignored
- // https://github.com/rust-lang/rust/issues/9390
- TokenTree::MetaVar(..) | TokenTree::MetaVarExpr(..) | TokenTree::Token(..) => {}
+ TokenTree::Token(..) => (),
+ TokenTree::MetaVar(..) | TokenTree::MetaVarExpr(..) => unreachable!(),
}
Ok(())
/// successful execution of this function.
/// - `next_items`: the set of newly generated items. These are used to replenish `cur_items` in
/// the function `parse`.
-/// - `eof_items`: the set of items that would be valid if this was the EOF.
/// - `bb_items`: the set of items that are waiting for the black-box parser.
/// - `token`: the current token of the parser.
///
/// # Returns
///
-/// A `ParseResult`. Note that matches are kept track of through the items generated.
-fn inner_parse_loop<'root, 'tt>(
+/// `Some(result)` if everything is finished, `None` otherwise. Note that matches are kept track of
+/// through the items generated.
+fn parse_tt_inner<'root, 'tt>(
sess: &ParseSess,
+ ms: &[TokenTree],
cur_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>,
- next_items: &mut Vec<MatcherPosHandle<'root, 'tt>>,
+ next_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>,
bb_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>,
- eof_items: &mut EofItems<'root, 'tt>,
token: &Token,
-) -> Result<(), (rustc_span::Span, String)> {
+) -> Option<NamedParseResult> {
+ // Matcher positions that would be valid if the macro invocation was over now
+ let mut eof_items = EofItems::None;
+
// Pop items from `cur_items` until it is empty.
while let Some(mut item) = cur_items.pop() {
// When unzipped trees end, remove them. This corresponds to backtracking out of a
// then we could be at the end of a sequence or at the beginning of the next
// repetition.
if let Some(repetition) = &item.repetition {
+ debug_assert!(matches!(item.top_elts, Tt(TokenTree::Sequence(..))));
+
// At this point, regardless of whether there is a separator, we should add all
// matches from the complete repetition of the sequence to the shared, top-level
// `matches` list (actually, `up.matches`, which could itself not be the top-level,
} else {
// If we are not in a repetition, then being at the end of a matcher means that we
// have reached the potential end of the input.
- *eof_items = match eof_items {
+ eof_items = match eof_items {
EofItems::None => EofItems::One(item),
EofItems::One(_) | EofItems::Multiple => EofItems::Multiple,
}
// We need to match a metavar (but the identifier is invalid)... this is an error
TokenTree::MetaVarDecl(span, _, None) => {
if sess.missing_fragment_specifiers.borrow_mut().remove(&span).is_some() {
- return Err((span, "missing fragment specifier".to_string()));
+ return Some(Error(span, "missing fragment specifier".to_string()));
}
}
// rules. NOTE that this is not necessarily an error unless _all_ items in
// `cur_items` end up doing this. There may still be some other matchers that do
// end up working out.
- TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarExpr(..) => {}
+ TokenTree::Token(..) => {}
+
+ TokenTree::MetaVar(..) | TokenTree::MetaVarExpr(..) => unreachable!(),
}
}
}
- // Yay a successful parse (so far)!
- Ok(())
+ // If we reached the EOF, check that there is EXACTLY ONE possible matcher. Otherwise,
+ // either the parse is ambiguous (which should never happen) or there is a syntax error.
+ if *token == token::Eof {
+ Some(match eof_items {
+ EofItems::One(mut eof_item) => {
+ let matches =
+ eof_item.matches.iter_mut().map(|dv| Lrc::make_mut(dv).pop().unwrap());
+ nameize(sess, ms, matches)
+ }
+ EofItems::Multiple => {
+ Error(token.span, "ambiguity: multiple successful parses".to_string())
+ }
+ EofItems::None => Failure(
+ Token::new(
+ token::Eof,
+ if token.span.is_dummy() { token.span } else { token.span.shrink_to_hi() },
+ ),
+ "missing tokens in macro arguments",
+ ),
+ })
+ } else {
+ None
+ }
}
/// Use the given sequence of token trees (`ms`) as a matcher. Match the token
macro_name: Ident,
) -> NamedParseResult {
// A queue of possible matcher positions. We initialize it with the matcher position in which
- // the "dot" is before the first token of the first token tree in `ms`. `inner_parse_loop` then
+ // the "dot" is before the first token of the first token tree in `ms`. `parse_tt_inner` then
// processes all of these possible matcher positions and produces possible next positions into
// `next_items`. After some post-processing, the contents of `next_items` replenish `cur_items`
// and we start over again.
// there are frequently *no* others! -- are allocated on the heap.
let mut initial = MatcherPos::new(ms);
let mut cur_items = smallvec![MatcherPosHandle::Ref(&mut initial)];
- let mut next_items = Vec::new();
loop {
- assert!(next_items.is_empty());
+ let mut next_items = SmallVec::new();
// Matcher positions black-box parsed by parser.rs (`parser`)
let mut bb_items = SmallVec::new();
- // Matcher positions that would be valid if the macro invocation was over now
- let mut eof_items = EofItems::None;
-
// Process `cur_items` until either we have finished the input or we need to get some
// parsing from the black-box parser done. The result is that `next_items` will contain a
// bunch of possible next matcher positions in `next_items`.
- match inner_parse_loop(
+ if let Some(result) = parse_tt_inner(
parser.sess,
+ ms,
&mut cur_items,
&mut next_items,
&mut bb_items,
- &mut eof_items,
&parser.token,
) {
- Ok(()) => {}
- Err((sp, msg)) => return Error(sp, msg),
+ return result;
}
- // inner parse loop handled all cur_items, so it's empty
+ // `parse_tt_inner` handled all cur_items, so it's empty.
assert!(cur_items.is_empty());
- // We need to do some post processing after the `inner_parse_loop`.
+ // We need to do some post processing after the `parse_tt_inner`.
//
// Error messages here could be improved with links to original rules.
- // If we reached the EOF, check that there is EXACTLY ONE possible matcher. Otherwise,
- // either the parse is ambiguous (which should never happen) or there is a syntax error.
- if parser.token == token::Eof {
- return match eof_items {
- EofItems::One(mut eof_item) => {
- let matches =
- eof_item.matches.iter_mut().map(|dv| Lrc::make_mut(dv).pop().unwrap());
- nameize(parser.sess, ms, matches)
- }
- EofItems::Multiple => {
- Error(parser.token.span, "ambiguity: multiple successful parses".to_string())
- }
- EofItems::None => Failure(
- Token::new(
- token::Eof,
- if parser.token.span.is_dummy() {
- parser.token.span
- } else {
- parser.token.span.shrink_to_hi()
- },
- ),
- "missing tokens in macro arguments",
- ),
- };
- }
- // Performance hack: `eof_items` may share matchers via `Rc` with other things that we want
- // to modify. Dropping `eof_items` now may drop these refcounts to 1, preventing an
- // unnecessary implicit clone later in `Rc::make_mut`.
- drop(eof_items);
-
- // If there are no possible next positions AND we aren't waiting for the black-box parser,
- // then there is a syntax error.
- if bb_items.is_empty() && next_items.is_empty() {
- return Failure(parser.token.clone(), "no rules expected this token in macro call");
- }
+ match (next_items.len(), bb_items.len()) {
+ (0, 0) => {
+ // There are no possible next positions AND we aren't waiting for the black-box
+ // parser: syntax error.
+ return Failure(parser.token.clone(), "no rules expected this token in macro call");
+ }
- if (!bb_items.is_empty() && !next_items.is_empty()) || bb_items.len() > 1 {
- // We need to call out to parse some rust nonterminal (black-box) parser. But something
- // is wrong, because there is not EXACTLY ONE of these.
- let nts = bb_items
- .iter()
- .map(|item| match item.top_elts.get_tt(item.idx) {
- TokenTree::MetaVarDecl(_, bind, Some(kind)) => format!("{} ('{}')", kind, bind),
- _ => panic!(),
- })
- .collect::<Vec<String>>()
- .join(" or ");
-
- return Error(
- parser.token.span,
- format!(
- "local ambiguity when calling macro `{macro_name}`: multiple parsing options: {}",
- match next_items.len() {
- 0 => format!("built-in NTs {}.", nts),
- 1 => format!("built-in NTs {} or 1 other option.", nts),
- n => format!("built-in NTs {} or {} other options.", nts, n),
- }
- ),
- );
- }
+ (_, 0) => {
+ // Dump all possible `next_items` into `cur_items` for the next iteration. Then
+ // process the next token.
+ cur_items.extend(next_items.drain(..));
+ parser.to_mut().bump();
+ }
- if !next_items.is_empty() {
- // Dump all possible `next_items` into `cur_items` for the next iteration. Then process
- // the next token.
- cur_items.extend(next_items.drain(..));
- parser.to_mut().bump();
- } else {
- // Finally, we have the case where we need to call the black-box parser to get some
- // nonterminal.
- assert_eq!(bb_items.len(), 1);
-
- let mut item = bb_items.pop().unwrap();
- if let TokenTree::MetaVarDecl(span, _, Some(kind)) = item.top_elts.get_tt(item.idx) {
- let match_cur = item.match_cur;
- // We use the span of the metavariable declaration to determine any
- // edition-specific matching behavior for non-terminals.
- let nt = match parser.to_mut().parse_nonterminal(kind) {
- Err(mut err) => {
- err.span_label(
- span,
- format!("while parsing argument for this `{}` macro fragment", kind),
- )
- .emit();
- return ErrorReported;
- }
- Ok(nt) => nt,
- };
- item.push_match(match_cur, MatchedNonterminal(Lrc::new(nt)));
- item.idx += 1;
- item.match_cur += 1;
- } else {
- unreachable!()
+ (0, 1) => {
+ // We need to call the black-box parser to get some nonterminal.
+ let mut item = bb_items.pop().unwrap();
+ if let TokenTree::MetaVarDecl(span, _, Some(kind)) = item.top_elts.get_tt(item.idx)
+ {
+ let match_cur = item.match_cur;
+ // We use the span of the metavariable declaration to determine any
+ // edition-specific matching behavior for non-terminals.
+ let nt = match parser.to_mut().parse_nonterminal(kind) {
+ Err(mut err) => {
+ err.span_label(
+ span,
+ format!("while parsing argument for this `{kind}` macro fragment"),
+ )
+ .emit();
+ return ErrorReported;
+ }
+ Ok(nt) => nt,
+ };
+ item.push_match(match_cur, MatchedNonterminal(Lrc::new(nt)));
+ item.idx += 1;
+ item.match_cur += 1;
+ } else {
+ unreachable!()
+ }
+ cur_items.push(item);
+ }
+
+ (_, _) => {
+ // We need to call the black-box parser to get some nonterminal, but something is
+ // wrong.
+ return bb_items_ambiguity_error(
+ macro_name,
+ next_items,
+ bb_items,
+ parser.token.span,
+ );
}
- cur_items.push(item);
}
assert!(!cur_items.is_empty());
}
}
+
+fn bb_items_ambiguity_error<'root, 'tt>(
+ macro_name: Ident,
+ next_items: SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>,
+ bb_items: SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>,
+ token_span: rustc_span::Span,
+) -> NamedParseResult {
+ let nts = bb_items
+ .iter()
+ .map(|item| match item.top_elts.get_tt(item.idx) {
+ TokenTree::MetaVarDecl(_, bind, Some(kind)) => {
+ format!("{} ('{}')", kind, bind)
+ }
+ _ => panic!(),
+ })
+ .collect::<Vec<String>>()
+ .join(" or ");
+
+ Error(
+ token_span,
+ format!(
+ "local ambiguity when calling macro `{macro_name}`: multiple parsing options: {}",
+ match next_items.len() {
+ 0 => format!("built-in NTs {}.", nts),
+ 1 => format!("built-in NTs {} or 1 other option.", nts),
+ n => format!("built-in NTs {} or {} other options.", nts, n),
+ }
+ ),
+ )
+}
use crate::base::ExtCtxt;
-use crate::mbe;
use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch};
-
+use crate::mbe::{self, MetaVarExpr};
use rustc_ast::mut_visit::{self, MutVisitor};
-use rustc_ast::token::{self, NtTT, Token};
+use rustc_ast::token::{self, NtTT, Token, TokenKind};
use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndSpacing};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lrc;
use rustc_errors::{pluralize, PResult};
+use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
use rustc_span::hygiene::{LocalExpnId, Transparency};
-use rustc_span::symbol::MacroRulesNormalizedIdent;
+use rustc_span::symbol::{sym, Ident, MacroRulesNormalizedIdent};
use rustc_span::Span;
use smallvec::{smallvec, SmallVec};
}
}
+/// Used solely by the `count` meta-variable expression, counts the outer-most repetitions at a
+/// given optional nested depth.
+///
+/// For example, a macro parameter of `$( { $( $foo:ident ),* } )*` called with `{ a, b } { c }`:
+///
+/// * `[ $( ${count(foo)} ),* ]` will return [2, 1] with a, b = 2 and c = 1
+/// * `[ $( ${count(foo, 0)} ),* ]` will be the same as `[ $( ${count(foo)} ),* ]`
+/// * `[ $( ${count(foo, 1)} ),* ]` will return an error because `${count(foo, 1)}` is
+/// declared inside a single repetition and the index `1` implies two nested repetitions.
+fn count_repetitions<'a>(
+ cx: &ExtCtxt<'a>,
+ depth_opt: Option<usize>,
+ mut matched: &NamedMatch,
+ repeats: &[(usize, usize)],
+ sp: &DelimSpan,
+) -> PResult<'a, usize> {
+ // Recursively count the number of matches in `matched` at given depth
+ // (or at the top-level of `matched` if no depth is given).
+ fn count<'a>(
+ cx: &ExtCtxt<'a>,
+ declared_lhs_depth: usize,
+ depth_opt: Option<usize>,
+ matched: &NamedMatch,
+ sp: &DelimSpan,
+ ) -> PResult<'a, usize> {
+ match matched {
+ MatchedNonterminal(_) => {
+ if declared_lhs_depth == 0 {
+ return Err(cx.struct_span_err(
+ sp.entire(),
+ "`count` can not be placed inside the inner-most repetition",
+ ));
+ }
+ match depth_opt {
+ None => Ok(1),
+ Some(_) => Err(out_of_bounds_err(cx, declared_lhs_depth, sp.entire(), "count")),
+ }
+ }
+ MatchedSeq(ref named_matches) => {
+ let new_declared_lhs_depth = declared_lhs_depth + 1;
+ match depth_opt {
+ None => named_matches
+ .iter()
+ .map(|elem| count(cx, new_declared_lhs_depth, None, elem, sp))
+ .sum(),
+ Some(0) => Ok(named_matches.len()),
+ Some(depth) => named_matches
+ .iter()
+ .map(|elem| count(cx, new_declared_lhs_depth, Some(depth - 1), elem, sp))
+ .sum(),
+ }
+ }
+ }
+ }
+ // `repeats` records all of the nested levels at which we are currently
+ // matching meta-variables. The meta-var-expr `count($x)` only counts
+ // matches that occur in this "subtree" of the `NamedMatch` where we
+ // are currently transcribing, so we need to descend to that subtree
+ // before we start counting. `matched` contains the various levels of the
+ // tree as we descend, and its final value is the subtree we are currently at.
+ for &(idx, _) in repeats {
+ if let MatchedSeq(ref ads) = matched {
+ matched = &ads[idx];
+ }
+ }
+ count(cx, 0, depth_opt, matched, sp)
+}
+
+/// Returns a `NamedMatch` item declared on the RHS given an arbitrary [Ident]
+fn matched_from_ident<'ctx, 'interp, 'rslt>(
+ cx: &ExtCtxt<'ctx>,
+ ident: Ident,
+ interp: &'interp FxHashMap<MacroRulesNormalizedIdent, NamedMatch>,
+) -> PResult<'ctx, &'rslt NamedMatch>
+where
+ 'interp: 'rslt,
+{
+ let span = ident.span;
+ let key = MacroRulesNormalizedIdent::new(ident);
+ interp.get(&key).ok_or_else(|| {
+ cx.struct_span_err(
+ span,
+ &format!("variable `{}` is not recognized in meta-variable expression", key),
+ )
+ })
+}
+
+/// Used by meta-variable expressions when an user input is out of the actual declared bounds. For
+/// example, index(999999) in an repetition of only three elements.
+fn out_of_bounds_err<'a>(
+ cx: &ExtCtxt<'a>,
+ max: usize,
+ span: Span,
+ ty: &str,
+) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
+ cx.struct_span_err(span, &format!("{ty} depth must be less than {max}"))
+}
+
fn transcribe_metavar_expr<'a>(
- _cx: &ExtCtxt<'a>,
- _expr: mbe::MetaVarExpr,
- _interp: &FxHashMap<MacroRulesNormalizedIdent, NamedMatch>,
- _repeats: &[(usize, usize)],
- _result: &mut Vec<TreeAndSpacing>,
- _sp: &DelimSpan,
+ cx: &ExtCtxt<'a>,
+ expr: MetaVarExpr,
+ interp: &FxHashMap<MacroRulesNormalizedIdent, NamedMatch>,
+ repeats: &[(usize, usize)],
+ result: &mut Vec<TreeAndSpacing>,
+ sp: &DelimSpan,
) -> PResult<'a, ()> {
+ match expr {
+ MetaVarExpr::Count(original_ident, depth_opt) => {
+ let matched = matched_from_ident(cx, original_ident, interp)?;
+ let count = count_repetitions(cx, depth_opt, matched, &repeats, sp)?;
+ let tt = TokenTree::token(
+ TokenKind::lit(token::Integer, sym::integer(count), None),
+ sp.entire(),
+ );
+ result.push(tt.into());
+ }
+ MetaVarExpr::Ignore(original_ident) => {
+ // Used to ensure that `original_ident` is present in the LHS
+ let _ = matched_from_ident(cx, original_ident, interp)?;
+ }
+ MetaVarExpr::Index(depth) => match repeats.iter().nth_back(depth) {
+ Some((index, _)) => {
+ result.push(
+ TokenTree::token(
+ TokenKind::lit(token::Integer, sym::integer(*index), None),
+ sp.entire(),
+ )
+ .into(),
+ );
+ }
+ None => return Err(out_of_bounds_err(cx, repeats.len(), sp.entire(), "index")),
+ },
+ MetaVarExpr::Length(depth) => match repeats.iter().nth_back(depth) {
+ Some((_, length)) => {
+ result.push(
+ TokenTree::token(
+ TokenKind::lit(token::Integer, sym::integer(*length), None),
+ sp.entire(),
+ )
+ .into(),
+ );
+ }
+ None => return Err(out_of_bounds_err(cx, repeats.len(), sp.entire(), "length")),
+ },
+ }
Ok(())
}
if let (&ty::Adt(exp_adt, _), &ty::Adt(found_adt, _)) =
(exp_found.expected.kind(), exp_found.found.kind())
{
- report_path_match(err, exp_adt.did, found_adt.did);
+ report_path_match(err, exp_adt.did(), found_adt.did());
}
}
TypeError::Traits(ref exp_found) => {
return Some(());
}
if let ty::Adt(def, _) = ta.kind() {
- let path_ = self.tcx.def_path_str(def.did);
+ let path_ = self.tcx.def_path_str(def.did());
if path_ == other_path {
self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, other_ty);
return Some(());
// process starts here
match (t1.kind(), t2.kind()) {
(&ty::Adt(def1, sub1), &ty::Adt(def2, sub2)) => {
- let sub_no_defaults_1 = self.strip_generic_default_params(def1.did, sub1);
- let sub_no_defaults_2 = self.strip_generic_default_params(def2.did, sub2);
+ let did1 = def1.did();
+ let did2 = def2.did();
+ let sub_no_defaults_1 = self.strip_generic_default_params(did1, sub1);
+ let sub_no_defaults_2 = self.strip_generic_default_params(did2, sub2);
let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
- let path1 = self.tcx.def_path_str(def1.did);
- let path2 = self.tcx.def_path_str(def2.did);
- if def1.did == def2.did {
+ let path1 = self.tcx.def_path_str(did1);
+ let path2 = self.tcx.def_path_str(did2);
+ if did1 == did2 {
// Easy case. Replace same types with `_` to shorten the output and highlight
// the differing ones.
// let x: Foo<Bar, Qux> = y::<Foo<Quz, Qux>>();
let t = match t.kind() {
// We'll hide this type only if all its type params are hidden as well.
ty::Adt(def, substs) => {
- let generics = self.tcx().generics_of(def.did);
+ let generics = self.tcx().generics_of(def.did());
// Account for params with default values, like `Vec`, where we
// want to show `Vec<T>`, not `Vec<T, _>`. If we replaced that
// subst, then we'd get the incorrect output, so we passthrough.
};
if self.level == 1 || substs.iter().any(should_keep) {
let substs = self.tcx().intern_substs(&substs[..]);
- self.tcx().mk_ty(ty::Adt(def, substs))
+ self.tcx().mk_ty(ty::Adt(*def, substs))
} else {
self.tcx().ty_error()
}
let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
let impl_ty = cx.tcx.type_of(parent);
let outerdef = match impl_ty.kind() {
- ty::Adt(def, _) => Some(def.did),
+ ty::Adt(def, _) => Some(def.did()),
ty::Foreign(def_id) => Some(*def_id),
_ => None,
};
let mut impls = LocalDefIdSet::default();
cx.tcx.for_each_impl(debug, |d| {
if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() {
- if let Some(def_id) = ty_def.did.as_local() {
+ if let Some(def_id) = ty_def.did().as_local() {
impls.insert(def_id);
}
}
/// Test if this enum has several actually "existing" variants.
/// Zero-sized uninhabited variants do not always have a tag assigned and thus do not "exist".
- fn is_multi_variant(adt: &ty::AdtDef) -> bool {
+ fn is_multi_variant<'tcx>(adt: ty::AdtDef<'tcx>) -> bool {
// As an approximation, we only count dataless variants. Those are definitely inhabited.
- let existing_variants = adt.variants.iter().filter(|v| v.fields.is_empty()).count();
+ let existing_variants = adt.variants().iter().filter(|v| v.fields.is_empty()).count();
existing_variants > 1
}
Adt(adt_def, substs) if !adt_def.is_union() => {
// First check if this ADT has a layout attribute (like `NonNull` and friends).
use std::ops::Bound;
- match tcx.layout_scalar_valid_range(adt_def.did) {
+ match tcx.layout_scalar_valid_range(adt_def.did()) {
// We exploit here that `layout_scalar_valid_range` will never
// return `Bound::Excluded`. (And we have tests checking that we
// handle the attribute correctly.)
_ => {}
}
// Now, recurse.
- match adt_def.variants.len() {
+ match adt_def.variants().len() {
0 => Some(("enums with no variants have no valid value".to_string(), None)),
1 => {
// Struct, or enum with exactly one variant.
// Proceed recursively, check all fields.
- let variant = &adt_def.variants[VariantIdx::from_u32(0)];
+ let variant = &adt_def.variant(VariantIdx::from_u32(0));
variant.fields.iter().find_map(|field| {
ty_find_init_error(tcx, field.ty(tcx, substs), init).map(
|(mut msg, span)| {
}
// Multi-variant enum.
_ => {
- if init == InitKind::Uninit && is_multi_variant(adt_def) {
- let span = tcx.def_span(adt_def.did);
+ if init == InitKind::Uninit && is_multi_variant(*adt_def) {
+ let span = tcx.def_span(adt_def.did());
Some((
"enums have to be initialized to a variant".to_string(),
Some(span),
let mut ty = ty;
loop {
if let ty::Adt(def, substs) = *ty.kind() {
- let is_transparent = def.subst(tcx, substs).repr.transparent();
- let is_non_null = crate::types::nonnull_optimization_guaranteed(tcx, &def);
+ let is_transparent = def.subst(tcx, substs).repr().transparent();
+ let is_non_null = crate::types::nonnull_optimization_guaranteed(tcx, def);
debug!(
"non_transparent_ty({:?}) -- type is transparent? {}, type is non-null? {}",
ty, is_transparent, is_non_null
);
if is_transparent && !is_non_null {
- debug_assert!(def.variants.len() == 1);
- let v = &def.variants[VariantIdx::new(0)];
+ debug_assert!(def.variants().len() == 1);
+ let v = &def.variant(VariantIdx::new(0));
ty = transparent_newtype_field(tcx, v)
.expect(
"single-variant transparent structure with zero-sized field",
}
// Grab a flattened representation of all fields.
- let a_fields = a_def.variants.iter().flat_map(|v| v.fields.iter());
- let b_fields = b_def.variants.iter().flat_map(|v| v.fields.iter());
+ let a_fields = a_def.variants().iter().flat_map(|v| v.fields.iter());
+ let b_fields = b_def.variants().iter().flat_map(|v| v.fields.iter());
// Perform a structural comparison for each field.
a_fields.eq_by(
) -> Result<Self::Path, Self::Error> {
if trait_ref.is_none() {
if let ty::Adt(def, substs) = self_ty.kind() {
- return self.print_def_path(def.did, substs);
+ return self.print_def_path(def.did(), substs);
}
}
Res::SelfTy { trait_: None, alias_to: Some((did, _)) } => {
if let ty::Adt(adt, substs) = cx.tcx.type_of(did).kind() {
if let Some(name @ (sym::Ty | sym::TyCtxt)) =
- cx.tcx.get_diagnostic_name(adt.did)
+ cx.tcx.get_diagnostic_name(adt.did())
{
// NOTE: This path is currently unreachable as `Ty<'tcx>` is
// defined as a type alias meaning that `impl<'tcx> Ty<'tcx>`
) {
let source_type = cx.typeck_results().expr_ty(source);
if let ty::Adt(def, substs) = source_type.kind() {
- if cx.tcx.is_diagnostic_item(sym::Result, def.did) {
+ if cx.tcx.is_diagnostic_item(sym::Result, def.did()) {
if let ty::Adt(adt, _) = substs.type_at(0).kind() {
- if cx.tcx.is_diagnostic_item(sym::cstring_type, adt.did) {
+ if cx.tcx.is_diagnostic_item(sym::cstring_type, adt.did()) {
cx.struct_span_lint(TEMPORARY_CSTRING_AS_PTR, as_ptr_span, |diag| {
let mut diag = diag
.build("getting the inner pointer of a temporary `CString`");
ty::Ref(_, r, _) if *r.kind() == ty::Str,
) || matches!(
ty.ty_adt_def(),
- Some(ty_def) if cx.tcx.is_diagnostic_item(sym::String, ty_def.did),
+ Some(ty_def) if cx.tcx.is_diagnostic_item(sym::String, ty_def.did()),
);
let (suggest_display, suggest_debug) = cx.tcx.infer_ctxt().enter(|infcx| {
}
Res::SelfTy { trait_: None, alias_to: Some((did, _)) } => {
if let ty::Adt(adt, substs) = cx.tcx.type_of(did).kind() {
- if cx.tcx.has_attr(adt.did, sym::rustc_pass_by_value) {
- return Some(cx.tcx.def_path_str_with_substs(adt.did, substs));
+ if cx.tcx.has_attr(adt.did(), sym::rustc_pass_by_value) {
+ return Some(cx.tcx.def_path_str_with_substs(adt.did(), substs));
}
}
}
FfiUnsafe { ty: Ty<'tcx>, reason: String, help: Option<String> },
}
-crate fn nonnull_optimization_guaranteed<'tcx>(tcx: TyCtxt<'tcx>, def: &ty::AdtDef) -> bool {
- tcx.get_attrs(def.did).iter().any(|a| a.has_name(sym::rustc_nonnull_optimization_guaranteed))
+crate fn nonnull_optimization_guaranteed<'tcx>(tcx: TyCtxt<'tcx>, def: ty::AdtDef<'tcx>) -> bool {
+ tcx.get_attrs(def.did()).iter().any(|a| a.has_name(sym::rustc_nonnull_optimization_guaranteed))
}
/// `repr(transparent)` structs can have a single non-ZST field, this function returns that
ty::FnPtr(_) => true,
ty::Ref(..) => true,
ty::Adt(def, _) if def.is_box() && matches!(mode, CItemKind::Definition) => true,
- ty::Adt(def, substs) if def.repr.transparent() && !def.is_union() => {
- let marked_non_null = nonnull_optimization_guaranteed(tcx, &def);
+ ty::Adt(def, substs) if def.repr().transparent() && !def.is_union() => {
+ let marked_non_null = nonnull_optimization_guaranteed(tcx, *def);
if marked_non_null {
return true;
// Types with a `#[repr(no_niche)]` attribute have their niche hidden.
// The attribute is used by the UnsafeCell for example (the only use so far).
- if def.repr.hide_niche() {
+ if def.repr().hide_niche() {
return false;
}
- def.variants
+ def.variants()
.iter()
.filter_map(|variant| transparent_newtype_field(cx.tcx, variant))
.any(|field| ty_is_known_nonnull(cx, field.ty(tcx, substs), mode))
Some(match *ty.kind() {
ty::Adt(field_def, field_substs) => {
let inner_field_ty = {
- let first_non_zst_ty =
- field_def.variants.iter().filter_map(|v| transparent_newtype_field(cx.tcx, v));
+ let first_non_zst_ty = field_def
+ .variants()
+ .iter()
+ .filter_map(|v| transparent_newtype_field(cx.tcx, v));
debug_assert_eq!(
first_non_zst_ty.clone().count(),
1,
) -> Option<Ty<'tcx>> {
debug!("is_repr_nullable_ptr(cx, ty = {:?})", ty);
if let ty::Adt(ty_def, substs) = ty.kind() {
- let field_ty = match &ty_def.variants.raw[..] {
+ let field_ty = match &ty_def.variants().raw[..] {
[var_one, var_two] => match (&var_one.fields[..], &var_two.fields[..]) {
([], [field]) | ([field], []) => field.ty(cx.tcx, substs),
_ => return None,
&self,
cache: &mut FxHashSet<Ty<'tcx>>,
ty: Ty<'tcx>,
- def: &ty::AdtDef,
+ def: ty::AdtDef<'tcx>,
variant: &ty::VariantDef,
substs: SubstsRef<'tcx>,
) -> FfiResult<'tcx> {
use FfiResult::*;
- if def.repr.transparent() {
+ if def.repr().transparent() {
// Can assume that at most one field is not a ZST, so only check
// that field's type for FFI-safety.
if let Some(field) = transparent_newtype_field(self.cx.tcx, variant) {
AdtKind::Struct | AdtKind::Union => {
let kind = if def.is_struct() { "struct" } else { "union" };
- if !def.repr.c() && !def.repr.transparent() {
+ if !def.repr().c() && !def.repr().transparent() {
return FfiUnsafe {
ty,
reason: format!("this {} has unspecified layout", kind),
let is_non_exhaustive =
def.non_enum_variant().is_field_list_non_exhaustive();
- if is_non_exhaustive && !def.did.is_local() {
+ if is_non_exhaustive && !def.did().is_local() {
return FfiUnsafe {
ty,
reason: format!("this {} is non-exhaustive", kind),
self.check_variant_for_ffi(cache, ty, def, def.non_enum_variant(), substs)
}
AdtKind::Enum => {
- if def.variants.is_empty() {
+ if def.variants().is_empty() {
// Empty enums are okay... although sort of useless.
return FfiSafe;
}
// Check for a repr() attribute to specify the size of the
// discriminant.
- if !def.repr.c() && !def.repr.transparent() && def.repr.int.is_none() {
+ if !def.repr().c() && !def.repr().transparent() && def.repr().int.is_none()
+ {
// Special-case types like `Option<extern fn()>`.
if repr_nullable_ptr(self.cx, ty, self.mode).is_none() {
return FfiUnsafe {
}
}
- if def.is_variant_list_non_exhaustive() && !def.did.is_local() {
+ if def.is_variant_list_non_exhaustive() && !def.did().is_local() {
return FfiUnsafe {
ty,
reason: "this enum is non-exhaustive".into(),
}
// Check the contained variants.
- for variant in &def.variants {
+ for variant in def.variants() {
let is_non_exhaustive = variant.is_field_list_non_exhaustive();
if is_non_exhaustive && !variant.def_id.is_local() {
return FfiUnsafe {
}
diag.note(note);
if let ty::Adt(def, _) = ty.kind() {
- if let Some(sp) = self.cx.tcx.hir().span_if_local(def.did) {
+ if let Some(sp) = self.cx.tcx.hir().span_if_local(def.did()) {
diag.span_note(sp, "the type is defined here");
}
}
&& let Some(adt) = cx.tcx.type_of(impl_did).ty_adt_def()
// skip extension traits, only lint functions from the standard library
&& cx.tcx.trait_id_of_impl(impl_did).is_none()
- && let Some(parent) = cx.tcx.parent(adt.did)
+ && let Some(parent) = cx.tcx.parent(adt.did())
&& cx.tcx.is_diagnostic_item(sym::atomic_mod, parent)
- && ATOMIC_TYPES.contains(&cx.tcx.item_name(adt.did))
+ && ATOMIC_TYPES.contains(&cx.tcx.item_name(adt.did()))
{
return Some((method_path.ident.name, args));
}
let descr_pre = &format!("{}boxed ", descr_pre);
check_must_use_ty(cx, boxed_ty, expr, span, descr_pre, descr_post, plural_len)
}
- ty::Adt(def, _) => check_must_use_def(cx, def.did, span, descr_pre, descr_post),
+ ty::Adt(def, _) => check_must_use_def(cx, def.did(), span, descr_pre, descr_post),
ty::Opaque(def, _) => {
let mut has_emitted = false;
for &(predicate, _) in cx.tcx.explicit_item_bounds(def) {
)
}
- fn get_adt_def(self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> &'tcx ty::AdtDef {
+ fn get_adt_def(self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::AdtDef<'tcx> {
let kind = self.kind(item_id);
let did = self.local_def_id(item_id);
record!(self.tables.type_of[def_id] <- self.tcx.type_of(def_id));
}
- fn encode_enum_variant_info(&mut self, def: &ty::AdtDef, index: VariantIdx) {
+ fn encode_enum_variant_info(&mut self, def: ty::AdtDef<'tcx>, index: VariantIdx) {
let tcx = self.tcx;
- let variant = &def.variants[index];
+ let variant = &def.variant(index);
let def_id = variant.def_id;
debug!("EncodeContext::encode_enum_variant_info({:?})", def_id);
}
}
- fn encode_enum_variant_ctor(&mut self, def: &ty::AdtDef, index: VariantIdx) {
+ fn encode_enum_variant_ctor(&mut self, def: ty::AdtDef<'tcx>, index: VariantIdx) {
let tcx = self.tcx;
- let variant = &def.variants[index];
+ let variant = &def.variant(index);
let def_id = variant.ctor_def_id.unwrap();
debug!("EncodeContext::encode_enum_variant_ctor({:?})", def_id);
fn encode_field(
&mut self,
- adt_def: &ty::AdtDef,
+ adt_def: ty::AdtDef<'tcx>,
variant_index: VariantIdx,
field_index: usize,
) {
- let variant = &adt_def.variants[variant_index];
+ let variant = &adt_def.variant(variant_index);
let field = &variant.fields[field_index];
let def_id = field.did;
self.encode_item_type(def_id);
}
- fn encode_struct_ctor(&mut self, adt_def: &ty::AdtDef, def_id: DefId) {
+ fn encode_struct_ctor(&mut self, adt_def: ty::AdtDef<'tcx>, def_id: DefId) {
debug!("EncodeContext::encode_struct_ctor({:?})", def_id);
let tcx = self.tcx;
let variant = adt_def.non_enum_variant();
is_non_exhaustive: variant.is_field_list_non_exhaustive(),
};
- record!(self.tables.kind[def_id] <- EntryKind::Struct(self.lazy(data), adt_def.repr));
+ record!(self.tables.kind[def_id] <- EntryKind::Struct(self.lazy(data), adt_def.repr()));
self.encode_item_type(def_id);
if variant.ctor_kind == CtorKind::Fn {
record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
self.encode_explicit_item_bounds(def_id);
EntryKind::OpaqueTy
}
- hir::ItemKind::Enum(..) => EntryKind::Enum(self.tcx.adt_def(def_id).repr),
+ hir::ItemKind::Enum(..) => EntryKind::Enum(self.tcx.adt_def(def_id).repr()),
hir::ItemKind::Struct(ref struct_def, _) => {
let adt_def = self.tcx.adt_def(def_id);
let variant = adt_def.non_enum_variant();
ctor,
is_non_exhaustive: variant.is_field_list_non_exhaustive(),
}),
- adt_def.repr,
+ adt_def.repr(),
)
}
hir::ItemKind::Union(..) => {
ctor: None,
is_non_exhaustive: variant.is_field_list_non_exhaustive(),
}),
- adt_def.repr,
+ adt_def.repr(),
)
}
hir::ItemKind::Impl(hir::Impl { defaultness, constness, .. }) => {
// FIXME(eddyb) there should be a nicer way to do this.
match item.kind {
hir::ItemKind::Enum(..) => record!(self.tables.children[def_id] <-
- self.tcx.adt_def(def_id).variants.iter().map(|v| {
+ self.tcx.adt_def(def_id).variants().iter().map(|v| {
assert!(v.def_id.is_local());
v.def_id.index
})
}
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
- fn encode_fields(&mut self, adt_def: &ty::AdtDef) {
- for (variant_index, variant) in adt_def.variants.iter_enumerated() {
+ fn encode_fields(&mut self, adt_def: ty::AdtDef<'tcx>) {
+ for (variant_index, variant) in adt_def.variants().iter_enumerated() {
for (field_index, _field) in variant.fields.iter().enumerate() {
self.encode_field(adt_def, variant_index, field_index);
}
let def = self.tcx.adt_def(item.def_id.to_def_id());
self.encode_fields(def);
- for (i, variant) in def.variants.iter_enumerated() {
+ for (i, variant) in def.variants().iter_enumerated() {
self.encode_enum_variant_info(def, i);
if let Some(_ctor_def_id) = variant.ctor_def_id {
[] layout: rustc_target::abi::LayoutS<'tcx>,
[] fn_abi: rustc_target::abi::call::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>,
// AdtDef are interned and compared by address
- [decode] adt_def: rustc_middle::ty::AdtDef,
+ [decode] adt_def: rustc_middle::ty::AdtDefData,
[] steal_thir: rustc_data_structures::steal::Steal<rustc_middle::thir::Thir<'tcx>>,
[] steal_mir: rustc_data_structures::steal::Steal<rustc_middle::mir::Body<'tcx>>,
[decode] mir: rustc_middle::mir::Body<'tcx>,
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html
use crate::ty::TyCtxt;
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_hir as hir;
use rustc_hir::Node;
/// conditional expression or repeating block. (Note that the
/// enclosing scope ID for the block associated with a closure is
/// the closure itself.)
- pub parent_map: FxHashMap<Scope, (Scope, ScopeDepth)>,
+ pub parent_map: FxIndexMap<Scope, (Scope, ScopeDepth)>,
/// Maps from a variable or binding ID to the block in which that
/// variable is declared.
- var_map: FxHashMap<hir::ItemLocalId, Scope>,
+ var_map: FxIndexMap<hir::ItemLocalId, Scope>,
/// Maps from a `NodeId` to the associated destruction scope (if any).
- destruction_scopes: FxHashMap<hir::ItemLocalId, Scope>,
+ destruction_scopes: FxIndexMap<hir::ItemLocalId, Scope>,
/// `rvalue_scopes` includes entries for those expressions whose
/// cleanup scope is larger than the default. The map goes from the
MemoryAccessTest,
/// We are doing pointer arithmetic.
PointerArithmeticTest,
+ /// We are doing pointer offset_from.
+ OffsetFromTest,
/// None of the above -- generic/unspecific inbounds test.
InboundsTest,
}
CheckInAllocMsg::DerefTest => "dereferencing pointer failed: ",
CheckInAllocMsg::MemoryAccessTest => "memory access failed: ",
CheckInAllocMsg::PointerArithmeticTest => "pointer arithmetic failed: ",
+ CheckInAllocMsg::OffsetFromTest => "out-of-bounds offset_from: ",
CheckInAllocMsg::InboundsTest => "",
}
)
DanglingIntPointer(0, CheckInAllocMsg::InboundsTest) => {
write!(f, "null pointer is not a valid pointer for this operation")
}
+ DanglingIntPointer(0, msg) => {
+ write!(f, "{}null pointer is not a valid pointer", msg)
+ }
DanglingIntPointer(i, msg) => {
write!(f, "{}0x{:x} is not a valid pointer", msg, i)
}
AggregateKind::Adt(adt_did, variant, substs, _user_ty, _) => {
ty::tls::with(|tcx| {
- let variant_def = &tcx.adt_def(adt_did).variants[variant];
+ let variant_def = &tcx.adt_def(adt_did).variant(variant);
let substs = tcx.lift(substs).expect("could not lift for printing");
let name = FmtPrinter::new(tcx, Namespace::ValueNS)
.print_def_path(variant_def.def_id, substs)?
self.map_projections(|pat_ty_proj| pat_ty_proj.leaf(field))
}
- pub fn variant(self, adt_def: &'tcx AdtDef, variant_index: VariantIdx, field: Field) -> Self {
+ pub fn variant(self, adt_def: AdtDef<'tcx>, variant_index: VariantIdx, field: Field) -> Self {
self.map_projections(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field))
}
}
pub(crate) fn variant(
mut self,
- adt_def: &AdtDef,
+ adt_def: AdtDef<'_>,
variant_index: VariantIdx,
field: Field,
) -> Self {
self.projs.push(ProjectionElem::Downcast(
- Some(adt_def.variants[variant_index].name),
+ Some(adt_def.variant(variant_index).name),
variant_index,
));
self.projs.push(ProjectionElem::Field(field, ()));
None => adt_def.non_enum_variant(),
Some(variant_index) => {
assert!(adt_def.is_enum());
- &adt_def.variants[variant_index]
+ &adt_def.variant(variant_index)
}
};
let field_def = &variant_def.fields[f.index()];
storage(ArenaCacheSelector<'tcx>)
separate_provide_extern
}
- query adt_def(key: DefId) -> &'tcx ty::AdtDef {
+ query adt_def(key: DefId) -> ty::AdtDef<'tcx> {
desc { |tcx| "computing ADT definition for `{}`", tcx.def_path_str(key) }
cache_on_disk_if { key.is_local() }
separate_provide_extern
#[derive(Debug, HashStable)]
pub struct Adt<'tcx> {
/// The ADT we're constructing.
- pub adt_def: &'tcx AdtDef,
+ pub adt_def: AdtDef<'tcx>,
/// The variant of the ADT.
pub variant_index: VariantIdx,
pub substs: SubstsRef<'tcx>,
/// `Foo(...)` or `Foo{...}` or `Foo`, where `Foo` is a variant name from an ADT with
/// multiple variants.
Variant {
- adt_def: &'tcx AdtDef,
+ adt_def: AdtDef<'tcx>,
substs: SubstsRef<'tcx>,
variant_index: VariantIdx,
subpatterns: Vec<FieldPat<'tcx>>,
PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => {
let variant = match *self.kind {
PatKind::Variant { adt_def, variant_index, .. } => {
- Some(&adt_def.variants[variant_index])
+ Some(adt_def.variant(variant_index))
}
_ => self.ty.ty_adt_def().and_then(|adt| {
if !adt.is_enum() { Some(adt.non_enum_variant()) } else { None }
type InternedVariances = Vec<chalk_ir::Variance>;
type InternedConstraints = Vec<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>>;
type DefId = DefId;
- type InternedAdtId = &'tcx AdtDef;
+ type InternedAdtId = AdtDef<'tcx>;
type Identifier = ();
type FnAbi = Abi;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::intern::Interned;
use rustc_data_structures::stable_hasher::HashingControls;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_errors::ErrorGuaranteed;
/// where `x` here represents the `DefId` of `S.x`. Then, the `DefId`
/// can be used with [`TyCtxt::type_of()`] to get the type of the field.
#[derive(TyEncodable, TyDecodable)]
-pub struct AdtDef {
+pub struct AdtDefData {
/// The `DefId` of the struct, enum or union item.
pub did: DefId,
/// Variants of the ADT. If this is a struct or union, then there will be a single variant.
- pub variants: IndexVec<VariantIdx, VariantDef>,
+ variants: IndexVec<VariantIdx, VariantDef>,
/// Flags of the ADT (e.g., is this a struct? is this non-exhaustive?).
flags: AdtFlags,
/// Repr options provided by the user.
- pub repr: ReprOptions,
+ repr: ReprOptions,
}
-impl PartialOrd for AdtDef {
- fn partial_cmp(&self, other: &AdtDef) -> Option<Ordering> {
+impl PartialOrd for AdtDefData {
+ fn partial_cmp(&self, other: &AdtDefData) -> Option<Ordering> {
Some(self.cmp(&other))
}
}
/// There should be only one AdtDef for each `did`, therefore
/// it is fine to implement `Ord` only based on `did`.
-impl Ord for AdtDef {
- fn cmp(&self, other: &AdtDef) -> Ordering {
+impl Ord for AdtDefData {
+ fn cmp(&self, other: &AdtDefData) -> Ordering {
self.did.cmp(&other.did)
}
}
/// There should be only one AdtDef for each `did`, therefore
/// it is fine to implement `PartialEq` only based on `did`.
-impl PartialEq for AdtDef {
+impl PartialEq for AdtDefData {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.did == other.did
}
}
-impl Eq for AdtDef {}
+impl Eq for AdtDefData {}
/// There should be only one AdtDef for each `did`, therefore
/// it is fine to implement `Hash` only based on `did`.
-impl Hash for AdtDef {
+impl Hash for AdtDefData {
#[inline]
fn hash<H: Hasher>(&self, s: &mut H) {
self.did.hash(s)
}
}
-impl<'a> HashStable<StableHashingContext<'a>> for AdtDef {
+impl<'a> HashStable<StableHashingContext<'a>> for AdtDefData {
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
thread_local! {
static CACHE: RefCell<FxHashMap<(usize, HashingControls), Fingerprint>> = Default::default();
}
let hash: Fingerprint = CACHE.with(|cache| {
- let addr = self as *const AdtDef as usize;
+ let addr = self as *const AdtDefData as usize;
let hashing_controls = hcx.hashing_controls();
*cache.borrow_mut().entry((addr, hashing_controls)).or_insert_with(|| {
- let ty::AdtDef { did, ref variants, ref flags, ref repr } = *self;
+ let ty::AdtDefData { did, ref variants, ref flags, ref repr } = *self;
let mut hasher = StableHasher::new();
did.hash_stable(hcx, &mut hasher);
}
}
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, HashStable)]
+#[cfg_attr(not(bootstrap), rustc_pass_by_value)]
+pub struct AdtDef<'tcx>(pub Interned<'tcx, AdtDefData>);
+
+impl<'tcx> AdtDef<'tcx> {
+ pub fn did(self) -> DefId {
+ self.0.0.did
+ }
+
+ pub fn variants(self) -> &'tcx IndexVec<VariantIdx, VariantDef> {
+ &self.0.0.variants
+ }
+
+ pub fn variant(self, idx: VariantIdx) -> &'tcx VariantDef {
+ &self.0.0.variants[idx]
+ }
+
+ pub fn flags(self) -> AdtFlags {
+ self.0.0.flags
+ }
+
+ pub fn repr(self) -> ReprOptions {
+ self.0.0.repr
+ }
+}
+
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
pub enum AdtKind {
Struct,
}
}
-impl<'tcx> AdtDef {
- /// Creates a new `AdtDef`.
+impl AdtDefData {
+ /// Creates a new `AdtDefData`.
pub(super) fn new(
tcx: TyCtxt<'_>,
did: DefId,
flags |= AdtFlags::IS_MANUALLY_DROP;
}
- AdtDef { did, variants, flags, repr }
+ AdtDefData { did, variants, flags, repr }
}
+}
+impl<'tcx> AdtDef<'tcx> {
/// Returns `true` if this is a struct.
#[inline]
- pub fn is_struct(&self) -> bool {
- self.flags.contains(AdtFlags::IS_STRUCT)
+ pub fn is_struct(self) -> bool {
+ self.flags().contains(AdtFlags::IS_STRUCT)
}
/// Returns `true` if this is a union.
#[inline]
- pub fn is_union(&self) -> bool {
- self.flags.contains(AdtFlags::IS_UNION)
+ pub fn is_union(self) -> bool {
+ self.flags().contains(AdtFlags::IS_UNION)
}
/// Returns `true` if this is an enum.
#[inline]
- pub fn is_enum(&self) -> bool {
- self.flags.contains(AdtFlags::IS_ENUM)
+ pub fn is_enum(self) -> bool {
+ self.flags().contains(AdtFlags::IS_ENUM)
}
/// Returns `true` if the variant list of this ADT is `#[non_exhaustive]`.
#[inline]
- pub fn is_variant_list_non_exhaustive(&self) -> bool {
- self.flags.contains(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
+ pub fn is_variant_list_non_exhaustive(self) -> bool {
+ self.flags().contains(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
}
/// Returns the kind of the ADT.
#[inline]
- pub fn adt_kind(&self) -> AdtKind {
+ pub fn adt_kind(self) -> AdtKind {
if self.is_enum() {
AdtKind::Enum
} else if self.is_union() {
}
/// Returns a description of this abstract data type.
- pub fn descr(&self) -> &'static str {
+ pub fn descr(self) -> &'static str {
match self.adt_kind() {
AdtKind::Struct => "struct",
AdtKind::Union => "union",
/// Returns a description of a variant of this abstract data type.
#[inline]
- pub fn variant_descr(&self) -> &'static str {
+ pub fn variant_descr(self) -> &'static str {
match self.adt_kind() {
AdtKind::Struct => "struct",
AdtKind::Union => "union",
/// If this function returns `true`, it implies that `is_struct` must return `true`.
#[inline]
- pub fn has_ctor(&self) -> bool {
- self.flags.contains(AdtFlags::HAS_CTOR)
+ pub fn has_ctor(self) -> bool {
+ self.flags().contains(AdtFlags::HAS_CTOR)
}
/// Returns `true` if this type is `#[fundamental]` for the purposes
/// of coherence checking.
#[inline]
- pub fn is_fundamental(&self) -> bool {
- self.flags.contains(AdtFlags::IS_FUNDAMENTAL)
+ pub fn is_fundamental(self) -> bool {
+ self.flags().contains(AdtFlags::IS_FUNDAMENTAL)
}
/// Returns `true` if this is `PhantomData<T>`.
#[inline]
- pub fn is_phantom_data(&self) -> bool {
- self.flags.contains(AdtFlags::IS_PHANTOM_DATA)
+ pub fn is_phantom_data(self) -> bool {
+ self.flags().contains(AdtFlags::IS_PHANTOM_DATA)
}
/// Returns `true` if this is Box<T>.
#[inline]
- pub fn is_box(&self) -> bool {
- self.flags.contains(AdtFlags::IS_BOX)
+ pub fn is_box(self) -> bool {
+ self.flags().contains(AdtFlags::IS_BOX)
}
/// Returns `true` if this is `ManuallyDrop<T>`.
#[inline]
- pub fn is_manually_drop(&self) -> bool {
- self.flags.contains(AdtFlags::IS_MANUALLY_DROP)
+ pub fn is_manually_drop(self) -> bool {
+ self.flags().contains(AdtFlags::IS_MANUALLY_DROP)
}
/// Returns `true` if this type has a destructor.
- pub fn has_dtor(&self, tcx: TyCtxt<'tcx>) -> bool {
+ pub fn has_dtor(self, tcx: TyCtxt<'tcx>) -> bool {
self.destructor(tcx).is_some()
}
- pub fn has_non_const_dtor(&self, tcx: TyCtxt<'tcx>) -> bool {
+ pub fn has_non_const_dtor(self, tcx: TyCtxt<'tcx>) -> bool {
matches!(self.destructor(tcx), Some(Destructor { constness: hir::Constness::NotConst, .. }))
}
/// Asserts this is a struct or union and returns its unique variant.
- pub fn non_enum_variant(&self) -> &VariantDef {
+ pub fn non_enum_variant(self) -> &'tcx VariantDef {
assert!(self.is_struct() || self.is_union());
- &self.variants[VariantIdx::new(0)]
+ &self.variant(VariantIdx::new(0))
}
#[inline]
- pub fn predicates(&self, tcx: TyCtxt<'tcx>) -> GenericPredicates<'tcx> {
- tcx.predicates_of(self.did)
+ pub fn predicates(self, tcx: TyCtxt<'tcx>) -> GenericPredicates<'tcx> {
+ tcx.predicates_of(self.did())
}
/// Returns an iterator over all fields contained
/// by this ADT.
#[inline]
- pub fn all_fields(&self) -> impl Iterator<Item = &FieldDef> + Clone {
- self.variants.iter().flat_map(|v| v.fields.iter())
+ pub fn all_fields(self) -> impl Iterator<Item = &'tcx FieldDef> + Clone {
+ self.variants().iter().flat_map(|v| v.fields.iter())
}
/// Whether the ADT lacks fields. Note that this includes uninhabited enums,
/// e.g., `enum Void {}` is considered payload free as well.
- pub fn is_payloadfree(&self) -> bool {
+ pub fn is_payloadfree(self) -> bool {
// Treat the ADT as not payload-free if arbitrary_enum_discriminant is used (#88621).
// This would disallow the following kind of enum from being casted into integer.
// ```
// }
// ```
if self
- .variants
+ .variants()
.iter()
.any(|v| matches!(v.discr, VariantDiscr::Explicit(_)) && v.ctor_kind != CtorKind::Const)
{
return false;
}
- self.variants.iter().all(|v| v.fields.is_empty())
+ self.variants().iter().all(|v| v.fields.is_empty())
}
/// Return a `VariantDef` given a variant id.
- pub fn variant_with_id(&self, vid: DefId) -> &VariantDef {
- self.variants.iter().find(|v| v.def_id == vid).expect("variant_with_id: unknown variant")
+ pub fn variant_with_id(self, vid: DefId) -> &'tcx VariantDef {
+ self.variants().iter().find(|v| v.def_id == vid).expect("variant_with_id: unknown variant")
}
/// Return a `VariantDef` given a constructor id.
- pub fn variant_with_ctor_id(&self, cid: DefId) -> &VariantDef {
- self.variants
+ pub fn variant_with_ctor_id(self, cid: DefId) -> &'tcx VariantDef {
+ self.variants()
.iter()
.find(|v| v.ctor_def_id == Some(cid))
.expect("variant_with_ctor_id: unknown variant")
}
/// Return the index of `VariantDef` given a variant id.
- pub fn variant_index_with_id(&self, vid: DefId) -> VariantIdx {
- self.variants
+ pub fn variant_index_with_id(self, vid: DefId) -> VariantIdx {
+ self.variants()
.iter_enumerated()
.find(|(_, v)| v.def_id == vid)
.expect("variant_index_with_id: unknown variant")
}
/// Return the index of `VariantDef` given a constructor id.
- pub fn variant_index_with_ctor_id(&self, cid: DefId) -> VariantIdx {
- self.variants
+ pub fn variant_index_with_ctor_id(self, cid: DefId) -> VariantIdx {
+ self.variants()
.iter_enumerated()
.find(|(_, v)| v.ctor_def_id == Some(cid))
.expect("variant_index_with_ctor_id: unknown variant")
.0
}
- pub fn variant_of_res(&self, res: Res) -> &VariantDef {
+ pub fn variant_of_res(self, res: Res) -> &'tcx VariantDef {
match res {
Res::Def(DefKind::Variant, vid) => self.variant_with_id(vid),
Res::Def(DefKind::Ctor(..), cid) => self.variant_with_ctor_id(cid),
}
#[inline]
- pub fn eval_explicit_discr(&self, tcx: TyCtxt<'tcx>, expr_did: DefId) -> Option<Discr<'tcx>> {
+ pub fn eval_explicit_discr(self, tcx: TyCtxt<'tcx>, expr_did: DefId) -> Option<Discr<'tcx>> {
assert!(self.is_enum());
let param_env = tcx.param_env(expr_did);
- let repr_type = self.repr.discr_type();
+ let repr_type = self.repr().discr_type();
match tcx.const_eval_poly(expr_did) {
Ok(val) => {
let ty = repr_type.to_ty(tcx);
#[inline]
pub fn discriminants(
- &'tcx self,
+ self,
tcx: TyCtxt<'tcx>,
) -> impl Iterator<Item = (VariantIdx, Discr<'tcx>)> + Captures<'tcx> {
assert!(self.is_enum());
- let repr_type = self.repr.discr_type();
+ let repr_type = self.repr().discr_type();
let initial = repr_type.initial_discriminant(tcx);
let mut prev_discr = None::<Discr<'tcx>>;
- self.variants.iter_enumerated().map(move |(i, v)| {
+ self.variants().iter_enumerated().map(move |(i, v)| {
let mut discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
if let VariantDiscr::Explicit(expr_did) = v.discr {
if let Some(new_discr) = self.eval_explicit_discr(tcx, expr_did) {
}
#[inline]
- pub fn variant_range(&self) -> Range<VariantIdx> {
- VariantIdx::new(0)..VariantIdx::new(self.variants.len())
+ pub fn variant_range(self) -> Range<VariantIdx> {
+ VariantIdx::new(0)..VariantIdx::new(self.variants().len())
}
/// Computes the discriminant value used by a specific variant.
/// assuming there are no constant-evaluation errors there.
#[inline]
pub fn discriminant_for_variant(
- &self,
+ self,
tcx: TyCtxt<'tcx>,
variant_index: VariantIdx,
) -> Discr<'tcx> {
let (val, offset) = self.discriminant_def_for_variant(variant_index);
let explicit_value = val
.and_then(|expr_did| self.eval_explicit_discr(tcx, expr_did))
- .unwrap_or_else(|| self.repr.discr_type().initial_discriminant(tcx));
+ .unwrap_or_else(|| self.repr().discr_type().initial_discriminant(tcx));
explicit_value.checked_add(tcx, offset as u128).0
}
/// Yields a `DefId` for the discriminant and an offset to add to it
/// Alternatively, if there is no explicit discriminant, returns the
/// inferred discriminant directly.
- pub fn discriminant_def_for_variant(&self, variant_index: VariantIdx) -> (Option<DefId>, u32) {
- assert!(!self.variants.is_empty());
+ pub fn discriminant_def_for_variant(self, variant_index: VariantIdx) -> (Option<DefId>, u32) {
+ assert!(!self.variants().is_empty());
let mut explicit_index = variant_index.as_u32();
let expr_did;
loop {
- match self.variants[VariantIdx::from_u32(explicit_index)].discr {
+ match self.variant(VariantIdx::from_u32(explicit_index)).discr {
ty::VariantDiscr::Relative(0) => {
expr_did = None;
break;
(expr_did, variant_index.as_u32() - explicit_index)
}
- pub fn destructor(&self, tcx: TyCtxt<'tcx>) -> Option<Destructor> {
- tcx.adt_destructor(self.did)
+ pub fn destructor(self, tcx: TyCtxt<'tcx>) -> Option<Destructor> {
+ tcx.adt_destructor(self.did())
}
/// Returns a list of types such that `Self: Sized` if and only
///
/// Due to normalization being eager, this applies even if
/// the associated type is behind a pointer (e.g., issue #31299).
- pub fn sized_constraint(&self, tcx: TyCtxt<'tcx>) -> &'tcx [Ty<'tcx>] {
- tcx.adt_sized_constraint(self.did).0
+ pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> &'tcx [Ty<'tcx>] {
+ tcx.adt_sized_constraint(self.did()).0
}
}
write!(
&mut symbol,
"__{}",
- def.variants[variant].fields[idx as usize].name.as_str(),
+ def.variant(variant).fields[idx as usize].name.as_str(),
)
.unwrap();
}
curr_string = format!(
"{}.{}",
curr_string,
- def.variants[variant].fields[idx as usize].name.as_str()
+ def.variant(variant).fields[idx as usize].name.as_str()
);
}
ty::Tuple(_) => {
use crate::thir;
use crate::traits;
use crate::ty::subst::SubstsRef;
-use crate::ty::{self, Ty, TyCtxt};
+use crate::ty::{self, AdtDef, Ty, TyCtxt};
use rustc_data_structures::fx::FxHashMap;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_span::Span;
}
}
+impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for AdtDef<'tcx> {
+ fn encode(&self, e: &mut E) -> Result<(), E::Error> {
+ self.0.0.encode(e)
+ }
+}
+
impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for AllocId {
fn encode(&self, e: &mut E) -> Result<(), E::Error> {
e.encode_alloc_id(self)
&'tcx mir::Body<'tcx>,
&'tcx mir::UnsafetyCheckResult,
&'tcx mir::BorrowCheckResult<'tcx>,
- &'tcx mir::coverage::CodeRegion,
- &'tcx ty::AdtDef
+ &'tcx mir::coverage::CodeRegion
}
pub trait TyDecoder<'tcx>: Decoder {
}
}
+impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for AdtDef<'tcx> {
+ fn decode(decoder: &mut D) -> Self {
+ decoder.tcx().intern_adt_def(Decodable::decode(decoder))
+ }
+}
+
impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [(ty::Predicate<'tcx>, Span)] {
fn decode(decoder: &mut D) -> &'tcx Self {
decoder.tcx().arena.alloc_from_iter(
&'tcx mir::UnsafetyCheckResult,
&'tcx mir::BorrowCheckResult<'tcx>,
&'tcx mir::coverage::CodeRegion,
- &'tcx ty::List<ty::BoundVariableKind>,
- &'tcx ty::AdtDef
+ &'tcx ty::List<ty::BoundVariableKind>
}
#[macro_export]
use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef, UserSubsts};
use crate::ty::TyKind::*;
use crate::ty::{
- self, AdtDef, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig,
+ self, AdtDef, AdtDefData, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig,
ClosureSizeProfileData, Const, ConstS, ConstVid, DefIdTree, ExistentialPredicate, FloatTy,
FloatVar, FloatVid, GenericParamDefKind, InferConst, InferTy, IntTy, IntVar, IntVid, List,
ParamConst, ParamTy, PolyFnSig, Predicate, PredicateKind, PredicateS, ProjectionTy, Region,
const_allocation: InternedSet<'tcx, Allocation>,
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
layout: InternedSet<'tcx, LayoutS<'tcx>>,
- adt_def: InternedSet<'tcx, AdtDef>,
+ adt_def: InternedSet<'tcx, AdtDefData>,
}
impl<'tcx> CtxtInterners<'tcx> {
kind: AdtKind,
variants: IndexVec<VariantIdx, ty::VariantDef>,
repr: ReprOptions,
- ) -> &'tcx ty::AdtDef {
- self.intern_adt_def(ty::AdtDef::new(self, did, kind, variants, repr))
+ ) -> ty::AdtDef<'tcx> {
+ self.intern_adt_def(ty::AdtDefData::new(self, did, kind, variants, repr))
}
/// Allocates a read-only byte or string literal for `mir::interpret`.
const_: mk_const(ConstS<'tcx>): Const -> Const<'tcx>,
const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
layout: intern_layout(LayoutS<'tcx>): Layout -> Layout<'tcx>,
-}
-
-macro_rules! direct_interners_old {
- ($($name:ident: $method:ident($ty:ty),)+) => {
- $(impl<'tcx> Borrow<$ty> for InternedInSet<'tcx, $ty> {
- fn borrow<'a>(&'a self) -> &'a $ty {
- &self.0
- }
- }
-
- impl<'tcx> PartialEq for InternedInSet<'tcx, $ty> {
- fn eq(&self, other: &Self) -> bool {
- // The `Borrow` trait requires that `x.borrow() == y.borrow()`
- // equals `x == y`.
- self.0 == other.0
- }
- }
-
- impl<'tcx> Eq for InternedInSet<'tcx, $ty> {}
-
- impl<'tcx> Hash for InternedInSet<'tcx, $ty> {
- fn hash<H: Hasher>(&self, s: &mut H) {
- // The `Borrow` trait requires that `x.borrow().hash(s) ==
- // x.hash(s)`.
- self.0.hash(s)
- }
- }
-
- impl<'tcx> TyCtxt<'tcx> {
- pub fn $method(self, v: $ty) -> &'tcx $ty {
- self.interners.$name.intern(v, |v| {
- InternedInSet(self.interners.arena.alloc(v))
- }).0
- }
- })+
- }
-}
-
-// FIXME: eventually these should all be converted to `direct_interners`.
-direct_interners_old! {
- adt_def: intern_adt_def(AdtDef),
+ adt_def: intern_adt_def(AdtDefData): AdtDef -> AdtDef<'tcx>,
}
macro_rules! slice_interners {
}
#[inline]
- pub fn mk_adt(self, def: &'tcx AdtDef, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
+ pub fn mk_adt(self, def: AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
// Take a copy of substs so that we own the vectors inside.
self.mk_ty(Adt(def, substs))
}
pub fn mk_place_downcast(
self,
place: Place<'tcx>,
- adt_def: &'tcx AdtDef,
+ adt_def: AdtDef<'tcx>,
variant_index: VariantIdx,
) -> Place<'tcx> {
self.mk_place_elem(
place,
- PlaceElem::Downcast(Some(adt_def.variants[variant_index].name), variant_index),
+ PlaceElem::Downcast(Some(adt_def.variant(variant_index).name), variant_index),
)
}
};
err.span_suggestion_verbose(span, msg, suggestion, applicability);
- } else {
+ } else if suggestions.len() > 1 {
err.multipart_suggestion_verbose(
"consider restricting type parameters",
suggestions.into_iter().map(|(span, suggestion, _)| (span, suggestion)).collect(),
}
ty::Tuple(ref tys) if tys.is_empty() => format!("`{}`", self).into(),
- ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.def_path_str(def.did)).into(),
+ ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.def_path_str(def.did())).into(),
ty::Foreign(def_id) => format!("extern type `{}`", tcx.def_path_str(def_id)).into(),
ty::Array(t, n) => {
if t.is_simple_ty() {
ty::Int(int_type) => Some(IntSimplifiedType(int_type)),
ty::Uint(uint_type) => Some(UintSimplifiedType(uint_type)),
ty::Float(float_type) => Some(FloatSimplifiedType(float_type)),
- ty::Adt(def, _) => Some(AdtSimplifiedType(def.did)),
+ ty::Adt(def, _) => Some(AdtSimplifiedType(def.did())),
ty::Str => Some(StrSimplifiedType),
ty::Array(..) => Some(ArraySimplifiedType),
ty::Slice(..) => Some(SliceSimplifiedType),
}
}
-impl<'tcx> AdtDef {
+impl<'tcx> AdtDef<'tcx> {
/// Calculates the forest of `DefId`s from which this ADT is visibly uninhabited.
fn uninhabited_from(
- &self,
+ self,
tcx: TyCtxt<'tcx>,
substs: SubstsRef<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> DefIdForest<'tcx> {
// Non-exhaustive ADTs from other crates are always considered inhabited.
- if self.is_variant_list_non_exhaustive() && !self.did.is_local() {
+ if self.is_variant_list_non_exhaustive() && !self.did().is_local() {
DefIdForest::empty()
} else {
DefIdForest::intersection(
tcx,
- self.variants
+ self.variants()
.iter()
.map(|v| v.uninhabited_from(tcx, substs, self.adt_kind(), param_env)),
)
}
// SIMD vector types.
- ty::Adt(def, substs) if def.repr.simd() => {
+ ty::Adt(def, substs) if def.repr().simd() => {
if !def.is_struct() {
// Should have yielded E0517 by now.
tcx.sess.delay_span_bug(
ty::Adt(def, substs) => {
// Cache the field layouts.
let variants = def
- .variants
+ .variants()
.iter()
.map(|v| {
v.fields
.collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
if def.is_union() {
- if def.repr.pack.is_some() && def.repr.align.is_some() {
+ if def.repr().pack.is_some() && def.repr().align.is_some() {
self.tcx.sess.delay_span_bug(
- tcx.def_span(def.did),
+ tcx.def_span(def.did()),
"union cannot be packed and aligned",
);
return Err(LayoutError::Unknown(ty));
}
let mut align =
- if def.repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align };
+ if def.repr().pack.is_some() { dl.i8_align } else { dl.aggregate_align };
- if let Some(repr_align) = def.repr.align {
+ if let Some(repr_align) = def.repr().align {
align = align.max(AbiAndPrefAlign::new(repr_align));
}
- let optimize = !def.repr.inhibit_union_abi_opt();
+ let optimize = !def.repr().inhibit_union_abi_opt();
let mut size = Size::ZERO;
let mut abi = Abi::Aggregate { sized: true };
let index = VariantIdx::new(0);
size = cmp::max(size, field.size);
}
- if let Some(pack) = def.repr.pack {
+ if let Some(pack) = def.repr().pack {
align = align.min(AbiAndPrefAlign::new(pack));
}
// Only one variant is present.
(present_second.is_none() &&
// Representation optimizations are allowed.
- !def.repr.inhibit_enum_layout_opt());
+ !def.repr().inhibit_enum_layout_opt());
if is_struct {
// Struct, or univariant enum equivalent to a struct.
// (Typechecking will reject discriminant-sizing attrs.)
let kind = if def.is_enum() || variants[v].is_empty() {
StructKind::AlwaysSized
} else {
- let param_env = tcx.param_env(def.did);
- let last_field = def.variants[v].fields.last().unwrap();
+ let param_env = tcx.param_env(def.did());
+ let last_field = def.variant(v).fields.last().unwrap();
let always_sized =
tcx.type_of(last_field.did).is_sized(tcx.at(DUMMY_SP), param_env);
if !always_sized {
}
};
- let mut st = self.univariant_uninterned(ty, &variants[v], &def.repr, kind)?;
+ let mut st = self.univariant_uninterned(ty, &variants[v], &def.repr(), kind)?;
st.variants = Variants::Single { index: v };
- let (start, end) = self.tcx.layout_scalar_valid_range(def.did);
+ let (start, end) = self.tcx.layout_scalar_valid_range(def.did());
match st.abi {
Abi::Scalar(ref mut scalar) | Abi::ScalarPair(ref mut scalar, _) => {
// the asserts ensure that we are not using the
}
// Update `largest_niche` if we have introduced a larger niche.
- let niche = if def.repr.hide_niche() {
+ let niche = if def.repr().hide_niche() {
None
} else {
Niche::from_scalar(dl, Size::ZERO, *scalar)
// instead of actual discriminants, so dataful enums with
// explicit discriminants (RFC #2363) would misbehave.
let no_explicit_discriminants = def
- .variants
+ .variants()
.iter_enumerated()
.all(|(i, v)| v.discr == ty::VariantDiscr::Relative(i.as_u32()));
let mut niche_filling_layout = None;
// Niche-filling enum optimization.
- if !def.repr.inhibit_enum_layout_opt() && no_explicit_discriminants {
+ if !def.repr().inhibit_enum_layout_opt() && no_explicit_discriminants {
let mut dataful_variant = None;
let mut niche_variants = VariantIdx::MAX..=VariantIdx::new(0);
let mut st = self.univariant_uninterned(
ty,
v,
- &def.repr,
+ &def.repr(),
StructKind::AlwaysSized,
)?;
st.variants = Variants::Single { index: j };
}
let (mut min, mut max) = (i128::MAX, i128::MIN);
- let discr_type = def.repr.discr_type();
+ let discr_type = def.repr().discr_type();
let bits = Integer::from_attr(self, discr_type).size().bits();
for (i, discr) in def.discriminants(tcx) {
if variants[i].iter().any(|f| f.abi.is_uninhabited()) {
max = 0;
}
assert!(min <= max, "discriminant range is {}...{}", min, max);
- let (min_ity, signed) = Integer::repr_discr(tcx, ty, &def.repr, min, max);
+ let (min_ity, signed) = Integer::repr_discr(tcx, ty, &def.repr(), min, max);
let mut align = dl.aggregate_align;
let mut size = Size::ZERO;
// determining the alignment of the overall enum, and the
// determining the alignment of the payload after the tag.)
let mut prefix_align = min_ity.align(dl).abi;
- if def.repr.c() {
+ if def.repr().c() {
for fields in &variants {
for field in fields {
prefix_align = prefix_align.max(field.align.abi);
let mut st = self.univariant_uninterned(
ty,
&field_layouts,
- &def.repr,
+ &def.repr(),
StructKind::Prefixed(min_ity.size(), prefix_align),
)?;
st.variants = Variants::Single { index: i };
return Err(LayoutError::SizeOverflow(ty));
}
- let typeck_ity = Integer::from_attr(dl, def.repr.discr_type());
+ let typeck_ity = Integer::from_attr(dl, def.repr().discr_type());
if typeck_ity < min_ity {
// It is a bug if Layout decided on a greater discriminant size than typeck for
// some reason at this point (based on values discriminant can take on). Mostly
// won't be so conservative.
// Use the initial field alignment
- let mut ity = if def.repr.c() || def.repr.int.is_some() {
+ let mut ity = if def.repr().c() || def.repr().int.is_some() {
min_ity
} else {
Integer::for_align(dl, start_align).unwrap_or(min_ity)
};
let adt_kind = adt_def.adt_kind();
- let adt_packed = adt_def.repr.pack.is_some();
+ let adt_packed = adt_def.repr().pack.is_some();
let build_variant_info = |n: Option<Symbol>, flds: &[Symbol], layout: TyAndLayout<'tcx>| {
let mut min_size = Size::ZERO;
match layout.variants {
Variants::Single { index } => {
- if !adt_def.variants.is_empty() && layout.fields != FieldsShape::Primitive {
+ if !adt_def.variants().is_empty() && layout.fields != FieldsShape::Primitive {
debug!(
"print-type-size `{:#?}` variant {}",
- layout, adt_def.variants[index].name
+ layout,
+ adt_def.variant(index).name
);
- let variant_def = &adt_def.variants[index];
+ let variant_def = &adt_def.variant(index);
let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect();
record(
adt_kind.into(),
debug!(
"print-type-size `{:#?}` adt general variants def {}",
layout.ty,
- adt_def.variants.len()
+ adt_def.variants().len()
);
let variant_infos: Vec<_> = adt_def
- .variants
+ .variants()
.iter_enumerated()
.map(|(i, variant_def)| {
let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect();
ty::Adt(def, substs) => {
// Only newtypes and enums w/ nullable pointer optimization.
- if def.is_union() || def.variants.is_empty() || def.variants.len() > 2 {
+ if def.is_union() || def.variants().is_empty() || def.variants().len() > 2 {
return Err(err);
}
// Get a zero-sized variant or a pointer newtype.
let zero_or_ptr_variant = |i| {
let i = VariantIdx::new(i);
- let fields = def.variants[i]
- .fields
- .iter()
- .map(|field| SizeSkeleton::compute(field.ty(tcx, substs), tcx, param_env));
+ let fields =
+ def.variant(i).fields.iter().map(|field| {
+ SizeSkeleton::compute(field.ty(tcx, substs), tcx, param_env)
+ });
let mut ptr = None;
for field in fields {
let field = field?;
let v0 = zero_or_ptr_variant(0)?;
// Newtype.
- if def.variants.len() == 1 {
+ if def.variants().len() == 1 {
if let Some(SizeSkeleton::Pointer { non_zero, tail }) = v0 {
return Ok(SizeSkeleton::Pointer {
non_zero: non_zero
- || match tcx.layout_scalar_valid_range(def.did) {
+ || match tcx.layout_scalar_valid_range(def.did()) {
(Bound::Included(start), Bound::Unbounded) => start > 0,
(Bound::Included(start), Bound::Included(end)) => {
0 < start && start < end
}
let fields = match this.ty.kind() {
- ty::Adt(def, _) if def.variants.is_empty() =>
+ ty::Adt(def, _) if def.variants().is_empty() =>
bug!("for_variant called on zero-variant enum"),
- ty::Adt(def, _) => def.variants[variant_index].fields.len(),
+ ty::Adt(def, _) => def.variant(variant_index).fields.len(),
_ => bug!(),
};
tcx.intern_layout(LayoutS {
ty::Adt(def, substs) => {
match this.variants {
Variants::Single { index } => {
- TyMaybeWithLayout::Ty(def.variants[index].fields[i].ty(tcx, substs))
+ TyMaybeWithLayout::Ty(def.variant(index).fields[i].ty(tcx, substs))
}
// Discriminant field for enums (where applicable).
visited: &mut SsoHashSet<Ty<'a>>,
) -> Option<DefId> {
match *ty.kind() {
- ty::Adt(adt_def, _) => Some(adt_def.did),
+ ty::Adt(adt_def, _) => Some(adt_def.did()),
ty::Dynamic(data, ..) => data.principal_def_id(),
ty::BoundTyKind::Param(p) => p!(write("{}", p)),
},
ty::Adt(def, substs) => {
- p!(print_def_path(def.did, substs));
+ p!(print_def_path(def.did(), substs));
}
ty::Dynamic(data, r) => {
let print_r = self.should_print_region(r);
}
p!(")");
}
- ty::Adt(def, _) if def.variants.is_empty() => {
+ ty::Adt(def, _) if def.variants().is_empty() => {
self = self.typed_value(
|mut this| {
write!(this, "unreachable()")?;
ty::Adt(def, substs) => {
let variant_idx =
contents.variant.expect("destructed const of adt without variant idx");
- let variant_def = &def.variants[variant_idx];
+ let variant_def = &def.variant(variant_idx);
p!(print_value_path(variant_def.def_id, substs));
match variant_def.ctor_kind {
(ty::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => Ok(a),
(&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs)) if a_def == b_def => {
- let substs = relation.relate_item_substs(a_def.did, a_substs, b_substs)?;
+ let substs = relation.relate_item_substs(a_def.did(), a_substs, b_substs)?;
Ok(tcx.mk_adt(a_def, substs))
}
}
}
-impl fmt::Debug for ty::AdtDef {
+impl<'tcx> fmt::Debug for ty::AdtDef<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
ty::tls::with(|tcx| {
with_no_trimmed_paths!({
f.write_str(
&FmtPrinter::new(tcx, Namespace::TypeNS)
- .print_def_path(self.did, &[])?
+ .print_def_path(self.did(), &[])?
.into_buffer(),
)
})
// TypeFoldable implementations.
/// AdtDefs are basically the same as a DefId.
-impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::AdtDef {
+impl<'tcx> TypeFoldable<'tcx> for ty::AdtDef<'tcx> {
fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
self,
_folder: &mut F,
///
/// Note that generic parameters in fields only get lazily substituted
/// by using something like `adt_def.all_fields().map(|field| field.ty(tcx, substs))`.
- Adt(&'tcx AdtDef, SubstsRef<'tcx>),
+ Adt(AdtDef<'tcx>, SubstsRef<'tcx>),
/// An unsized FFI type that is opaque to Rust. Written as `extern type T`.
Foreign(DefId),
#[inline]
pub fn is_simd(self) -> bool {
match self.kind() {
- Adt(def, _) => def.repr.simd(),
+ Adt(def, _) => def.repr().simd(),
_ => false,
}
}
pub fn simd_size_and_type(self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) {
match self.kind() {
Adt(def, substs) => {
- assert!(def.repr.simd(), "`simd_size_and_type` called on non-SIMD type");
+ assert!(def.repr().simd(), "`simd_size_and_type` called on non-SIMD type");
let variant = def.non_enum_variant();
let f0_ty = variant.fields[0].ty(tcx, substs);
}
#[inline]
- pub fn ty_adt_def(self) -> Option<&'tcx AdtDef> {
+ pub fn ty_adt_def(self) -> Option<AdtDef<'tcx>> {
match self.kind() {
- Adt(adt, _) => Some(adt),
+ Adt(adt, _) => Some(*adt),
_ => None,
}
}
variant_index: VariantIdx,
) -> Option<Discr<'tcx>> {
match self.kind() {
- TyKind::Adt(adt, _) if adt.variants.is_empty() => {
+ TyKind::Adt(adt, _) if adt.variants().is_empty() => {
// This can actually happen during CTFE, see
// https://github.com/rust-lang/rust/issues/89765.
None
/// Returns the type of the discriminant of this type.
pub fn discriminant_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
match self.kind() {
- ty::Adt(adt, _) if adt.is_enum() => adt.repr.discr_type().to_ty(tcx),
+ ty::Adt(adt, _) if adt.is_enum() => adt.repr().discr_type().to_ty(tcx),
ty::Generator(_, substs, _) => substs.as_generator().discr_ty(tcx),
ty::Param(_) | ty::Projection(_) | ty::Opaque(..) | ty::Infer(ty::TyVar(_)) => {
/// Note that this returns only the constraints for the
/// destructor of `def` itself. For the destructors of the
/// contents, you need `adt_dtorck_constraint`.
- pub fn destructor_constraints(self, def: &'tcx ty::AdtDef) -> Vec<ty::subst::GenericArg<'tcx>> {
+ pub fn destructor_constraints(self, def: ty::AdtDef<'tcx>) -> Vec<ty::subst::GenericArg<'tcx>> {
let dtor = match def.destructor(self) {
None => {
- debug!("destructor_constraints({:?}) - no dtor", def.did);
+ debug!("destructor_constraints({:?}) - no dtor", def.did());
return vec![];
}
Some(dtor) => dtor.did,
_ => bug!(),
};
- let item_substs = match *self.type_of(def.did).kind() {
+ let item_substs = match *self.type_of(def.did()).kind() {
ty::Adt(def_, substs) if def_ == def => substs,
_ => bug!(),
};
})
.map(|(item_param, _)| item_param)
.collect();
- debug!("destructor_constraint({:?}) = {:?}", def.did, result);
+ debug!("destructor_constraint({:?}) = {:?}", def.did(), result);
result
}
self.project(PlaceElem::Deref)
}
- crate fn downcast(self, adt_def: &'tcx AdtDef, variant_index: VariantIdx) -> Self {
- self.project(PlaceElem::Downcast(Some(adt_def.variants[variant_index].name), variant_index))
+ crate fn downcast(self, adt_def: AdtDef<'tcx>, variant_index: VariantIdx) -> Self {
+ self.project(PlaceElem::Downcast(Some(adt_def.variant(variant_index).name), variant_index))
}
fn index(self, index: Local) -> Self {
.collect();
let field_names: Vec<_> =
- (0..adt_def.variants[variant_index].fields.len()).map(Field::new).collect();
+ (0..adt_def.variant(variant_index).fields.len()).map(Field::new).collect();
let fields: Vec<_> = if let Some(FruInfo { base, field_types }) = base {
let place_builder =
})
});
let adt = Box::new(AggregateKind::Adt(
- adt_def.did,
+ adt_def.did(),
variant_index,
substs,
user_ty,
/// Test what enum variant a value is.
Switch {
/// The enum type being tested.
- adt_def: &'tcx ty::AdtDef,
+ adt_def: ty::AdtDef<'tcx>,
/// The set of variants that we should create a branch for. We also
/// create an additional "otherwise" case.
variants: BitSet<VariantIdx>,
}
PatKind::Variant { adt_def, substs, variant_index, ref subpatterns } => {
- let irrefutable = adt_def.variants.iter_enumerated().all(|(i, v)| {
+ let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| {
i == variant_index || {
self.tcx.features().exhaustive_patterns
&& !v
)
.is_empty()
}
- }) && (adt_def.did.is_local()
+ }) && (adt_def.did().is_local()
|| !adt_def.is_variant_list_non_exhaustive());
if irrefutable {
let place_builder = match_pair.place.downcast(adt_def, variant_index);
/// It is a bug to call this with a not-fully-simplified pattern.
pub(super) fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
match *match_pair.pattern.kind {
- PatKind::Variant { ref adt_def, substs: _, variant_index: _, subpatterns: _ } => Test {
+ PatKind::Variant { adt_def, substs: _, variant_index: _, subpatterns: _ } => Test {
span: match_pair.pattern.span,
kind: TestKind::Switch {
adt_def,
- variants: BitSet::new_empty(adt_def.variants.len()),
+ variants: BitSet::new_empty(adt_def.variants().len()),
},
},
TestKind::Switch { adt_def, ref variants } => {
let target_blocks = make_target_blocks(self);
// Variants is a BitVec of indexes into adt_def.variants.
- let num_enum_variants = adt_def.variants.len();
+ let num_enum_variants = adt_def.variants().len();
debug_assert_eq!(target_blocks.len(), num_enum_variants + 1);
let otherwise_block = *target_blocks.last().unwrap();
let tcx = self.tcx;
otherwise_block,
);
debug!("num_enum_variants: {}, variants: {:?}", num_enum_variants, variants);
- let discr_ty = adt_def.repr.discr_type().to_ty(tcx);
+ let discr_ty = adt_def.repr().discr_type().to_ty(tcx);
let discr = self.temp(discr_ty, test.span);
self.cfg.push_assign(
block,
fn candidate_after_variant_switch<'pat>(
&mut self,
match_pair_index: usize,
- adt_def: &'tcx ty::AdtDef,
+ adt_def: ty::AdtDef<'tcx>,
variant_index: VariantIdx,
subpatterns: &'pat [FieldPat<'tcx>],
candidate: &mut Candidate<'pat, 'tcx>,
// we want to create a set of derived match-patterns like
// `(x as Variant).0 @ P1` and `(x as Variant).1 @ P1`.
let elem =
- ProjectionElem::Downcast(Some(adt_def.variants[variant_index].name), variant_index);
+ ProjectionElem::Downcast(Some(adt_def.variant(variant_index).name), variant_index);
let downcast_place = match_pair.place.project(elem); // `(x as Variant)`
let consequent_match_pairs = subpatterns.iter().map(|subpattern| {
// e.g., `(x as Variant).0`
// variants, we have a target for each variant and the
// otherwise case, and we make sure that all of the cases not
// specified have the same block.
- adt_def.variants.len() + 1
+ adt_def.variants().len() + 1
}
TestKind::SwitchInt { switch_ty, ref options, .. } => {
if switch_ty.is_bool() {
ExprKind::Field { lhs, .. } => {
if let ty::Adt(adt_def, _) = self.thir[lhs].ty.kind() {
if (Bound::Unbounded, Bound::Unbounded)
- != self.tcx.layout_scalar_valid_range(adt_def.did)
+ != self.tcx.layout_scalar_valid_range(adt_def.did())
{
self.found = true;
}
visit::walk_pat(self, pat);
self.in_union_destructure = old_in_union_destructure;
} else if (Bound::Unbounded, Bound::Unbounded)
- != self.tcx.layout_scalar_valid_range(adt_def.did)
+ != self.tcx.layout_scalar_valid_range(adt_def.did())
{
let old_inside_adt = std::mem::replace(&mut self.inside_adt, true);
visit::walk_pat(self, pat);
user_ty: _,
fields: _,
base: _,
- }) => match self.tcx.layout_scalar_valid_range(adt_def.did) {
+ }) => match self.tcx.layout_scalar_valid_range(adt_def.did()) {
(Bound::Unbounded, Bound::Unbounded) => {}
_ => self.requires_unsafe(expr.span, InitializingTypeWith),
},
let user_ty =
user_provided_types.get(fun.hir_id).copied().map(|mut u_ty| {
if let UserType::TypeOf(ref mut did, _) = &mut u_ty.value {
- *did = adt_def.did;
+ *did = adt_def.did();
}
u_ty
});
let user_ty = user_provided_types.get(expr.hir_id).copied();
debug!("make_mirror_unadjusted: (struct/union) user_ty={:?}", user_ty);
ExprKind::Adt(Box::new(Adt {
- adt_def: adt,
+ adt_def: *adt,
variant_index: VariantIdx::new(0),
substs,
user_ty,
let user_ty = user_provided_types.get(expr.hir_id).copied();
debug!("make_mirror_unadjusted: (variant) user_ty={:?}", user_ty);
ExprKind::Adt(Box::new(Adt {
- adt_def: adt,
+ adt_def: *adt,
variant_index: index,
substs,
user_ty,
let idx = adt_def.variant_index_with_ctor_id(variant_ctor_id);
let (d, o) = adt_def.discriminant_def_for_variant(idx);
use rustc_middle::ty::util::IntTypeExt;
- let ty = adt_def.repr.discr_type();
+ let ty = adt_def.repr().discr_type();
let ty = ty.to_ty(self.tcx());
Some((d, o, ty))
}
// A unit struct/variant which is used as a value.
// We return a completely different ExprKind here to account for this special case.
ty::Adt(adt_def, substs) => ExprKind::Adt(Box::new(Adt {
- adt_def,
+ adt_def: *adt_def,
variant_index: adt_def.variant_index_with_ctor_id(def_id),
substs,
user_ty: user_provided_type,
&& let pat_ty = cx.typeck_results.pat_ty(p).peel_refs()
&& let ty::Adt(edef, _) = pat_ty.kind()
&& edef.is_enum()
- && edef.variants.iter().any(|variant| {
+ && edef.variants().iter().any(|variant| {
variant.ident(cx.tcx) == ident && variant.ctor_kind == CtorKind::Const
})
{
- let variant_count = edef.variants.len();
+ let variant_count = edef.variants().len();
cx.tcx.struct_span_lint_hir(
BINDINGS_WITH_VARIANT_NAME,
p.hir_id,
p.span,
|lint| {
- let ty_path = cx.tcx.def_path_str(edef.did);
+ let ty_path = cx.tcx.def_path_str(edef.did());
let mut err = lint.build(&format!(
"pattern binding `{}` is named the same as one \
of the variants of the type `{}`",
) {
let is_empty_match = arms.is_empty();
let non_empty_enum = match scrut_ty.kind() {
- ty::Adt(def, _) => def.is_enum() && !def.variants.is_empty(),
+ ty::Adt(def, _) => def.is_enum() && !def.variants().is_empty(),
_ => false,
};
// In the case of an empty match, replace the '`_` not covered' diagnostic with something more
};
let is_variant_list_non_exhaustive = match scrut_ty.kind() {
- ty::Adt(def, _) if def.is_variant_list_non_exhaustive() && !def.did.is_local() => true,
+ ty::Adt(def, _) if def.is_variant_list_non_exhaustive() && !def.did().is_local() => true,
_ => false,
};
if let ty::Adt(def, _) = ty.kind() {
let mut spans = vec![];
if witnesses.len() < 5 {
- for sp in maybe_point_at_variant(cx, def, witnesses.iter()) {
+ for sp in maybe_point_at_variant(cx, *def, witnesses.iter()) {
spans.push(sp);
}
}
let def_span = cx
.tcx
.hir()
- .get_if_local(def.did)
+ .get_if_local(def.did())
.and_then(|node| node.ident())
.map(|ident| ident.span)
- .unwrap_or_else(|| cx.tcx.def_span(def.did));
+ .unwrap_or_else(|| cx.tcx.def_span(def.did()));
let mut span: MultiSpan =
if spans.is_empty() { def_span.into() } else { spans.clone().into() };
fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>(
cx: &MatchCheckCtxt<'p, 'tcx>,
- def: &AdtDef,
+ def: AdtDef<'tcx>,
patterns: impl Iterator<Item = &'a DeconstructedPat<'p, 'tcx>>,
) -> Vec<Span> {
use Constructor::*;
let mut covered = vec![];
for pattern in patterns {
if let Variant(variant_index) = pattern.ctor() {
- if let ty::Adt(this_def, _) = pattern.ty().kind() && this_def.did != def.did {
+ if let ty::Adt(this_def, _) = pattern.ty().kind() && this_def.did() != def.did() {
continue;
}
- let sp = def.variants[*variant_index].ident(cx.tcx).span;
+ let sp = def.variant(*variant_index).ident(cx.tcx).span;
if covered.contains(&sp) {
// Don't point at variants that have already been covered due to other patterns to avoid
// visual clutter.
self.infcx.tcx
}
- fn adt_derive_msg(&self, adt_def: &AdtDef) -> String {
- let path = self.tcx().def_path_str(adt_def.did);
+ fn adt_derive_msg(&self, adt_def: AdtDef<'tcx>) -> String {
+ let path = self.tcx().def_path_str(adt_def.did());
format!(
"to use a constant of type `{}` in a pattern, \
`{}` must be annotated with `#[derive(PartialEq, Eq)]`",
adt_def,
cv.ty()
);
- let path = tcx.def_path_str(adt_def.did);
+ let path = tcx.def_path_str(adt_def.did());
let msg = format!(
"to use a constant of type `{}` in a pattern, \
`{}` must be annotated with `#[derive(PartialEq, Eq)]`",
ty::Adt(adt_def, substs) if adt_def.is_enum() => {
let destructured = tcx.destructure_const(param_env.and(cv));
PatKind::Variant {
- adt_def,
+ adt_def: *adt_def,
substs,
variant_index: destructured
.variant
/// This means that the variant has a stdlib unstable feature marking it.
pub(super) fn is_unstable_variant(&self, pcx: PatCtxt<'_, '_, 'tcx>) -> bool {
if let Constructor::Variant(idx) = self && let ty::Adt(adt, _) = pcx.ty.kind() {
- let variant_def_id = adt.variants[*idx].def_id;
+ let variant_def_id = adt.variant(*idx).def_id;
// Filter variants that depend on a disabled unstable feature.
return matches!(
pcx.cx.tcx.eval_stability(variant_def_id, None, DUMMY_SP, None),
}
/// Checks if the `Constructor` is a `Constructor::Variant` with a `#[doc(hidden)]`
- /// attribute.
+ /// attribute from a type not local to the current crate.
pub(super) fn is_doc_hidden_variant(&self, pcx: PatCtxt<'_, '_, 'tcx>) -> bool {
if let Constructor::Variant(idx) = self && let ty::Adt(adt, _) = pcx.ty.kind() {
- let variant_def_id = adt.variants[*idx].def_id;
- return pcx.cx.tcx.is_doc_hidden(variant_def_id);
+ let variant_def_id = adt.variants()[*idx].def_id;
+ return pcx.cx.tcx.is_doc_hidden(variant_def_id) && !variant_def_id.is_local();
}
false
}
- fn variant_index_for_adt(&self, adt: &'tcx ty::AdtDef) -> VariantIdx {
+ fn variant_index_for_adt(&self, adt: ty::AdtDef<'tcx>) -> VariantIdx {
match *self {
Variant(idx) => idx,
Single => {
// patterns. If we're here we can assume this is a box pattern.
1
} else {
- let variant = &adt.variants[self.variant_index_for_adt(adt)];
+ let variant = &adt.variant(self.variant_index_for_adt(*adt));
Fields::list_variant_nonhidden_fields(pcx.cx, pcx.ty, variant).count()
}
}
// exception is if the pattern is at the top level, because we want empty matches to be
// considered exhaustive.
let is_secretly_empty =
- def.variants.is_empty() && !is_exhaustive_pat_feature && !pcx.is_top_level;
+ def.variants().is_empty() && !is_exhaustive_pat_feature && !pcx.is_top_level;
let mut ctors: SmallVec<[_; 1]> = def
- .variants
+ .variants()
.iter_enumerated()
.filter(|(_, v)| {
// If `exhaustive_patterns` is enabled, we exclude variants known to be
) -> impl Iterator<Item = (Field, Ty<'tcx>)> + Captures<'a> + Captures<'p> {
let ty::Adt(adt, substs) = ty.kind() else { bug!() };
// Whether we must not match the fields of this variant exhaustively.
- let is_non_exhaustive = variant.is_field_list_non_exhaustive() && !adt.did.is_local();
+ let is_non_exhaustive = variant.is_field_list_non_exhaustive() && !adt.did().is_local();
variant.fields.iter().enumerate().filter_map(move |(i, field)| {
let ty = field.ty(cx.tcx, substs);
// patterns. If we're here we can assume this is a box pattern.
Fields::wildcards_from_tys(cx, once(substs.type_at(0)))
} else {
- let variant = &adt.variants[constructor.variant_index_for_adt(adt)];
+ let variant = &adt.variant(constructor.variant_index_for_adt(*adt));
let tys = Fields::list_variant_nonhidden_fields(cx, ty, variant)
.map(|(_, ty)| ty);
Fields::wildcards_from_tys(cx, tys)
PatKind::Variant { variant_index, .. } => Variant(*variant_index),
_ => bug!(),
};
- let variant = &adt.variants[ctor.variant_index_for_adt(adt)];
+ let variant = &adt.variant(ctor.variant_index_for_adt(*adt));
// For each field in the variant, we store the relevant index into `self.fields` if any.
let mut field_id_to_id: Vec<Option<usize>> =
(0..variant.fields.len()).map(|_| None).collect();
PatKind::Deref { subpattern: subpatterns.next().unwrap() }
}
ty::Adt(adt_def, substs) => {
- let variant_index = self.ctor.variant_index_for_adt(adt_def);
- let variant = &adt_def.variants[variant_index];
+ let variant_index = self.ctor.variant_index_for_adt(*adt_def);
+ let variant = &adt_def.variant(variant_index);
let subpatterns = Fields::list_variant_nonhidden_fields(cx, self.ty, variant)
.zip(subpatterns)
.map(|((field, _ty), pattern)| FieldPat { field, pattern })
.collect();
if adt_def.is_enum() {
- PatKind::Variant { adt_def, substs, variant_index, subpatterns }
+ PatKind::Variant { adt_def: *adt_def, substs, variant_index, subpatterns }
} else {
PatKind::Leaf { subpatterns }
}
}
ty::Adt(..) | ty::Tuple(..) => {
let variant = match self.ty.kind() {
- ty::Adt(adt, _) => {
- Some(&adt.variants[self.ctor.variant_index_for_adt(adt)])
- }
+ ty::Adt(adt, _) => Some(adt.variant(self.ctor.variant_index_for_adt(*adt))),
ty::Tuple(_) => None,
_ => unreachable!(),
};
CloneImpls! { <'tcx>
Span, Field, Mutability, Symbol, hir::HirId, usize, ty::Const<'tcx>,
- Region<'tcx>, Ty<'tcx>, BindingMode, &'tcx AdtDef,
+ Region<'tcx>, Ty<'tcx>, BindingMode, AdtDef<'tcx>,
SubstsRef<'tcx>, &'tcx GenericArg<'tcx>, UserType<'tcx>,
UserTypeProjection, PatTyProj<'tcx>
}
pub(super) fn is_foreign_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
match ty.kind() {
ty::Adt(def, ..) => {
- def.is_enum() && def.is_variant_list_non_exhaustive() && !def.did.is_local()
+ def.is_enum() && def.is_variant_list_non_exhaustive() && !def.did().is_local()
}
_ => false,
}
match ty.kind() {
ty::Adt(adt_def, ..) => {
if let UserType::TypeOf(ref mut did, _) = &mut user_ty.value {
- *did = adt_def.did;
+ *did = adt_def.did();
}
Some(user_ty)
}
self.drop_ladder(fields, succ, unwind).0
}
- fn open_drop_for_box(&mut self, adt: &'tcx ty::AdtDef, substs: SubstsRef<'tcx>) -> BasicBlock {
+ fn open_drop_for_box(&mut self, adt: ty::AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> BasicBlock {
debug!("open_drop_for_box({:?}, {:?}, {:?})", self, adt, substs);
let interior = self.tcx().mk_place_deref(self.place);
self.drop_subpath(interior, interior_path, succ, unwind_succ)
}
- fn open_drop_for_adt(&mut self, adt: &'tcx ty::AdtDef, substs: SubstsRef<'tcx>) -> BasicBlock {
+ fn open_drop_for_adt(&mut self, adt: ty::AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> BasicBlock {
debug!("open_drop_for_adt({:?}, {:?}, {:?})", self, adt, substs);
- if adt.variants.is_empty() {
+ if adt.variants().is_empty() {
return self.elaborator.patch().new_block(BasicBlockData {
statements: vec![],
terminator: Some(Terminator {
}
let skip_contents =
- adt.is_union() || Some(adt.did) == self.tcx().lang_items().manually_drop();
+ adt.is_union() || Some(adt.did()) == self.tcx().lang_items().manually_drop();
let contents_drop = if skip_contents {
(self.succ, self.unwind)
} else {
fn open_drop_for_adt_contents(
&mut self,
- adt: &'tcx ty::AdtDef,
+ adt: ty::AdtDef<'tcx>,
substs: SubstsRef<'tcx>,
) -> (BasicBlock, Unwind) {
let (succ, unwind) = self.drop_ladder_bottom();
let fields = self.move_paths_for_fields(
self.place,
self.path,
- &adt.variants[VariantIdx::new(0)],
+ &adt.variant(VariantIdx::new(0)),
substs,
);
self.drop_ladder(fields, succ, unwind)
fn open_drop_for_multivariant(
&mut self,
- adt: &'tcx ty::AdtDef,
+ adt: ty::AdtDef<'tcx>,
substs: SubstsRef<'tcx>,
succ: BasicBlock,
unwind: Unwind,
) -> (BasicBlock, Unwind) {
- let mut values = Vec::with_capacity(adt.variants.len());
- let mut normal_blocks = Vec::with_capacity(adt.variants.len());
+ let mut values = Vec::with_capacity(adt.variants().len());
+ let mut normal_blocks = Vec::with_capacity(adt.variants().len());
let mut unwind_blocks =
- if unwind.is_cleanup() { None } else { Some(Vec::with_capacity(adt.variants.len())) };
+ if unwind.is_cleanup() { None } else { Some(Vec::with_capacity(adt.variants().len())) };
let mut have_otherwise_with_drop_glue = false;
let mut have_otherwise = false;
let tcx = self.tcx();
for (variant_index, discr) in adt.discriminants(tcx) {
- let variant = &adt.variants[variant_index];
+ let variant = &adt.variant(variant_index);
let subpath = self.elaborator.downcast_subpath(self.path, variant_index);
if let Some(variant_path) = subpath {
fn adt_switch_block(
&mut self,
- adt: &'tcx ty::AdtDef,
+ adt: ty::AdtDef<'tcx>,
blocks: Vec<BasicBlock>,
values: &[u128],
succ: BasicBlock,
// Additionally, we do not want to switch on the
// discriminant after it is free-ed, because that
// way lies only trouble.
- let discr_ty = adt.repr.discr_type().to_ty(self.tcx());
+ let discr_ty = adt.repr().discr_type().to_ty(self.tcx());
let discr = Place::from(self.new_temp(discr_ty));
let discr_rv = Rvalue::Discriminant(self.place);
let switch_block = BasicBlockData {
ty::Tuple(fields) => self.open_drop_for_tuple(fields),
ty::Adt(def, substs) => {
if def.is_box() {
- self.open_drop_for_box(def, substs)
+ self.open_drop_for_box(*def, substs)
} else {
- self.open_drop_for_adt(def, substs)
+ self.open_drop_for_adt(*def, substs)
}
}
ty::Dynamic(..) => self.complete_drop(self.succ, self.unwind),
/// The contained value will not be dropped.
fn box_free_block(
&mut self,
- adt: &'tcx ty::AdtDef,
+ adt: ty::AdtDef<'tcx>,
substs: SubstsRef<'tcx>,
target: BasicBlock,
unwind: Unwind,
/// value).
fn unelaborated_free_block(
&mut self,
- adt: &'tcx ty::AdtDef,
+ adt: ty::AdtDef<'tcx>,
substs: SubstsRef<'tcx>,
target: BasicBlock,
unwind: Unwind,
let tcx = self.tcx();
let unit_temp = Place::from(self.new_temp(tcx.mk_unit()));
let free_func = tcx.require_lang_item(LangItem::BoxFree, Some(self.source_info.span));
- let args = adt.variants[VariantIdx::new(0)]
+ let args = adt
+ .variant(VariantIdx::new(0))
.fields
.iter()
.enumerate()
body: &'mir mir::Body<'tcx>,
block: &'mir mir::BasicBlockData<'tcx>,
switch_on: mir::Place<'tcx>,
-) -> Option<(mir::Place<'tcx>, &'tcx ty::AdtDef)> {
+) -> Option<(mir::Place<'tcx>, ty::AdtDef<'tcx>)> {
for statement in block.statements.iter().rev() {
match &statement.kind {
mir::StatementKind::Assign(box (lhs, mir::Rvalue::Discriminant(discriminated)))
if *lhs == switch_on =>
{
- match &discriminated.ty(body, tcx).ty.kind() {
- ty::Adt(def, _) => return Some((*discriminated, def)),
+ match discriminated.ty(body, tcx).ty.kind() {
+ ty::Adt(def, _) => return Some((*discriminated, *def)),
// `Rvalue::Discriminant` is also used to get the active yield point for a
// generator, but we do not need edge-specific effects in that case. This may
ProjectionElem::Field(..) => {
let ty = place_base.ty(&self.body.local_decls, self.tcx).ty;
if let ty::Adt(def, _) = ty.kind() {
- if self.tcx.layout_scalar_valid_range(def.did)
+ if self.tcx.layout_scalar_valid_range(def.did())
!= (Bound::Unbounded, Bound::Unbounded)
{
let details = if is_mut_use {
struct TransformVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
- state_adt_ref: &'tcx AdtDef,
+ state_adt_ref: AdtDef<'tcx>,
state_substs: SubstsRef<'tcx>,
// The type of the discriminant in the generator struct
val: Operand<'tcx>,
source_info: SourceInfo,
) -> impl Iterator<Item = Statement<'tcx>> {
- let kind = AggregateKind::Adt(self.state_adt_ref.did, idx, self.state_substs, None, None);
- assert_eq!(self.state_adt_ref.variants[idx].fields.len(), 1);
+ let kind = AggregateKind::Adt(self.state_adt_ref.did(), idx, self.state_substs, None, None);
+ assert_eq!(self.state_adt_ref.variant(idx).fields.len(), 1);
let ty = self
.tcx
- .type_of(self.state_adt_ref.variants[idx].fields[0].did)
+ .type_of(self.state_adt_ref.variant(idx).fields[0].did)
.subst(self.tcx, self.state_substs);
expand_aggregate(
Place::return_place(),
//
// If its projection *is* present in `MoveData`, then the field may have been moved
// from separate from its parent. Recurse.
- adt.variants.iter_enumerated().any(|(vid, variant)| {
+ adt.variants().iter_enumerated().any(|(vid, variant)| {
// Enums have multiple variants, which are discriminated with a `Downcast` projection.
// Structs have a single variant, and don't use a `Downcast` projection.
let mpi = if adt.is_enum() {
let statements = expand_aggregate(
Place::return_place(),
- adt_def.variants[variant_index].fields.iter().enumerate().map(|(idx, field_def)| {
+ adt_def.variant(variant_index).fields.iter().enumerate().map(|(idx, field_def)| {
(Operand::Move(Place::from(Local::new(idx + 1))), field_def.ty(tcx, substs))
}),
- AggregateKind::Adt(adt_def.did, variant_index, substs, None, None),
+ AggregateKind::Adt(adt_def.did(), variant_index, substs, None, None),
source_info,
tcx,
)
);
return StatementEquality::NotEqual;
}
- let variant_is_fieldless = adt.variants[variant_index].fields.is_empty();
+ let variant_is_fieldless = adt.variant(variant_index).fields.is_empty();
if !variant_is_fieldless {
trace!("NO: variant {:?} was not fieldless", variant_index);
return StatementEquality::NotEqual;
let value = self.mk_expr_err(start.to(expr.span));
err.emit();
return Ok(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value }));
+ } else if token::Colon == snapshot.token.kind
+ && expr.span.lo() == snapshot.token.span.hi()
+ && matches!(expr.kind, ExprKind::Path(..))
+ {
+ // Find a mistake like "foo::var:A".
+ err.span_suggestion(
+ snapshot.token.span,
+ "write a path separator here",
+ "::".to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ err.emit();
+ return Ok(GenericArg::Type(self.mk_ty(start.to(expr.span), TyKind::Err)));
} else if token::Comma == self.token.kind || self.token.kind.should_end_const_arg()
{
// Avoid the following output by checking that we consumed a full const arg:
let name = self.parse_field_ident(adt_ty, lo)?;
self.expect_field_ty_separator()?;
let ty = self.parse_ty()?;
+ if self.token.kind == token::Colon && self.look_ahead(1, |tok| tok.kind != token::Colon) {
+ self.struct_span_err(self.token.span, "found single colon in a struct field type path")
+ .span_suggestion_verbose(
+ self.token.span,
+ "write a path separator here",
+ "::".to_string(),
+ Applicability::MaybeIncorrect,
+ )
+ .emit();
+ }
if self.token.kind == token::Eq {
self.bump();
let const_expr = self.parse_anon_const_expr()?;
if self.tcx.has_attr(trait_of, sym::rustc_trivial_field_reads) {
let trait_ref = self.tcx.impl_trait_ref(impl_of).unwrap();
if let ty::Adt(adt_def, _) = trait_ref.self_ty().kind() {
- if let Some(adt_def_id) = adt_def.did.as_local() {
+ if let Some(adt_def_id) = adt_def.did().as_local() {
self.ignored_derived_traits
.entry(adt_def_id)
.or_default()
match item.kind {
hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
let def = self.tcx.adt_def(item.def_id);
- self.repr_has_repr_c = def.repr.c();
+ self.repr_has_repr_c = def.repr().c();
intravisit::walk_item(self, &item);
}
self.repr_has_repr_c = had_repr_c;
}
- fn mark_as_used_if_union(&mut self, adt: &ty::AdtDef, fields: &[hir::ExprField<'_>]) {
- if adt.is_union() && adt.non_enum_variant().fields.len() > 1 && adt.did.is_local() {
+ fn mark_as_used_if_union(&mut self, adt: ty::AdtDef<'tcx>, fields: &[hir::ExprField<'_>]) {
+ if adt.is_union() && adt.non_enum_variant().fields.len() > 1 && adt.did().is_local() {
for field in fields {
let index = self.tcx.field_index(field.hir_id, self.typeck_results());
self.insert_def_id(adt.non_enum_variant().fields[index].did);
hir::ExprKind::Struct(ref qpath, ref fields, _) => {
let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
self.handle_res(res);
- if let ty::Adt(ref adt, _) = self.typeck_results().expr_ty(expr).kind() {
- self.mark_as_used_if_union(adt, fields);
+ if let ty::Adt(adt, _) = self.typeck_results().expr_ty(expr).kind() {
+ self.mark_as_used_if_union(*adt, fields);
}
}
_ => (),
fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
let ty::Adt(def, substs) = *ty.kind() else { return ty };
- if def.variants.len() == 2 && !def.repr.c() && def.repr.int.is_none() {
+ if def.variants().len() == 2 && !def.repr().c() && def.repr().int.is_none() {
let data_idx;
let one = VariantIdx::new(1);
let zero = VariantIdx::new(0);
- if def.variants[zero].fields.is_empty() {
+ if def.variant(zero).fields.is_empty() {
data_idx = one;
- } else if def.variants[one].fields.is_empty() {
+ } else if def.variant(one).fields.is_empty() {
data_idx = zero;
} else {
return ty;
}
- if def.variants[data_idx].fields.len() == 1 {
- return def.variants[data_idx].fields[0].ty(tcx, substs);
+ if def.variant(data_idx).fields.len() == 1 {
+ return def.variant(data_idx).fields[0].ty(tcx, substs);
}
}
ty::RawPtr(ty::TypeAndMut { ty, mutbl: _ }) if self.is_thin_ptr_ty(ty) => {
Some(asm_ty_isize)
}
- ty::Adt(adt, substs) if adt.repr.simd() => {
+ ty::Adt(adt, substs) if adt.repr().simd() => {
let fields = &adt.non_enum_variant().fields;
let elem_ty = fields[0].ty(self.tcx, substs);
match elem_ty.kind() {
use rustc_ast::MacroDef;
use rustc_attr as attr;
use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::intern::Interned;
use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
let tcx = self.def_id_visitor.tcx();
// InternalSubsts are not visited here because they are visited below in `super_visit_with`.
match *ty.kind() {
- ty::Adt(&ty::AdtDef { did: def_id, .. }, ..)
+ ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), ..)
| ty::Foreign(def_id)
| ty::FnDef(def_id, ..)
| ty::Closure(def_id, ..)
&mut self,
use_ctxt: Span, // syntax context of the field name at the use site
span: Span, // span of the field pattern, e.g., `x: 0`
- def: &'tcx ty::AdtDef, // definition of the struct or enum
+ def: ty::AdtDef<'tcx>, // definition of the struct or enum
field: &'tcx ty::FieldDef,
in_update_syntax: bool,
) {
// definition of the field
let ident = Ident::new(kw::Empty, use_ctxt);
let hir_id = self.tcx.hir().local_def_id_to_hir_id(self.current_item);
- let def_id = self.tcx.adjust_ident_and_get_scope(ident, def.did, hir_id).1;
+ let def_id = self.tcx.adjust_ident_and_get_scope(ident, def.did(), hir_id).1;
if !field.vis.is_accessible_from(def_id, self.tcx) {
let label = if in_update_syntax {
format!("field `{}` is private", field.name)
"field `{}` of {} `{}` is private",
field.name,
def.variant_descr(),
- self.tcx.def_path_str(def.did)
+ self.tcx.def_path_str(def.did())
)
.span_label(span, label)
.emit();
Some(Data::RefData(Ref {
kind: RefKind::Type,
span,
- ref_id: id_from_def_id(def.did),
+ ref_id: id_from_def_id(def.did()),
}))
}
_ => {
use rustc_data_structures::base_n;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::intern::Interned;
use rustc_hir as hir;
use rustc_hir::def::CtorKind;
use rustc_hir::def_id::{CrateNum, DefId};
}
// Mangle all nominal types as paths.
- ty::Adt(&ty::AdtDef { did: def_id, .. }, substs)
+ ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), substs)
| ty::FnDef(def_id, substs)
| ty::Opaque(def_id, substs)
| ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs })
ty::Adt(def, substs) => {
let variant_idx =
contents.variant.expect("destructed const of adt without variant idx");
- let variant_def = &def.variants[variant_idx];
+ let variant_def = &def.variant(variant_idx);
self.push("V");
self = self.print_def_path(variant_def.def_id, substs)?;
match types.next() {
None => {
tcx.sess.span_err(
- tcx.def_span(def.did),
+ tcx.def_span(def.did()),
"`#[fundamental]` requires at least one type parameter",
);
InCrate::Remote => true,
},
- ty::Adt(def, _) => def_id_is_local(def.did, in_crate),
+ ty::Adt(def, _) => def_id_is_local(def.did(), in_crate),
ty::Foreign(did) => def_id_is_local(did, in_crate),
ty::Opaque(..) => {
// This merits some explanation.
| ty::Foreign(did)
| ty::FnDef(did, _)
| ty::Generator(did, ..) => Some(did),
- ty::Adt(def, _) => Some(def.did),
+ ty::Adt(def, _) => Some(def.did()),
_ => None,
};
ty::Bool => Some(0),
ty::Char => Some(1),
ty::Str => Some(2),
- ty::Adt(def, _) if tcx.is_diagnostic_item(sym::String, def.did) => Some(2),
+ ty::Adt(def, _) if tcx.is_diagnostic_item(sym::String, def.did()) => Some(2),
ty::Int(..)
| ty::Uint(..)
| ty::Float(..)
if let Some(def) = self_ty.ty_adt_def() {
// We also want to be able to select self's original
// signature with no type arguments resolved
- flags.push((sym::_Self, Some(self.tcx.type_of(def.did).to_string())));
+ flags.push((sym::_Self, Some(self.tcx.type_of(def.did()).to_string())));
}
for param in generics.params.iter() {
if let Some(def) = param_ty.ty_adt_def() {
// We also want to be able to select the parameter's
// original signature with no type arguments resolved
- flags.push((name, Some(self.tcx.type_of(def.did).to_string())));
+ flags.push((name, Some(self.tcx.type_of(def.did()).to_string())));
}
}
}
- if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) {
+ if let Some(true) = self_ty.ty_adt_def().map(|def| def.did().is_local()) {
flags.push((sym::crate_local, None));
}
if let Some(def) = aty.ty_adt_def() {
// We also want to be able to select the array's type's original
// signature with no type arguments resolved
- let type_string = self.tcx.type_of(def.did).to_string();
+ let type_string = self.tcx.type_of(def.did()).to_string();
flags.push((sym::_Self, Some(format!("[{}]", type_string))));
let len =
if !is_upvar_tys_infer_tuple {
let msg = format!("required because it appears within the type `{}`", ty);
match ty.kind() {
- ty::Adt(def, _) => match self.tcx.opt_item_name(def.did) {
+ ty::Adt(def, _) => match self.tcx.opt_item_name(def.did()) {
Some(ident) => err.span_note(ident.span, &msg),
None => err.note(&msg),
},
};
let mut infringing = Vec::new();
- for variant in &adt.variants {
+ for variant in adt.variants() {
for field in &variant.fields {
let ty = field.ty(tcx, substs);
if ty.references_error() {
// If it does not, then this field probably doesn't normalize
// to begin with, and point to the bad field's span instead.
let cause = if field
- .ty(tcx, traits::InternalSubsts::identity_for_item(tcx, adt.did))
+ .ty(tcx, traits::InternalSubsts::identity_for_item(tcx, adt.did()))
.has_param_types_or_consts()
{
cause.clone()
}
ty::Adt(def, _) => {
- if Some(def.did) == tcx.lang_items().manually_drop() {
+ if Some(def.did()) == tcx.lang_items().manually_drop() {
// `ManuallyDrop` never has a dtor.
true
} else {
#[derive(Debug)]
pub enum NonStructuralMatchTy<'tcx> {
- Adt(&'tcx AdtDef),
+ Adt(AdtDef<'tcx>),
Param,
Dynamic,
Foreign,
}
};
- if !self.seen.insert(adt_def.did) {
+ if !self.seen.insert(adt_def.did()) {
debug!("Search already seen adt_def: {:?}", adt_def);
return ControlFlow::CONTINUE;
}
if !self.type_marked_structural(ty) {
debug!("Search found ty: {:?}", ty);
- return ControlFlow::Break(NonStructuralMatchTy::Adt(&adt_def));
+ return ControlFlow::Break(NonStructuralMatchTy::Adt(adt_def));
}
// structural-match does not care about the
ty::Adt(def, substs) => {
// WfNominalType
- let obligations = self.nominal_obligations(def.did, substs);
+ let obligations = self.nominal_obligations(def.did(), substs);
self.out.extend(obligations);
}
) -> Arc<chalk_solve::rust_ir::AdtDatum<RustInterner<'tcx>>> {
let adt_def = adt_id.0;
- let bound_vars = bound_vars_for_item(self.interner.tcx, adt_def.did);
+ let bound_vars = bound_vars_for_item(self.interner.tcx, adt_def.did());
let binders = binders_for(self.interner, bound_vars);
- let where_clauses = self.where_clauses_for(adt_def.did, bound_vars);
+ let where_clauses = self.where_clauses_for(adt_def.did(), bound_vars);
let variants: Vec<_> = adt_def
- .variants
+ .variants()
.iter()
.map(|variant| chalk_solve::rust_ir::AdtVariantDatum {
fields: variant
chalk_solve::rust_ir::AdtDatumBound { variants, where_clauses },
),
flags: chalk_solve::rust_ir::AdtFlags {
- upstream: !adt_def.did.is_local(),
+ upstream: !adt_def.did().is_local(),
fundamental: adt_def.is_fundamental(),
phantom_data: adt_def.is_phantom_data(),
},
let int = |i| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Int(i)).intern(self.interner);
let uint = |i| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Uint(i)).intern(self.interner);
Arc::new(chalk_solve::rust_ir::AdtRepr {
- c: adt_def.repr.c(),
- packed: adt_def.repr.packed(),
- int: adt_def.repr.int.map(|i| match i {
+ c: adt_def.repr().c(),
+ packed: adt_def.repr().packed(),
+ int: adt_def.repr().int.map(|i| match i {
attr::IntType::SignedInt(ty) => match ty {
ast::IntTy::Isize => int(chalk_ir::IntTy::Isize),
ast::IntTy::I8 => int(chalk_ir::IntTy::I8),
let trait_ref = self.interner.tcx.impl_trait_ref(impl_def_id).unwrap();
let self_ty = trait_ref.self_ty();
let provides = match (self_ty.kind(), chalk_ty) {
- (&ty::Adt(impl_adt_def, ..), Adt(id, ..)) => impl_adt_def.did == id.0.did,
+ (&ty::Adt(impl_adt_def, ..), Adt(id, ..)) => impl_adt_def.did() == id.0.did(),
(_, AssociatedType(_ty_id, ..)) => {
// FIXME(chalk): See https://github.com/rust-lang/rust/pull/77152#discussion_r494484774
false
&self,
adt_id: chalk_ir::AdtId<RustInterner<'tcx>>,
) -> chalk_ir::Variances<RustInterner<'tcx>> {
- let variances = self.interner.tcx.variances_of(adt_id.0.did);
+ let variances = self.interner.tcx.variances_of(adt_id.0.did());
chalk_ir::Variances::from_iter(
self.interner,
variances.iter().map(|v| v.lower_into(self.interner)),
ty::Adt(def, substs) => {
let DtorckConstraint { dtorck_types, outlives, overflows } =
- tcx.at(span).adt_dtorck_constraint(def.did)?;
+ tcx.at(span).adt_dtorck_constraint(def.did())?;
// FIXME: we can try to recursively `dtorck_constraint_on_ty`
// there, but that needs some way to handle cycles.
constraints.dtorck_types.extend(dtorck_types.iter().map(|t| t.subst(tcx, substs)));
// parameter without a `Copy` bound, then we conservatively return that it
// needs drop.
let adt_has_dtor =
- |adt_def: &ty::AdtDef| adt_def.destructor(tcx).map(|_| DtorType::Significant);
+ |adt_def: ty::AdtDef<'tcx>| adt_def.destructor(tcx).map(|_| DtorType::Significant);
let res =
drop_tys_helper(tcx, query.value, query.param_env, adt_has_dtor, false).next().is_some();
impl<'tcx, F, I> Iterator for NeedsDropTypes<'tcx, F>
where
- F: Fn(&ty::AdtDef, SubstsRef<'tcx>) -> NeedsDropResult<I>,
+ F: Fn(ty::AdtDef<'tcx>, SubstsRef<'tcx>) -> NeedsDropResult<I>,
I: Iterator<Item = Ty<'tcx>>,
{
type Item = NeedsDropResult<Ty<'tcx>>;
tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>,
param_env: rustc_middle::ty::ParamEnv<'tcx>,
- adt_has_dtor: impl Fn(&ty::AdtDef) -> Option<DtorType>,
+ adt_has_dtor: impl Fn(ty::AdtDef<'tcx>) -> Option<DtorType>,
only_significant: bool,
) -> impl Iterator<Item = NeedsDropResult<Ty<'tcx>>> {
fn with_query_cache<'tcx>(
iter.into_iter().try_fold(Vec::new(), |mut vec, subty| {
match subty.kind() {
ty::Adt(adt_id, subst) => {
- for subty in tcx.adt_drop_tys(adt_id.did)? {
+ for subty in tcx.adt_drop_tys(adt_id.did())? {
vec.push(subty.subst(tcx, subst));
}
}
})
}
- let adt_components = move |adt_def: &ty::AdtDef, substs: SubstsRef<'tcx>| {
+ let adt_components = move |adt_def: ty::AdtDef<'tcx>, substs: SubstsRef<'tcx>| {
if adt_def.is_manually_drop() {
debug!("drop_tys_helper: `{:?}` is manually drop", adt_def);
Ok(Vec::new())
fn adt_consider_insignificant_dtor<'tcx>(
tcx: TyCtxt<'tcx>,
-) -> impl Fn(&ty::AdtDef) -> Option<DtorType> + 'tcx {
- move |adt_def: &ty::AdtDef| {
- let is_marked_insig = tcx.has_attr(adt_def.did, sym::rustc_insignificant_dtor);
+) -> impl Fn(ty::AdtDef<'tcx>) -> Option<DtorType> + 'tcx {
+ move |adt_def: ty::AdtDef<'tcx>| {
+ let is_marked_insig = tcx.has_attr(adt_def.did(), sym::rustc_insignificant_dtor);
if is_marked_insig {
// In some cases like `std::collections::HashMap` where the struct is a wrapper around
// a type that is a Drop type, and the wrapped type (eg: `hashbrown::HashMap`) lies
}
}
-fn adt_drop_tys(tcx: TyCtxt<'_>, def_id: DefId) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
+fn adt_drop_tys<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ def_id: DefId,
+) -> Result<&ty::List<Ty<'tcx>>, AlwaysRequiresDrop> {
// This is for the "adt_drop_tys" query, that considers all `Drop` impls, therefore all dtors are
// significant.
let adt_has_dtor =
- |adt_def: &ty::AdtDef| adt_def.destructor(tcx).map(|_| DtorType::Significant);
+ |adt_def: ty::AdtDef<'tcx>| adt_def.destructor(tcx).map(|_| DtorType::Significant);
// `tcx.type_of(def_id)` identical to `tcx.make_adt(def, identity_substs)`
drop_tys_helper(tcx, tcx.type_of(def_id), tcx.param_env(def_id), adt_has_dtor, false)
.collect::<Result<Vec<_>, _>>()
// cleared when recursing to check A, but `shadow_seen` won't, so that we
// can catch cases of mutual recursion where A also contains B).
let mut seen: Vec<Ty<'_>> = Vec::new();
- let mut shadow_seen: Vec<&'tcx ty::AdtDef> = Vec::new();
+ let mut shadow_seen: Vec<ty::AdtDef<'tcx>> = Vec::new();
let mut representable_cache = FxHashMap::default();
let mut force_result = false;
let r = is_type_structurally_recursive(
tcx: TyCtxt<'tcx>,
sp: Span,
seen: &mut Vec<Ty<'tcx>>,
- shadow_seen: &mut Vec<&'tcx ty::AdtDef>,
+ shadow_seen: &mut Vec<ty::AdtDef<'tcx>>,
representable_cache: &mut FxHashMap<Ty<'tcx>, Representability>,
ty: Ty<'tcx>,
force_result: &mut bool,
.take(shadow_seen.len() - 1)
.any(|seen_def| seen_def == def)
{
- let adt_def_id = def.did;
+ let adt_def_id = def.did();
let raw_adt_ty = tcx.type_of(adt_def_id);
debug!("are_inner_types_recursive: checking nested type: {:?}", raw_adt_ty);
}
}
-fn same_adt<'tcx>(ty: Ty<'tcx>, def: &'tcx ty::AdtDef) -> bool {
+fn same_adt<'tcx>(ty: Ty<'tcx>, def: ty::AdtDef<'tcx>) -> bool {
match *ty.kind() {
ty::Adt(ty_def, _) => ty_def == def,
_ => false,
tcx: TyCtxt<'tcx>,
sp: Span,
seen: &mut Vec<Ty<'tcx>>,
- shadow_seen: &mut Vec<&'tcx ty::AdtDef>,
+ shadow_seen: &mut Vec<ty::AdtDef<'tcx>>,
representable_cache: &mut FxHashMap<Ty<'tcx>, Representability>,
ty: Ty<'tcx>,
force_result: &mut bool,
tcx: TyCtxt<'tcx>,
sp: Span,
seen: &mut Vec<Ty<'tcx>>,
- shadow_seen: &mut Vec<&'tcx ty::AdtDef>,
+ shadow_seen: &mut Vec<ty::AdtDef<'tcx>>,
representable_cache: &mut FxHashMap<Ty<'tcx>, Representability>,
ty: Ty<'tcx>,
force_result: &mut bool,
// For structs and enums, track all previously seen types by pushing them
// onto the 'seen' stack.
seen.push(ty);
- shadow_seen.push(def);
+ shadow_seen.push(*def);
let out = are_inner_types_recursive(
tcx,
sp,
fn sized_constraint_for_ty<'tcx>(
tcx: TyCtxt<'tcx>,
- adtdef: &ty::AdtDef,
+ adtdef: ty::AdtDef<'tcx>,
ty: Ty<'tcx>,
) -> Vec<Ty<'tcx>> {
use ty::TyKind::*;
})
.without_const()
.to_predicate(tcx);
- let predicates = tcx.predicates_of(adtdef.did).predicates;
+ let predicates = tcx.predicates_of(adtdef.did()).predicates;
if predicates.iter().any(|(p, _)| *p == sized_predicate) { vec![] } else { vec![ty] }
}
let def = tcx.adt_def(def_id);
let result = tcx.mk_type_list(
- def.variants
+ def.variants()
.iter()
.flat_map(|v| v.fields.last())
.flat_map(|f| sized_constraint_for_ty(tcx, def, tcx.type_of(f.did))),
// (a) It has no variants (i.e. an empty `enum`);
// (b) Each of its variants (a single one in the case of a `struct`) has at least
// one uninhabited field.
- def.variants.iter().all(|var| {
+ def.variants().iter().all(|var| {
var.fields.iter().any(|field| {
let ty = tcx.type_of(field.did).subst(tcx, substs);
tcx.conservative_is_privately_uninhabited(param_env.and(ty))
if let ty::Adt(adt_def, _) = qself_ty.kind() {
if adt_def.is_enum() {
let variant_def = adt_def
- .variants
+ .variants()
.iter()
- .find(|vd| tcx.hygienic_eq(assoc_ident, vd.ident(tcx), adt_def.did));
+ .find(|vd| tcx.hygienic_eq(assoc_ident, vd.ident(tcx), adt_def.did()));
if let Some(variant_def) = variant_def {
if permit_variants {
tcx.check_stability(variant_def.def_id, Some(hir_ref_id), span, None);
let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT");
if let Some(suggested_name) = find_best_match_for_name(
&adt_def
- .variants
+ .variants()
.iter()
.map(|variant| variant.name)
.collect::<Vec<Symbol>>(),
);
}
- if let Some(sp) = tcx.hir().span_if_local(adt_def.did) {
+ if let Some(sp) = tcx.hir().span_if_local(adt_def.did()) {
let sp = tcx.sess.source_map().guess_head_span(sp);
err.span_label(sp, format!("variant `{}` not found here", assoc_ident));
}
let adt_def = self_ty.map(|t| t.ty_adt_def().unwrap());
let (generics_def_id, index) = if let Some(adt_def) = adt_def {
debug_assert!(adt_def.is_enum());
- (adt_def.did, last)
+ (adt_def.did(), last)
} else if last >= 1 && segments[last - 1].args.is_some() {
// Everything but the penultimate segment should have no
// parameters at all.
let arg_is_panic_info = match *inputs[0].kind() {
ty::Ref(region, ty, mutbl) => match *ty.kind() {
ty::Adt(ref adt, _) => {
- adt.did == panic_info_did
+ adt.did() == panic_info_did
&& mutbl == hir::Mutability::Not
&& !region.is_static()
}
let span = hir.span(fn_id);
if inputs.len() == 1 {
let arg_is_alloc_layout = match inputs[0].kind() {
- ty::Adt(ref adt, _) => adt.did == alloc_layout_did,
+ ty::Adt(ref adt, _) => adt.did() == alloc_layout_did,
_ => false,
};
def.destructor(tcx); // force the destructor to be evaluated
check_representable(tcx, span, def_id);
- if def.repr.simd() {
+ if def.repr().simd() {
check_simd(tcx, span, def_id);
}
}
let len = if let ty::Array(_ty, c) = e.kind() {
- c.try_eval_usize(tcx, tcx.param_env(def.did))
+ c.try_eval_usize(tcx, tcx.param_env(def.did()))
} else {
Some(fields.len() as u64)
};
}
}
-pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: &ty::AdtDef) {
- let repr = def.repr;
+pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) {
+ let repr = def.repr();
if repr.packed() {
- for attr in tcx.get_attrs(def.did).iter() {
+ for attr in tcx.get_attrs(def.did()).iter() {
for r in attr::find_repr_attrs(&tcx.sess, attr) {
if let attr::ReprPacked(pack) = r
&& let Some(repr_pack) = repr.pack
)
.emit();
} else {
- if let Some(def_spans) = check_packed_inner(tcx, def.did, &mut vec![]) {
+ if let Some(def_spans) = check_packed_inner(tcx, def.did(), &mut vec![]) {
let mut err = struct_span_err!(
tcx.sess,
sp,
&if first {
format!(
"`{}` contains a field of type `{}`",
- tcx.type_of(def.did),
+ tcx.type_of(def.did()),
ident
)
} else {
) -> Option<Vec<(DefId, Span)>> {
if let ty::Adt(def, substs) = tcx.type_of(def_id).kind() {
if def.is_struct() || def.is_union() {
- if def.repr.align.is_some() {
- return Some(vec![(def.did, DUMMY_SP)]);
+ if def.repr().align.is_some() {
+ return Some(vec![(def.did(), DUMMY_SP)]);
}
stack.push(def_id);
for field in &def.non_enum_variant().fields {
if let ty::Adt(def, _) = field.ty(tcx, substs).kind() {
- if !stack.contains(&def.did) {
- if let Some(mut defs) = check_packed_inner(tcx, def.did, stack) {
- defs.push((def.did, field.ident(tcx).span));
+ if !stack.contains(&def.did()) {
+ if let Some(mut defs) = check_packed_inner(tcx, def.did(), stack) {
+ defs.push((def.did(), field.ident(tcx).span));
return Some(defs);
}
}
None
}
-pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: &'tcx ty::AdtDef) {
- if !adt.repr.transparent() {
+pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtDef<'tcx>) {
+ if !adt.repr().transparent() {
return;
}
let sp = tcx.sess.source_map().guess_head_span(sp);
.emit();
}
- if adt.variants.len() != 1 {
- bad_variant_count(tcx, adt, sp, adt.did);
- if adt.variants.is_empty() {
+ if adt.variants().len() != 1 {
+ bad_variant_count(tcx, adt, sp, adt.did());
+ if adt.variants().is_empty() {
// Don't bother checking the fields. No variants (and thus no fields) exist.
return;
}
}
}
- let repr_type_ty = def.repr.discr_type().to_ty(tcx);
+ let repr_type_ty = def.repr().discr_type().to_ty(tcx);
if repr_type_ty == tcx.types.i128 || repr_type_ty == tcx.types.u128 {
if !tcx.features().repr128 {
feature_err(
}
}
- if tcx.adt_def(def_id).repr.int.is_none() && tcx.features().arbitrary_enum_discriminant {
+ if tcx.adt_def(def_id).repr().int.is_none() && tcx.features().arbitrary_enum_discriminant {
let is_unit = |var: &hir::Variant<'_>| matches!(var.data, hir::VariantData::Unit(..));
let has_disr = |var: &hir::Variant<'_>| var.disr_expr.is_some();
for ((_, discr), v) in iter::zip(def.discriminants(tcx), vs) {
// Check for duplicate discriminant values
if let Some(i) = disr_vals.iter().position(|&x| x.val == discr.val) {
- let variant_did = def.variants[VariantIdx::new(i)].def_id;
+ let variant_did = def.variant(VariantIdx::new(i)).def_id;
let variant_i_hir_id = tcx.hir().local_def_id_to_hir_id(variant_did.expect_local());
let variant_i = tcx.hir().expect_variant(variant_i_hir_id);
let i_span = match variant_i.disr_expr {
{
if e.hir_id == id {
if let Some(span) = expr.span.find_ancestor_inside(block_span) {
- let return_suggestions =
- if self.tcx.is_diagnostic_item(sym::Result, expected_adt.did) {
- vec!["Ok(())".to_string()]
- } else if self.tcx.is_diagnostic_item(sym::Option, expected_adt.did)
- {
- vec!["None".to_string(), "Some(())".to_string()]
- } else {
- return;
- };
+ let return_suggestions = if self
+ .tcx
+ .is_diagnostic_item(sym::Result, expected_adt.did())
+ {
+ vec!["Ok(())".to_string()]
+ } else if self.tcx.is_diagnostic_item(sym::Option, expected_adt.did()) {
+ vec!["None".to_string(), "Some(())".to_string()]
+ } else {
+ return;
+ };
if let Some(indent) =
self.tcx.sess.source_map().indentation_before(span.shrink_to_lo())
{
}
let compatible_variants: Vec<String> = expected_adt
- .variants
+ .variants()
.iter()
.filter(|variant| variant.fields.len() == 1)
.filter_map(|variant| {
err.multipart_suggestions(
&format!(
"try wrapping the expression in a variant of `{}`",
- self.tcx.def_path_str(expected_adt.did)
+ self.tcx.def_path_str(expected_adt.did())
),
compatible_variants.into_iter().map(|variant| {
vec![
tcx,
drop_impl_did.expect_local(),
dtor_self_type,
- adt_def.did,
+ adt_def.did(),
)?;
ensure_drop_predicates_are_implied_by_item_defn(
tcx,
dtor_predicates,
- adt_def.did.expect_local(),
+ adt_def.did().expect_local(),
self_to_impl_substs,
)
}
// Prohibit struct expressions when non-exhaustive flag is set.
let adt = adt_ty.ty_adt_def().expect("`check_struct_path` returned non-ADT type");
- if !adt.did.is_local() && variant.is_field_list_non_exhaustive() {
+ if !adt.did().is_local() && variant.is_field_list_non_exhaustive() {
self.tcx
.sess
.emit_err(StructExprNonExhaustive { span: expr.span, what: adt.variant_descr() });
ty::Adt(base_def, substs) if !base_def.is_enum() => {
debug!("struct named {:?}", base_t);
let (ident, def_scope) =
- self.tcx.adjust_ident_and_get_scope(field, base_def.did, self.body_id);
+ self.tcx.adjust_ident_and_get_scope(field, base_def.did(), self.body_id);
let fields = &base_def.non_enum_variant().fields;
if let Some(index) = fields
.iter()
self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None);
return field_ty;
}
- private_candidate = Some((adjustments, base_def.did, field_ty));
+ private_candidate = Some((adjustments, base_def.did(), field_ty));
}
}
ty::Tuple(tys) => {
if let ty::RawPtr(ty_and_mut) = expr_t.kind() {
if let ty::Adt(adt_def, _) = ty_and_mut.ty.kind() {
- if adt_def.variants.len() == 1
+ if adt_def.variants().len() == 1
&& adt_def
- .variants
+ .variants()
.iter()
.next()
.unwrap()
fn suggest_fields_on_recordish(
&self,
err: &mut Diagnostic,
- def: &'tcx ty::AdtDef,
+ def: ty::AdtDef<'tcx>,
field: Ident,
access_span: Span,
) {
if let Some(self_ty) = self_ty =>
{
let adt_def = self_ty.ty_adt_def().unwrap();
- user_self_ty = Some(UserSelfTy { impl_def_id: adt_def.did, self_ty });
+ user_self_ty = Some(UserSelfTy { impl_def_id: adt_def.did(), self_ty });
is_alias_variant_ctor = true;
}
Res::Def(DefKind::AssocFn | DefKind::AssocConst, def_id) => {
return None;
}
Res::Def(DefKind::Variant, _) => match ty.kind() {
- ty::Adt(adt, substs) => Some((adt.variant_of_res(def), adt.did, substs)),
+ ty::Adt(adt, substs) => Some((adt.variant_of_res(def), adt.did(), substs)),
_ => bug!("unexpected type: {:?}", ty),
},
Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
| Res::SelfTy { .. } => match ty.kind() {
ty::Adt(adt, substs) if !adt.is_enum() => {
- Some((adt.non_enum_variant(), adt.did, substs))
+ Some((adt.non_enum_variant(), adt.did(), substs))
}
_ => None,
},
let pin_box_found = self.tcx.mk_lang_item(box_found, LangItem::Pin).unwrap();
let pin_found = self.tcx.mk_lang_item(found, LangItem::Pin).unwrap();
match expected.kind() {
- ty::Adt(def, _) if Some(def.did) == pin_did => {
+ ty::Adt(def, _) if Some(def.did()) == pin_did => {
if self.can_coerce(pin_box_found, expected) {
debug!("can coerce {:?} to {:?}, suggesting Box::pin", pin_box_found, expected);
match found.kind() {
let descr_pre = &format!("{}boxed ", data.descr_pre);
check_must_not_suspend_ty(fcx, boxed_ty, hir_id, SuspendCheckData { descr_pre, ..data })
}
- ty::Adt(def, _) => check_must_not_suspend_def(fcx.tcx, def.did, hir_id, data),
+ ty::Adt(def, _) => check_must_not_suspend_def(fcx.tcx, def.did(), hir_id, data),
// FIXME: support adding the attribute to TAITs
ty::Opaque(def, _) => {
let mut has_emitted = false;
if let ty::Adt(adt_def, _) = self_ty.kind() {
if adt_def.is_enum() {
let variant_def = adt_def
- .variants
+ .variants()
.iter()
- .find(|vd| tcx.hygienic_eq(method_name, vd.ident(tcx), adt_def.did));
+ .find(|vd| tcx.hygienic_eq(method_name, vd.ident(tcx), adt_def.did()));
if let Some(variant_def) = variant_def {
// Braced variants generate unusable names in value namespace (reserved for
// possible future use), so variants resolved as associated items may refer to
// for a "<" in `self_ty_name`.
if !self_ty_name.contains('<') {
if let Adt(def, _) = self_ty.kind() {
- let generics = self.tcx.generics_of(def.did);
+ let generics = self.tcx.generics_of(def.did());
if !generics.params.is_empty() {
let counts = generics.own_counts();
self_ty_name += &format!(
self.assemble_inherent_impl_candidates_for_type(p.def_id());
}
ty::Adt(def, _) => {
- self.assemble_inherent_impl_candidates_for_type(def.did);
+ self.assemble_inherent_impl_candidates_for_type(def.did());
}
ty::Foreign(did) => {
self.assemble_inherent_impl_candidates_for_type(did);
let candidate_found = autoderef.any(|(ty, _)| {
if let ty::Adt(adt_deref, _) = ty.kind() {
self.tcx
- .inherent_impls(adt_deref.did)
+ .inherent_impls(adt_deref.did())
.iter()
.filter_map(|def_id| {
self.associated_value(*def_id, item_name)
}
if let Some(def) = actual.ty_adt_def() {
- if let Some(full_sp) = tcx.hir().span_if_local(def.did) {
+ if let Some(full_sp) = tcx.hir().span_if_local(def.did()) {
let def_sp = tcx.sess.source_map().guess_head_span(full_sp);
err.span_label(
def_sp,
// Pick out the list of unimplemented traits on the receiver.
// This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
let mut unimplemented_traits = FxHashMap::default();
+ let mut unimplemented_traits_only = true;
for (predicate, _parent_pred, cause) in &unsatisfied_predicates {
if let (ty::PredicateKind::Trait(p), Some(cause)) =
(predicate.kind().skip_binder(), cause.as_ref())
}
}
+ // Make sure that, if any traits other than the found ones were involved,
+ // we don't don't report an unimplemented trait.
+ // We don't want to say that `iter::Cloned` is not an interator, just
+ // because of some non-Clone item being iterated over.
+ for (predicate, _parent_pred, _cause) in &unsatisfied_predicates {
+ match predicate.kind().skip_binder() {
+ ty::PredicateKind::Trait(p)
+ if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {}
+ _ => {
+ unimplemented_traits_only = false;
+ break;
+ }
+ }
+ }
+
let mut collect_type_param_suggestions =
|self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| {
// We don't care about regions here, so it's fine to skip the binder here.
.get(self.tcx.hir().local_def_id_to_hir_id(did)),
)
}
- ty::Adt(def, _) => def.did.as_local().map(|def_id| {
+ ty::Adt(def, _) => def.did().as_local().map(|def_id| {
self.tcx
.hir()
.get(self.tcx.hir().local_def_id_to_hir_id(def_id))
);
match &self_ty.kind() {
// Point at the type that couldn't satisfy the bound.
- ty::Adt(def, _) => bound_spans.push((def_span(def.did), msg)),
+ ty::Adt(def, _) => bound_spans.push((def_span(def.did()), msg)),
// Point at the trait object that couldn't satisfy the bound.
ty::Dynamic(preds, _) => {
for pred in preds.iter() {
.join("\n");
let actual_prefix = actual.prefix_string(self.tcx);
info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
- let (primary_message, label) = if unimplemented_traits.len() == 1 {
+ let (primary_message, label) = if unimplemented_traits.len() == 1
+ && unimplemented_traits_only
+ {
unimplemented_traits
.into_iter()
.next()
ty.is_str()
|| matches!(
ty.kind(),
- ty::Adt(adt, _) if self.tcx.is_diagnostic_item(sym::String, adt.did)
+ ty::Adt(adt, _) if self.tcx.is_diagnostic_item(sym::String, adt.did())
)
}
- ty::Adt(adt, _) => self.tcx.is_diagnostic_item(sym::String, adt.did),
+ ty::Adt(adt, _) => self.tcx.is_diagnostic_item(sym::String, adt.did()),
_ => false,
};
if is_string_or_ref_str && item_name.name == sym::iter {
if let ty::Adt(adt, _) = rcvr_ty.kind() {
let mut inherent_impls_candidate = self
.tcx
- .inherent_impls(adt.did)
+ .inherent_impls(adt.did())
.iter()
.copied()
.filter(|def_id| {
if unsatisfied_predicates.is_empty() && actual.is_enum() {
let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
if let Some(suggestion) = lev_distance::find_best_match_for_name(
- &adt_def.variants.iter().map(|s| s.name).collect::<Vec<_>>(),
+ &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
item_name.name,
None,
) {
let all_local_types_needing_impls =
errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
ty::PredicateKind::Trait(pred) => match pred.self_ty().kind() {
- ty::Adt(def, _) => def.did.is_local(),
+ ty::Adt(def, _) => def.did().is_local(),
_ => false,
},
_ => false,
let def_ids = preds
.iter()
.filter_map(|pred| match pred.self_ty().kind() {
- ty::Adt(def, _) => Some(def.did),
+ ty::Adt(def, _) => Some(def.did()),
_ => None,
})
.collect::<FxHashSet<_>>();
match pred.self_ty().kind() {
ty::Adt(def, _) => {
spans.push_span_label(
- sm.guess_head_span(self.tcx.def_span(def.did)),
+ sm.guess_head_span(self.tcx.def_span(def.did())),
format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
);
}
for (pred, _, _) in unsatisfied_predicates {
let ty::PredicateKind::Trait(trait_pred) = pred.kind().skip_binder() else { continue };
let adt = match trait_pred.self_ty().ty_adt_def() {
- Some(adt) if adt.did.is_local() => adt,
+ Some(adt) if adt.did().is_local() => adt,
_ => continue,
};
if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
};
if can_derive {
let self_name = trait_pred.self_ty().to_string();
- let self_span = self.tcx.def_span(adt.did);
+ let self_span = self.tcx.def_span(adt.did());
if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
{
/// Print out the type for use in value namespace.
fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
match ty.kind() {
- ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did, substs)),
+ ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did(), substs)),
_ => self.ty_to_string(ty),
}
}
) -> bool {
fn is_local(ty: Ty<'_>) -> bool {
match ty.kind() {
- ty::Adt(def, _) => def.did.is_local(),
+ ty::Adt(def, _) => def.did().is_local(),
ty::Foreign(did) => did.is_local(),
ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
ty::Param(_) => true,
}
/// Emit an error when encountering two or more variants in a transparent enum.
-fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: &'tcx ty::AdtDef, sp: Span, did: DefId) {
+fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>, sp: Span, did: DefId) {
let variant_spans: Vec<_> = adt
- .variants
+ .variants()
.iter()
.map(|variant| tcx.hir().span_if_local(variant.def_id).unwrap())
.collect();
- let msg = format!("needs exactly one variant, but has {}", adt.variants.len(),);
+ let msg = format!("needs exactly one variant, but has {}", adt.variants().len(),);
let mut err = struct_span_err!(tcx.sess, sp, E0731, "transparent enum {}", msg);
err.span_label(sp, &msg);
if let [start @ .., end] = &*variant_spans {
/// enum.
fn bad_non_zero_sized_fields<'tcx>(
tcx: TyCtxt<'tcx>,
- adt: &'tcx ty::AdtDef,
+ adt: ty::AdtDef<'tcx>,
field_count: usize,
field_spans: impl Iterator<Item = Span>,
sp: Span,
let string_type = self.tcx.get_diagnostic_item(sym::String);
let is_std_string = |ty: Ty<'tcx>| match ty.ty_adt_def() {
- Some(ty_def) => Some(ty_def.did) == string_type,
+ Some(ty_def) => Some(ty_def.did()) == string_type,
None => false,
};
use rustc_hir::{HirId, Pat, PatKind};
use rustc_infer::infer;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_middle::middle::stability::EvalResult;
use rustc_middle::ty::{self, Adt, BindingMode, Ty, TypeFoldable};
use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
use rustc_span::hygiene::DesugaringKind;
_ => {
let (type_def_id, item_def_id) = match pat_ty.kind() {
Adt(def, _) => match res {
- Res::Def(DefKind::Const, def_id) => (Some(def.did), Some(def_id)),
+ Res::Def(DefKind::Const, def_id) => (Some(def.did()), Some(def_id)),
_ => (None, None),
},
_ => (None, None),
};
// Require `..` if struct has non_exhaustive attribute.
- let non_exhaustive = variant.is_field_list_non_exhaustive() && !adt.did.is_local();
+ let non_exhaustive = variant.is_field_list_non_exhaustive() && !adt.did().is_local();
if non_exhaustive && !has_rest_pat {
self.error_foreign_non_exhaustive_spat(pat, adt.variant_descr(), fields.is_empty());
}
.copied()
.filter(|(field, _)| {
field.vis.is_accessible_from(tcx.parent_module(pat.hir_id).to_def_id(), tcx)
+ && !matches!(
+ tcx.eval_stability(field.did, None, DUMMY_SP, None),
+ EvalResult::Deny { .. }
+ )
+ // We only want to report the error if it is hidden and not local
+ && !(tcx.is_doc_hidden(field.did) && !field.did.is_local())
})
.collect();
.find_map(|(ty, _)| {
match ty.kind() {
ty::Adt(adt_def, _)
- if self.tcx.is_diagnostic_item(sym::Option, adt_def.did)
- || self.tcx.is_diagnostic_item(sym::Result, adt_def.did) =>
+ if self.tcx.is_diagnostic_item(sym::Option, adt_def.did())
+ || self.tcx.is_diagnostic_item(sym::Result, adt_def.did()) =>
{
// Slicing won't work here, but `.as_deref()` might (issue #91328).
err.span_suggestion(
use crate::check::method::MethodCallee;
use crate::check::{has_expected_num_generic_args, FnCtxt, PlaceOp};
use rustc_ast as ast;
+use rustc_data_structures::intern::Interned;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
) = index_expr.kind
{
match adjusted_ty.kind() {
- ty::Adt(ty::AdtDef { did, .. }, _)
+ ty::Adt(ty::AdtDef(Interned(ty::AdtDefData { did, .. }, _)), _)
if self.tcx.is_diagnostic_item(sym::Vec, *did) =>
{
return self.negative_index(adjusted_ty, index_expr.span, base_expr);
ty::Adt(def, substs) => {
// Multi-varaint enums are captured in entirety,
// which would've been handled in the case of single empty slice in `captured_by_move_projs`.
- assert_eq!(def.variants.len(), 1);
+ assert_eq!(def.variants().len(), 1);
// Only Field projections can be applied to a non-box Adt.
assert!(
ProjectionKind::Field(..)
))
);
- def.variants.get(VariantIdx::new(0)).unwrap().fields.iter().enumerate().any(
+ def.variants().get(VariantIdx::new(0)).unwrap().fields.iter().enumerate().any(
|(i, field)| {
let paths_using_field = captured_by_move_projs
.iter()
// Return true for fields of packed structs, unless those fields have alignment 1.
match p.kind {
ProjectionKind::Field(..) => match ty.kind() {
- ty::Adt(def, _) if def.repr.packed() => {
+ ty::Adt(def, _) if def.repr().packed() => {
// We erase regions here because they cannot be hashed
match tcx.layout_of(param_env.and(tcx.erase_regions(p.ty))) {
Ok(layout) if layout.align.abi.bytes() == 1 => {
{
for_item(tcx, item).with_fcx(|fcx| {
let variants = lookup_fields(fcx);
- let packed = tcx.adt_def(item.def_id).repr.packed();
+ let packed = tcx.adt_def(item.def_id).repr().packed();
for variant in &variants {
// For DST, or when drop needs to copy things around, all
if def_a.is_struct() && def_b.is_struct() =>
{
if def_a != def_b {
- let source_path = tcx.def_path_str(def_a.did);
- let target_path = tcx.def_path_str(def_b.did);
+ let source_path = tcx.def_path_str(def_a.did());
+ let target_path = tcx.def_path_str(def_b.did());
create_err(&format!(
"the trait `DispatchFromDyn` may only be implemented \
return;
}
- if def_a.repr.c() || def_a.repr.packed() {
+ if def_a.repr().c() || def_a.repr().packed() {
create_err(
"structs implementing `DispatchFromDyn` may not have \
`#[repr(packed)]` or `#[repr(C)]`",
if def_a.is_struct() && def_b.is_struct() =>
{
if def_a != def_b {
- let source_path = tcx.def_path_str(def_a.did);
- let target_path = tcx.def_path_str(def_b.did);
+ let source_path = tcx.def_path_str(def_a.did());
+ let target_path = tcx.def_path_str(def_b.did());
struct_span_err!(
tcx.sess,
span,
let lang_items = self.tcx.lang_items();
match *self_ty.kind() {
ty::Adt(def, _) => {
- self.check_def_id(item, def.did);
+ self.check_def_id(item, def.did());
}
ty::Foreign(did) => {
self.check_def_id(item, did);
if tcx.trait_is_auto(trait_def_id) && !trait_def_id.is_local() {
let self_ty = trait_ref.self_ty();
let opt_self_def_id = match *self_ty.kind() {
- ty::Adt(self_def, _) => Some(self_def.did),
+ ty::Adt(self_def, _) => Some(self_def.did()),
ty::Foreign(did) => Some(did),
_ => None,
};
// That way if we had `Vec<MyType>`, we will properly attribute the
// problem to `Vec<T>` and avoid confusing the user if they were to see
// `MyType` in the error.
- ty::Adt(def, _) => tcx.mk_adt(def, ty::List::empty()),
+ ty::Adt(def, _) => tcx.mk_adt(*def, ty::List::empty()),
_ => ty,
};
let this = "this".to_string();
assert_eq!(trait_ref.substs.len(), 1);
let self_ty = trait_ref.self_ty();
let (self_type_did, substs) = match self_ty.kind() {
- ty::Adt(def, substs) => (def.did, substs),
+ ty::Adt(def, substs) => (def.did(), substs),
_ => {
// FIXME: should also lint for stuff like `&i32` but
// considering that auto traits are unstable, that
// by only visiting each `DefId` once.
//
// This will be is incorrect in subtle cases, but I don't care :)
- if self.seen.insert(def.did) {
+ if self.seen.insert(def.did()) {
for ty in def.all_fields().map(|field| field.ty(tcx, substs)) {
ty.visit_with(self)?;
}
}
let self_ty_root = match self_ty.kind() {
- ty::Adt(def, _) => tcx.mk_adt(def, InternalSubsts::identity_for_item(tcx, def.did)),
+ ty::Adt(def, _) => tcx.mk_adt(*def, InternalSubsts::identity_for_item(tcx, def.did())),
_ => unimplemented!("unexpected self ty {:?}", self_ty),
};
fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId, variants: &[hir::Variant<'_>]) {
let def = tcx.adt_def(def_id);
- let repr_type = def.repr.discr_type();
+ let repr_type = def.repr().discr_type();
let initial = repr_type.initial_discriminant(tcx);
let mut prev_discr = None::<Discr<'_>>;
)
}
-fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::AdtDef {
+fn adt_def<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::AdtDef<'tcx> {
use rustc_hir::*;
let def_id = def_id.expect_local();
Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => tcx
.adt_def(tcx.hir().get_parent_item(hir_id))
- .repr
+ .repr()
.discr_type()
.to_ty(tcx),
}
AdtKind::Enum => def.is_variant_list_non_exhaustive(),
};
- def.variants.len() > 1 || (!def.did.is_local() && is_non_exhaustive)
+ def.variants().len() > 1 || (!def.did().is_local() && is_non_exhaustive)
} else {
false
}
) -> McResult<usize> {
let ty = self.typeck_results.node_type(pat_hir_id);
match ty.kind() {
- ty::Adt(adt_def, _) => Ok(adt_def.variants[variant_index].fields.len()),
+ ty::Adt(adt_def, _) => Ok(adt_def.variant(variant_index).fields.len()),
_ => {
self.tcx()
.sess
// `['b => 'a, U => T]` and thus get the requirement that `T:
// 'a` holds for `Foo`.
debug!("Adt");
- if let Some(unsubstituted_predicates) = global_inferred_outlives.get(&def.did) {
+ if let Some(unsubstituted_predicates) = global_inferred_outlives.get(&def.did()) {
for (unsubstituted_predicate, &span) in unsubstituted_predicates {
// `unsubstituted_predicate` is `U: 'b` in the
// example above. So apply the substitution to
// let _: () = substs.region_at(0);
check_explicit_predicates(
tcx,
- def.did,
+ def.did(),
substs,
required_predicates,
explicit_map,
}
ty::Adt(def, substs) => {
- self.add_constraints_from_substs(current, def.did, substs, variance);
+ self.add_constraints_from_substs(current, def.did(), substs, variance);
}
ty::Projection(ref data) => {
use core::fmt;
use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
+use core::mem::MaybeUninit;
use core::ops::Try;
use super::{count, wrap_index, RingSlices};
/// [`iter`]: super::VecDeque::iter
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Iter<'a, T: 'a> {
- pub(crate) ring: &'a [T],
+ pub(crate) ring: &'a [MaybeUninit<T>],
pub(crate) tail: usize,
pub(crate) head: usize,
}
impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail);
- f.debug_tuple("Iter").field(&front).field(&back).finish()
+ // Safety:
+ // - `self.head` and `self.tail` in a ring buffer are always valid indices.
+ // - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized.
+ unsafe {
+ f.debug_tuple("Iter")
+ .field(&MaybeUninit::slice_assume_init_ref(front))
+ .field(&MaybeUninit::slice_assume_init_ref(back))
+ .finish()
+ }
}
}
}
let tail = self.tail;
self.tail = wrap_index(self.tail.wrapping_add(1), self.ring.len());
- unsafe { Some(self.ring.get_unchecked(tail)) }
+ // Safety:
+ // - `self.tail` in a ring buffer is always a valid index.
+ // - `self.head` and `self.tail` equality is checked above.
+ unsafe { Some(self.ring.get_unchecked(tail).assume_init_ref()) }
}
#[inline]
F: FnMut(Acc, Self::Item) -> Acc,
{
let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail);
- accum = front.iter().fold(accum, &mut f);
- back.iter().fold(accum, &mut f)
+ // Safety:
+ // - `self.head` and `self.tail` in a ring buffer are always valid indices.
+ // - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized.
+ unsafe {
+ accum = MaybeUninit::slice_assume_init_ref(front).iter().fold(accum, &mut f);
+ MaybeUninit::slice_assume_init_ref(back).iter().fold(accum, &mut f)
+ }
}
fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
{
let (mut iter, final_res);
if self.tail <= self.head {
- // single slice self.ring[self.tail..self.head]
- iter = self.ring[self.tail..self.head].iter();
+ // Safety: single slice self.ring[self.tail..self.head] is initialized.
+ iter = unsafe { MaybeUninit::slice_assume_init_ref(&self.ring[self.tail..self.head]) }
+ .iter();
final_res = iter.try_fold(init, &mut f);
} else {
- // two slices: self.ring[self.tail..], self.ring[..self.head]
+ // Safety: two slices: self.ring[self.tail..], self.ring[..self.head] both are initialized.
let (front, back) = self.ring.split_at(self.tail);
- let mut back_iter = back.iter();
+
+ let mut back_iter = unsafe { MaybeUninit::slice_assume_init_ref(back).iter() };
let res = back_iter.try_fold(init, &mut f);
let len = self.ring.len();
self.tail = (self.ring.len() - back_iter.len()) & (len - 1);
- iter = front[..self.head].iter();
+ iter = unsafe { MaybeUninit::slice_assume_init_ref(&front[..self.head]).iter() };
final_res = iter.try_fold(res?, &mut f);
}
self.tail = self.head - iter.len();
// that is in bounds.
unsafe {
let idx = wrap_index(self.tail.wrapping_add(idx), self.ring.len());
- self.ring.get_unchecked(idx)
+ self.ring.get_unchecked(idx).assume_init_ref()
}
}
}
return None;
}
self.head = wrap_index(self.head.wrapping_sub(1), self.ring.len());
- unsafe { Some(self.ring.get_unchecked(self.head)) }
+ // Safety:
+ // - `self.head` in a ring buffer is always a valid index.
+ // - `self.head` and `self.tail` equality is checked above.
+ unsafe { Some(self.ring.get_unchecked(self.head).assume_init_ref()) }
}
fn rfold<Acc, F>(self, mut accum: Acc, mut f: F) -> Acc
F: FnMut(Acc, Self::Item) -> Acc,
{
let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail);
- accum = back.iter().rfold(accum, &mut f);
- front.iter().rfold(accum, &mut f)
+ // Safety:
+ // - `self.head` and `self.tail` in a ring buffer are always valid indices.
+ // - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized.
+ unsafe {
+ accum = MaybeUninit::slice_assume_init_ref(back).iter().rfold(accum, &mut f);
+ MaybeUninit::slice_assume_init_ref(front).iter().rfold(accum, &mut f)
+ }
}
fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
{
let (mut iter, final_res);
if self.tail <= self.head {
- // single slice self.ring[self.tail..self.head]
- iter = self.ring[self.tail..self.head].iter();
+ // Safety: single slice self.ring[self.tail..self.head] is initialized.
+ iter = unsafe {
+ MaybeUninit::slice_assume_init_ref(&self.ring[self.tail..self.head]).iter()
+ };
final_res = iter.try_rfold(init, &mut f);
} else {
- // two slices: self.ring[self.tail..], self.ring[..self.head]
+ // Safety: two slices: self.ring[self.tail..], self.ring[..self.head] both are initialized.
let (front, back) = self.ring.split_at(self.tail);
- let mut front_iter = front[..self.head].iter();
+
+ let mut front_iter =
+ unsafe { MaybeUninit::slice_assume_init_ref(&front[..self.head]).iter() };
let res = front_iter.try_rfold(init, &mut f);
self.head = front_iter.len();
- iter = back.iter();
+ iter = unsafe { MaybeUninit::slice_assume_init_ref(back).iter() };
final_res = iter.try_rfold(res?, &mut f);
}
self.head = self.tail + iter.len();
use core::hash::{Hash, Hasher};
use core::iter::{repeat_with, FromIterator};
use core::marker::PhantomData;
-use core::mem::{self, ManuallyDrop};
+use core::mem::{self, ManuallyDrop, MaybeUninit};
use core::ops::{Index, IndexMut, Range, RangeBounds};
use core::ptr::{self, NonNull};
use core::slice;
}
}
- /// Turn ptr into a slice
+ /// Turn ptr into a slice, since the elements of the backing buffer may be uninitialized,
+ /// we will return a slice of [`MaybeUninit<T>`].
+ ///
+ /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and
+ /// incorrect usage of this method.
+ ///
+ /// [zeroed]: mem::MaybeUninit::zeroed
#[inline]
- unsafe fn buffer_as_slice(&self) -> &[T] {
- unsafe { slice::from_raw_parts(self.ptr(), self.cap()) }
+ unsafe fn buffer_as_slice(&self) -> &[MaybeUninit<T>] {
+ unsafe { slice::from_raw_parts(self.ptr() as *mut MaybeUninit<T>, self.cap()) }
}
- /// Turn ptr into a mut slice
+ /// Turn ptr into a mut slice, since the elements of the backing buffer may be uninitialized,
+ /// we will return a slice of [`MaybeUninit<T>`].
+ ///
+ /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and
+ /// incorrect usage of this method.
+ ///
+ /// [zeroed]: mem::MaybeUninit::zeroed
#[inline]
- unsafe fn buffer_as_mut_slice(&mut self) -> &mut [T] {
- unsafe { slice::from_raw_parts_mut(self.ptr(), self.cap()) }
+ unsafe fn buffer_as_mut_slice(&mut self) -> &mut [MaybeUninit<T>] {
+ unsafe { slice::from_raw_parts_mut(self.ptr() as *mut MaybeUninit<T>, self.cap()) }
}
/// Moves an element out of the buffer
#[inline]
#[stable(feature = "deque_extras_15", since = "1.5.0")]
pub fn as_slices(&self) -> (&[T], &[T]) {
+ // Safety:
+ // - `self.head` and `self.tail` in a ring buffer are always valid indices.
+ // - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized.
unsafe {
let buf = self.buffer_as_slice();
- RingSlices::ring_slices(buf, self.head, self.tail)
+ let (front, back) = RingSlices::ring_slices(buf, self.head, self.tail);
+ (MaybeUninit::slice_assume_init_ref(front), MaybeUninit::slice_assume_init_ref(back))
}
}
#[inline]
#[stable(feature = "deque_extras_15", since = "1.5.0")]
pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) {
+ // Safety:
+ // - `self.head` and `self.tail` in a ring buffer are always valid indices.
+ // - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized.
unsafe {
let head = self.head;
let tail = self.tail;
let buf = self.buffer_as_mut_slice();
- RingSlices::ring_slices(buf, head, tail)
+ let (front, back) = RingSlices::ring_slices(buf, head, tail);
+ (MaybeUninit::slice_assume_init_mut(front), MaybeUninit::slice_assume_init_mut(back))
}
}
if self.is_contiguous() {
let tail = self.tail;
let head = self.head;
- return unsafe { RingSlices::ring_slices(self.buffer_as_mut_slice(), head, tail).0 };
+ // Safety:
+ // - `self.head` and `self.tail` in a ring buffer are always valid indices.
+ // - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized.
+ return unsafe {
+ MaybeUninit::slice_assume_init_mut(
+ RingSlices::ring_slices(self.buffer_as_mut_slice(), head, tail).0,
+ )
+ };
}
let buf = self.buf.ptr();
let tail = self.tail;
let head = self.head;
- unsafe { RingSlices::ring_slices(self.buffer_as_mut_slice(), head, tail).0 }
+ // Safety:
+ // - `self.head` and `self.tail` in a ring buffer are always valid indices.
+ // - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized.
+ unsafe {
+ MaybeUninit::slice_assume_init_mut(
+ RingSlices::ring_slices(self.buffer_as_mut_slice(), head, tail).0,
+ )
+ }
}
/// Rotates the double-ended queue `mid` places to the left.
}
/// An error which can be returned when parsing a char.
+///
+/// This `struct` is created when using the [`char::from_str`] method.
#[stable(feature = "char_from_str", since = "1.20.0")]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ParseCharError {
}
}
-/// The error type returned when a conversion from u32 to char fails.
+/// The error type returned when a conversion from [`prim@u32`] to [`prim@char`] fails.
+///
+/// This `struct` is created by the [`char::try_from<u32>`](char#impl-TryFrom<u32>) method.
+/// See its documentation for more.
#[stable(feature = "try_from", since = "1.34.0")]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct CharTryFromError(());
/// Which kind of future are we turning this into?
#[unstable(feature = "into_future", issue = "67644")]
- type Future: Future<Output = Self::Output>;
+ type IntoFuture: Future<Output = Self::Output>;
/// Creates a future from a value.
#[unstable(feature = "into_future", issue = "67644")]
#[lang = "into_future"]
- fn into_future(self) -> Self::Future;
+ fn into_future(self) -> Self::IntoFuture;
}
#[unstable(feature = "into_future", issue = "67644")]
impl<F: Future> IntoFuture for F {
type Output = F::Output;
- type Future = F;
+ type IntoFuture = F;
- fn into_future(self) -> Self::Future {
+ fn into_future(self) -> Self::IntoFuture {
self
}
}
/// * '2.5E-10'
/// * '5.'
/// * '.5', or, equivalently, '0.5'
- /// * 'inf', '-inf', 'NaN'
+ /// * 'inf', '-inf', '+infinity', 'NaN'
+ ///
+ /// Note that alphabetical characters are not case-sensitive.
///
/// Leading and trailing whitespace represent an error.
///
/// # Grammar
///
- /// All strings that adhere to the following [EBNF] grammar
- /// will result in an [`Ok`] being returned:
+ /// All strings that adhere to the following [EBNF] grammar when
+ /// lowercased will result in an [`Ok`] being returned:
///
/// ```txt
- /// Float ::= Sign? ( 'inf' | 'NaN' | Number )
+ /// Float ::= Sign? ( 'inf' | 'infinity' | 'nan' | Number )
/// Number ::= ( Digit+ |
+ /// '.' Digit* |
/// Digit+ '.' Digit* |
/// Digit* '.' Digit+ ) Exp?
- /// Exp ::= [eE] Sign? Digit+
+ /// Exp ::= 'e' Sign? Digit+
/// Sign ::= [+-]
/// Digit ::= [0-9]
/// ```
}
fn stage_dir_exists(stage_path: &str) -> bool {
- match fs::create_dir(&stage_path[..]) {
+ match fs::create_dir(&stage_path) {
Ok(_) => true,
- Err(_) => Path::new(&stage_path[..]).exists(),
+ Err(_) => Path::new(&stage_path).exists(),
}
}
return;
}
- if try_link_toolchain(&stage_path[..]) {
+ if try_link_toolchain(&stage_path) {
println!(
"Added `stage1` rustup toolchain; try `cargo +stage1 build` on a separate rust project to run a newly-built toolchain"
);
println!(
"To manually link stage 1 build to `stage1` toolchain, run:\n
`rustup toolchain link stage1 {}`",
- &stage_path[..]
+ &stage_path
);
}
}
fn try_link_toolchain(stage_path: &str) -> bool {
Command::new("rustup")
.stdout(std::process::Stdio::null())
- .args(&["toolchain", "link", "stage1", &stage_path[..]])
+ .args(&["toolchain", "link", "stage1", &stage_path])
.output()
.map_or(false, |output| output.status.success())
}
# https://github.com/puppeteer/puppeteer/issues/375
#
# We also specify the version in case we need to update it to go around cache limitations.
-RUN npm install -g browser-ui-test@0.8.0 --unsafe-perm=true
+RUN npm install -g browser-ui-test@0.8.1 --unsafe-perm=true
ENV RUST_CONFIGURE_ARGS \
--build=x86_64-unknown-linux-gnu \
clean::Enum {
generics: clean_ty_generics(cx, cx.tcx.generics_of(did), predicates),
variants_stripped: false,
- variants: cx.tcx.adt_def(did).variants.iter().map(|v| v.clean(cx)).collect(),
+ variants: cx.tcx.adt_def(did).variants().iter().map(|v| v.clean(cx)).collect(),
}
}
/// Inline an `impl`, inherent or of a trait. The `did` must be for an `impl`.
crate fn build_impl(
cx: &mut DocContext<'_>,
- parent_module: impl Into<Option<DefId>>,
+ parent_module: Option<DefId>,
did: DefId,
attrs: Option<Attrs<'_>>,
ret: &mut Vec<clean::Item>,
record_extern_trait(cx, did);
}
- let (merged_attrs, cfg) = merge_attrs(cx, parent_module.into(), load_attrs(cx, did), attrs);
+ let (merged_attrs, cfg) = merge_attrs(cx, parent_module, load_attrs(cx, did), attrs);
trace!("merged_attrs={:?}", merged_attrs);
trace!(
})
}
ty::Adt(def, substs) => {
- let did = def.did;
+ let did = def.did();
let kind = match def.adt_kind() {
AdtKind::Struct => ItemType::Struct,
AdtKind::Union => ItemType::Union,
// Render the list of items inside one of the sections "Trait Implementations",
// "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages).
-fn render_impls(cx: &Context<'_>, w: &mut Buffer, impls: &[&&Impl], containing_item: &clean::Item) {
+fn render_impls(
+ cx: &Context<'_>,
+ w: &mut Buffer,
+ impls: &[&&Impl],
+ containing_item: &clean::Item,
+ toggle_open_by_default: bool,
+) {
let tcx = cx.tcx();
let mut rendered_impls = impls
.iter()
is_on_foreign_type: false,
show_default_items: true,
show_non_assoc_items: true,
- toggle_open_by_default: true,
+ toggle_open_by_default,
},
);
buffer.into_inner()
concrete.into_iter().partition(|t| t.inner_impl().kind.is_blanket());
let mut impls = Buffer::empty_from(w);
- render_impls(cx, &mut impls, &concrete, containing_item);
+ render_impls(cx, &mut impls, &concrete, containing_item, true);
let impls = impls.into_inner();
if !impls.is_empty() {
write!(
</h2>\
<div id=\"synthetic-implementations-list\">",
);
- render_impls(cx, w, &synthetic, containing_item);
+ render_impls(cx, w, &synthetic, containing_item, false);
w.write_str("</div>");
}
</h2>\
<div id=\"blanket-implementations-list\">",
);
- render_impls(cx, w, &blanket_impl, containing_item);
+ render_impls(cx, w, &blanket_impl, containing_item, false);
w.write_str("</div>");
}
}
};
for (index, layout) in variants.iter_enumerated() {
- let name = adt.variants[index].name;
+ let name = adt.variant(index).name;
write!(w, "<li><code>{name}</code>: ", name = name);
write_size_of_layout(w, *layout, tag_size);
writeln!(w, "</li>");
Lifetime { outlives } => GenericParamDefKind::Lifetime {
outlives: outlives.into_iter().map(|lt| lt.0.to_string()).collect(),
},
- Type { did: _, bounds, default, synthetic: _ } => GenericParamDefKind::Type {
+ Type { did: _, bounds, default, synthetic } => GenericParamDefKind::Type {
bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
default: default.map(|x| (*x).into_tcx(tcx)),
+ synthetic,
},
Const { did: _, ty, default } => {
GenericParamDefKind::Const { ty: (*ty).into_tcx(tcx), default: default.map(|x| *x) }
//!
//! [RFC 1946]: https://github.com/rust-lang/rfcs/blob/master/text/1946-intra-rustdoc-links.md
-use rustc_data_structures::{fx::FxHashMap, stable_set::FxHashSet};
+use rustc_data_structures::{fx::FxHashMap, intern::Interned, stable_set::FxHashSet};
use rustc_errors::{Applicability, Diagnostic};
use rustc_hir::def::{
DefKind,
Err(ResolutionFailure::NotResolved {
item_id,
module_id,
- partial_res: Some(Res::Def(DefKind::Enum, def.did)),
+ partial_res: Some(Res::Def(DefKind::Enum, def.did())),
unresolved: variant_field_name.to_string().into(),
}
.into())
ty::FnDef(..) => panic!("type alias to a function definition"),
ty::FnPtr(_) => Res::Primitive(Fn),
ty::Never => Res::Primitive(Never),
- ty::Adt(&ty::AdtDef { did, .. }, _) | ty::Foreign(did) => {
+ ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did, .. }, _)), _) | ty::Foreign(did) => {
Res::Def(self.cx.tcx.def_kind(did), did)
}
ty::Projection(_)
if ns == TypeNS && def_kind == DefKind::Enum {
match tcx.type_of(did).kind() {
ty::Adt(adt_def, _) => {
- for variant in &adt_def.variants {
+ for variant in adt_def.variants() {
if variant.name == item_name {
return Some((
root_res,
let saw_impl = impl_type == ty
|| match (impl_type.kind(), ty.kind()) {
(ty::Adt(impl_def, _), ty::Adt(ty_def, _)) => {
- debug!("impl def_id: {:?}, ty def_id: {:?}", impl_def.did, ty_def.did);
- impl_def.did == ty_def.did
+ debug!("impl def_id: {:?}, ty def_id: {:?}", impl_def.did(), ty_def.did());
+ impl_def.did() == ty_def.did()
}
_ => false,
};
use serde::{Deserialize, Serialize};
/// rustdoc format-version.
-pub const FORMAT_VERSION: u32 = 12;
+pub const FORMAT_VERSION: u32 = 13;
/// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
/// about the language items in the local crate, as well as info about external items to allow
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum GenericParamDefKind {
- Lifetime { outlives: Vec<String> },
- Type { bounds: Vec<GenericBound>, default: Option<Type> },
- Const { ty: Type, default: Option<String> },
+ Lifetime {
+ outlives: Vec<String>,
+ },
+ Type {
+ bounds: Vec<GenericBound>,
+ default: Option<Type>,
+ /// This is normally `false`, which means that this generic parameter is
+ /// declared in the Rust source text.
+ ///
+ /// If it is `true`, this generic parameter has been introduced by the
+ /// compiler behind the scenes.
+ ///
+ /// # Example
+ ///
+ /// Consider
+ ///
+ /// ```ignore (pseudo-rust)
+ /// pub fn f(_: impl Trait) {}
+ /// ```
+ ///
+ /// The compiler will transform this behind the scenes to
+ ///
+ /// ```ignore (pseudo-rust)
+ /// pub fn f<impl Trait: Trait>(_: impl Trait) {}
+ /// ```
+ ///
+ /// In this example, the generic parameter named `impl Trait` (and which
+ /// is bound by `Trait`) is synthetic, because it was not originally in
+ /// the Rust source text.
+ synthetic: bool,
+ },
+ Const {
+ ty: Type,
+ default: Option<String>,
+ },
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
goto: file://|DOC_PATH|/test_docs/struct.Foo.html
// We first check that everything is visible.
assert-text: ("#toggle-all-docs", "[−]")
-assert-attribute: ("details.rustdoc-toggle", {"open": ""}, ALL)
+assert-attribute: ("#implementations-list details.rustdoc-toggle", {"open": ""}, ALL)
+assert-attribute: ("#trait-implementations-list details.rustdoc-toggle", {"open": ""}, ALL)
+assert-attribute-false: (
+ "#blanket-implementations-list > details.rustdoc-toggle",
+ {"open": ""},
+ ALL,
+)
+
// We collapse them all.
click: "#toggle-all-docs"
wait-for: 50
--- /dev/null
+// ignore-tidy-linelength
+
+#![feature(no_core)]
+#![no_core]
+
+// @set wham_id = generics.json "$.index[*][?(@.name=='Wham')].id"
+pub trait Wham {}
+
+// @is - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.where_predicates" []
+// @count - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[*]" 1
+// @is - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].name" '"T"'
+// @has - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].kind.type.synthetic" false
+// @has - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.inner.id" $wham_id
+// @is - "$.index[*][?(@.name=='one_generic_param_fn')].inner.decl.inputs" '[["w", {"inner": "T", "kind": "generic"}]]'
+pub fn one_generic_param_fn<T: Wham>(w: T) {}
+
+// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.where_predicates" []
+// @count - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[*]" 1
+// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].name" '"impl Wham"'
+// @has - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].kind.type.synthetic" true
+// @has - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.inner.id" $wham_id
+// @count - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[*]" 1
+// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][0]" '"w"'
+// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][1].kind" '"impl_trait"'
+// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.inner.id" $wham_id
+pub fn one_synthetic_generic_param_fn(w: impl Wham) {}
impl IntoFuture for AwaitMe {
type Output = i32;
- type Future = Pin<Box<dyn Future<Output = i32>>>;
+ type IntoFuture = Pin<Box<dyn Future<Output = i32>>>;
- fn into_future(self) -> Self::Future {
+ fn into_future(self) -> Self::IntoFuture {
Box::pin(me())
}
}
// build-pass
#![feature(allocator_api)]
+#![allow(unused_must_use)]
use std::alloc::Allocator;
fn main() {
Box::new_in((), &std::alloc::Global);
Box::new_in((), BigAllocator([0; 2]));
+ generic_function(0);
+}
+
+fn generic_function<T>(val: T) {
+ *Box::new_in(val, &std::alloc::Global);
}
-#![feature(const_ptr_offset_from)]
+#![feature(const_ptr_offset_from, const_ptr_offset)]
#![feature(core_intrinsics)]
use std::intrinsics::ptr_offset_from;
//~| 0x10 is not a valid pointer
};
+const OUT_OF_BOUNDS_1: isize = {
+ let start_ptr = &4 as *const _ as *const u8;
+ let length = 10;
+ let end_ptr = (start_ptr).wrapping_add(length);
+ // First ptr is out of bounds
+ unsafe { ptr_offset_from(end_ptr, start_ptr) } //~ERROR evaluation of constant value failed
+ //~| pointer at offset 10 is out-of-bounds
+};
+
+const OUT_OF_BOUNDS_2: isize = {
+ let start_ptr = &4 as *const _ as *const u8;
+ let length = 10;
+ let end_ptr = (start_ptr).wrapping_add(length);
+ // Second ptr is out of bounds
+ unsafe { ptr_offset_from(start_ptr, end_ptr) } //~ERROR evaluation of constant value failed
+ //~| pointer at offset 10 is out-of-bounds
+};
+
+const OUT_OF_BOUNDS_SAME: isize = {
+ let start_ptr = &4 as *const _ as *const u8;
+ let length = 10;
+ let end_ptr = (start_ptr).wrapping_add(length);
+ unsafe { ptr_offset_from(end_ptr, end_ptr) } //~ERROR evaluation of constant value failed
+ //~| pointer at offset 10 is out-of-bounds
+};
+
fn main() {}
LL | unsafe { intrinsics::ptr_offset_from(self, origin) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
- | 0x2a is not a valid pointer
+ | out-of-bounds offset_from: 0x2a is not a valid pointer
| inside `ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
::: $DIR/offset_from_ub.rs:23:14
--> $DIR/offset_from_ub.rs:36:14
|
LL | unsafe { ptr_offset_from(ptr, ptr) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ null pointer is not a valid pointer for this operation
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: null pointer is not a valid pointer
error[E0080]: evaluation of constant value failed
--> $DIR/offset_from_ub.rs:43:14
|
LL | unsafe { ptr_offset_from(ptr2, ptr1) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 0x10 is not a valid pointer
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: 0x10 is not a valid pointer
-error: aborting due to 5 previous errors
+error[E0080]: evaluation of constant value failed
+ --> $DIR/offset_from_ub.rs:52:14
+ |
+LL | unsafe { ptr_offset_from(end_ptr, start_ptr) }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc18 has size 4, so pointer at offset 10 is out-of-bounds
+
+error[E0080]: evaluation of constant value failed
+ --> $DIR/offset_from_ub.rs:61:14
+ |
+LL | unsafe { ptr_offset_from(start_ptr, end_ptr) }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc21 has size 4, so pointer at offset 10 is out-of-bounds
+
+error[E0080]: evaluation of constant value failed
+ --> $DIR/offset_from_ub.rs:69:14
+ |
+LL | unsafe { ptr_offset_from(end_ptr, end_ptr) }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc24 has size 4, so pointer at offset 10 is out-of-bounds
+
+error: aborting due to 8 previous errors
For more information about this error, try `rustc --explain E0080`.
LL | unsafe { intrinsics::offset(self, count) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
- | pointer arithmetic failed: 0x0 is not a valid pointer
+ | pointer arithmetic failed: null pointer is not a valid pointer
| inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
::: $DIR/offset_ub.rs:22:50
--- /dev/null
+pub mod foo {
+ pub mod bar {
+ pub struct A;
+ }
+}
+
+pub struct Foo {
+ a: Vec<foo::bar:A>,
+ //~^ ERROR expected
+ //~| HELP path separator
+}
+
+fn main() {}
--- /dev/null
+error: expected one of `,` or `>`, found `:`
+ --> $DIR/single-colon-path-not-const-generics.rs:8:18
+ |
+LL | a: Vec<foo::bar:A>,
+ | ^
+ | |
+ | expected one of `,` or `>`
+ | help: write a path separator here: `::`
+
+error: aborting due to previous error
+
--- /dev/null
+// run-pass
+
+#![feature(macro_metavar_expr)]
+
+fn main() {
+ macro_rules! one_nested_count_and_length {
+ ( $( [ $( $l:literal ),* ] ),* ) => {
+ [
+ // outer-most repetition
+ $(
+ // inner-most repetition
+ $(
+ ${ignore(l)} ${index()}, ${length()},
+ )*
+ ${count(l)}, ${index()}, ${length()},
+ )*
+ ${count(l)},
+ ]
+ };
+ }
+ assert_eq!(
+ one_nested_count_and_length!(["foo"], ["bar", "baz"]),
+ [
+ // # ["foo"]
+
+ // ## inner-most repetition (first iteration)
+ //
+ // `index` is 0 because this is the first inner-most iteration.
+ // `length` is 1 because there is only one inner-most repetition, "foo".
+ 0, 1,
+
+ // ## outer-most repetition (first iteration)
+ //
+ // `count` is 1 because of "foo", i,e, `$l` has only one repetition,
+ // `index` is 0 because this is the first outer-most iteration.
+ // `length` is 2 because there are 2 outer-most repetitions, ["foo"] and ["bar", "baz"]
+ 1, 0, 2,
+
+ // # ["bar", "baz"]
+
+ // ## inner-most repetition (first iteration)
+ //
+ // `index` is 0 because this is the first inner-most iteration
+ // `length` is 2 because there are repetitions, "bar" and "baz"
+ 0, 2,
+
+ // ## inner-most repetition (second iteration)
+ //
+ // `index` is 1 because this is the second inner-most iteration
+ // `length` is 2 because there are repetitions, "bar" and "baz"
+ 1, 2,
+
+ // ## outer-most repetition (second iteration)
+ //
+ // `count` is 2 because of "bar" and "baz", i,e, `$l` has two repetitions,
+ // `index` is 1 because this is the second outer-most iteration
+ // `length` is 2 because there are 2 outer-most repetitions, ["foo"] and ["bar", "baz"]
+ 2, 1, 2,
+
+ // # last count
+
+ // Because there are a total of 3 repetitions of `$l`, "foo", "bar" and "baz"
+ 3,
+ ]
+ );
+
+ // Based on the above explanation, the following macros should be straightforward
+
+ // Grouped from the outer-most to the inner-most
+ macro_rules! three_nested_count {
+ ( $( { $( [ $( ( $( $i:ident )* ) )* ] )* } )* ) => {
+ &[
+ $( $( $(
+ &[
+ ${ignore(i)} ${count(i, 0)},
+ ][..],
+ )* )* )*
+
+ $( $(
+ &[
+ ${ignore(i)} ${count(i, 0)},
+ ${ignore(i)} ${count(i, 1)},
+ ][..],
+ )* )*
+
+ $(
+ &[
+ ${ignore(i)} ${count(i, 0)},
+ ${ignore(i)} ${count(i, 1)},
+ ${ignore(i)} ${count(i, 2)},
+ ][..],
+ )*
+
+ &[
+ ${count(i, 0)},
+ ${count(i, 1)},
+ ${count(i, 2)},
+ ${count(i, 3)},
+ ][..]
+ ][..]
+ }
+ }
+ assert_eq!(
+ three_nested_count!(
+ {
+ [ (a b c) (d e f) ]
+ [ (g h) (i j k l m) ]
+ [ (n) ]
+ }
+ {
+ [ (o) (p q) (r s) ]
+ [ (t u v w x y z) ]
+ }
+ ),
+ &[
+ // a b c
+ &[3][..],
+ // d e f
+ &[3][..],
+ // g h
+ &[2][..],
+ // i j k l m
+ &[5][..],
+ // n
+ &[1][..],
+ // o
+ &[1][..],
+ // p q
+ &[2][..],
+ // r s
+ &[2][..],
+ // t u v w x y z
+ &[7][..],
+
+ // (a b c) (d e f)
+ &[2, 6][..],
+ // (g h) (i j k l m)
+ &[2, 7][..],
+ // (n)
+ &[1, 1][..],
+ // (o) (p q) (r s)
+ &[3, 5][..],
+ // (t u v w x y z)
+ &[1, 7][..],
+
+ // [ (a b c) (d e f) ]
+ // [ (g h) (i j k l m) ]
+ // [ (n) ]
+ &[3, 5, 14][..],
+ // [ (o) (p q) (r s) ]
+ // [ (t u v w x y z) ]
+ &[2, 4, 12][..],
+
+ // {
+ // [ (a b c) (d e f) ]
+ // [ (g h) (i j k l m) ]
+ // [ (n) ]
+ // }
+ // {
+ // [ (o) (p q) (r s) ]
+ // [ (t u v w x y z) ]
+ // }
+ &[2, 5, 9, 26][..]
+ ][..]
+ );
+
+ // Grouped from the outer-most to the inner-most
+ macro_rules! three_nested_length {
+ ( $( { $( [ $( ( $( $i:ident )* ) )* ] )* } )* ) => {
+ &[
+ $( $( $( $(
+ &[
+ ${ignore(i)} ${length(3)},
+ ${ignore(i)} ${length(2)},
+ ${ignore(i)} ${length(1)},
+ ${ignore(i)} ${length(0)},
+ ][..],
+ )* )* )* )*
+
+ $( $( $(
+ &[
+ ${ignore(i)} ${length(2)},
+ ${ignore(i)} ${length(1)},
+ ${ignore(i)} ${length(0)},
+ ][..],
+ )* )* )*
+
+ $( $(
+ &[
+ ${ignore(i)} ${length(1)},
+ ${ignore(i)} ${length(0)},
+ ][..],
+ )* )*
+
+ $(
+ &[
+ ${ignore(i)} ${length(0)},
+ ][..],
+ )*
+ ][..]
+ }
+ }
+ assert_eq!(
+ three_nested_length!(
+ {
+ [ (a b c) (d e f) ]
+ [ (g h) (i j k l m) ]
+ [ (n) ]
+ }
+ {
+ [ (o) (p q) (r s) ]
+ [ (t u v w x y z) ]
+ }
+ ),
+ &[
+ // a b c
+ &[2, 3, 2, 3][..], &[2, 3, 2, 3][..], &[2, 3, 2, 3][..],
+ // d e f
+ &[2, 3, 2, 3][..], &[2, 3, 2, 3][..], &[2, 3, 2, 3][..],
+ // g h
+ &[2, 3, 2, 2][..], &[2, 3, 2, 2][..],
+ // i j k l m
+ &[2, 3, 2, 5][..], &[2, 3, 2, 5][..], &[2, 3, 2, 5][..], &[2, 3, 2, 5][..],
+ &[2, 3, 2, 5][..],
+ // n
+ &[2, 3, 1, 1][..],
+ // o
+ &[2, 2, 3, 1][..],
+ // p q
+ &[2, 2, 3, 2][..], &[2, 2, 3, 2][..],
+ // r s
+ &[2, 2, 3, 2][..], &[2, 2, 3, 2][..],
+ // t u v w x y z
+ &[2, 2, 1, 7][..], &[2, 2, 1, 7][..], &[2, 2, 1, 7][..], &[2, 2, 1, 7][..],
+ &[2, 2, 1, 7][..], &[2, 2, 1, 7][..], &[2, 2, 1, 7][..],
+
+ // (a b c) (d e f)
+ &[2, 3, 2][..], &[2, 3, 2][..],
+ // (g h) (i j k l m)
+ &[2, 3, 2][..], &[2, 3, 2][..],
+ // (n)
+ &[2, 3, 1][..],
+ // (o) (p q) (r s)
+ &[2, 2, 3][..], &[2, 2, 3][..], &[2, 2, 3][..],
+ // (t u v w x y z)
+ &[2, 2, 1][..],
+
+ // [ (a b c) (d e f) ]
+ // [ (g h) (i j k l m) ]
+ // [ (n) ]
+ &[2, 3][..], &[2, 3][..], &[2, 3,][..],
+ // [ (o) (p q) (r s) ]
+ // [ (t u v w x y z) ]
+ &[2, 2][..], &[2, 2][..],
+
+ // {
+ // [ (a b c) (d e f) ]
+ // [ (g h) (i j k l m) ]
+ // [ (n) ]
+ // }
+ // {
+ // [ (o) (p q) (r s) ]
+ // [ (t u v w x y z) ]
+ // }
+ &[2][..], &[2][..]
+ ][..]
+ );
+
+ // It is possible to say, to some degree, that count is an "amalgamation" of length (see
+ // each length line result and compare them with the count results)
+}
#![feature(macro_metavar_expr)]
-macro_rules! ignore {
- ( $( $i:ident ),* ) => {{
- let array: [i32; 0] = [$( ${ignore(i)} )*];
- array
- }};
+/// Count the number of idents in a macro repetition.
+macro_rules! count_idents {
+ ( $( $i:ident ),* ) => {
+ ${count(i)}
+ };
}
+/// Count the number of idents in a 2-dimensional macro repetition.
+macro_rules! count_idents_2 {
+ ( $( [ $( $i:ident ),* ] ),* ) => {
+ ${count(i)}
+ };
+}
+
+/// Mostly counts the number of OUTER-MOST repetitions
+macro_rules! count_depth_limits {
+ ( $( { $( [ $( $outer:ident : ( $( $inner:ident )* ) )* ] )* } )* ) => {
+ (
+ (
+ ${count(inner)},
+ ${count(inner, 0)},
+ ${count(inner, 1)},
+ ${count(inner, 2)},
+ ${count(inner, 3)},
+ ),
+ (
+ ${count(outer)},
+ ${count(outer, 0)},
+ ${count(outer, 1)},
+ ${count(outer, 2)},
+ ),
+ )
+ };
+}
+
+/// Produce (index, length) pairs for literals in a macro repetition.
+/// The literal is not included in the output, so this macro uses the
+/// `ignore` meta-variable expression to create a non-expanding
+/// repetition binding.
+macro_rules! enumerate_literals {
+ ( $( ($l:stmt) ),* ) => {
+ [$( ${ignore(l)} (${index()}, ${length()}) ),*]
+ };
+}
+
+/// Produce index and length tuples for literals in a 2-dimensional
+/// macro repetition.
+macro_rules! enumerate_literals_2 {
+ ( $( [ $( ($l:literal) ),* ] ),* ) => {
+ [
+ $(
+ $(
+ (
+ ${index(1)},
+ ${length(1)},
+ ${index(0)},
+ ${length(0)},
+ $l
+ ),
+ )*
+ )*
+ ]
+ };
+}
+
+/// Generate macros that count idents and then add a constant number
+/// to the count.
+///
+/// This macro uses dollar escaping to make it unambiguous as to which
+/// macro the repetition belongs to.
+macro_rules! make_count_adders {
+ ( $( $i:ident, $b:literal );* ) => {
+ $(
+ macro_rules! $i {
+ ( $$( $$j:ident ),* ) => {
+ $b + $${count(j)}
+ };
+ }
+ )*
+ };
+}
+
+make_count_adders! { plus_one, 1; plus_five, 5 }
+
+/// Generate a macro that allows selection of a particular literal
+/// from a sequence of inputs by their identifier.
+///
+/// This macro uses dollar escaping to make it unambiguous as to which
+/// macro the repetition belongs to, and to allow expansion of an
+/// identifier the name of which is not known in the definition
+/// of `make_picker`.
+macro_rules! make_picker {
+ ( $m:ident => $( $i:ident ),* ; $p:ident ) => {
+ macro_rules! $m {
+ ( $( $$ $i:literal ),* ) => {
+ $$ $p
+ };
+ }
+ };
+}
+
+make_picker!(first => a, b; a);
+
+make_picker!(second => a, b; b);
+
fn main() {
- assert_eq!(ignore!(a, b, c), []);
+ assert_eq!(count_idents!(a, b, c), 3);
+ assert_eq!(count_idents_2!([a, b, c], [d, e], [f]), 6);
+ assert_eq!(
+ count_depth_limits! {
+ {
+ [ A: (a b c) D: (d e f) ]
+ [ G: (g h) I: (i j k l m) ]
+ [ N: (n) ]
+ }
+ {
+ [ O: (o) P: (p q) R: (r s) ]
+ [ T: (t u v w x y z) ]
+ }
+ },
+ ((26, 2, 5, 9, 26), (9, 2, 5, 9))
+ );
+ assert_eq!(enumerate_literals![("foo"), ("bar")], [(0, 2), (1, 2)]);
+ assert_eq!(
+ enumerate_literals_2![
+ [("foo"), ("bar"), ("baz")],
+ [("qux"), ("quux"), ("quuz"), ("xyzzy")]
+ ],
+ [
+ (0, 2, 0, 3, "foo"),
+ (0, 2, 1, 3, "bar"),
+ (0, 2, 2, 3, "baz"),
+
+ (1, 2, 0, 4, "qux"),
+ (1, 2, 1, 4, "quux"),
+ (1, 2, 2, 4, "quuz"),
+ (1, 2, 3, 4, "xyzzy"),
+ ]
+ );
+ assert_eq!(plus_one!(a, b, c), 4);
+ assert_eq!(plus_five!(a, b), 7);
+ assert_eq!(first!(1, 2), 1);
+ assert_eq!(second!(1, 2), 2);
}
--- /dev/null
+// run-pass
+
+#![feature(macro_metavar_expr)]
+
+#[derive(Debug)]
+struct Example<'a> {
+ _indexes: &'a [(u32, u32)],
+ _counts: &'a [u32],
+ _nested: Vec<Example<'a>>,
+}
+
+macro_rules! example {
+ ( $( [ $( ( $( $x:ident )* ) )* ] )* ) => {
+ Example {
+ _indexes: &[],
+ _counts: &[${count(x, 0)}, ${count(x, 1)}, ${count(x, 2)}],
+ _nested: vec![
+ $(
+ Example {
+ _indexes: &[(${index()}, ${length()})],
+ _counts: &[${count(x, 0)}, ${count(x, 1)}],
+ _nested: vec![
+ $(
+ Example {
+ _indexes: &[(${index(1)}, ${length(1)}), (${index()}, ${length()})],
+ _counts: &[${count(x)}],
+ _nested: vec![
+ $(
+ Example {
+ _indexes: &[
+ (${index(2)}, ${length(2)}),
+ (${index(1)}, ${length(1)}),
+ (${index()}, ${length()})
+ ],
+ _counts: &[],
+ _nested: vec![],
+ ${ignore(x)}
+ }
+ ),*
+ ]
+ }
+ ),*
+ ]
+ }
+ ),*
+ ]
+ }
+ };
+}
+
+static EXPECTED: &str = concat!(
+ "Example { _indexes: [], _counts: [2, 4, 13], _nested: [",
+ concat!(
+ "Example { _indexes: [(0, 2)], _counts: [3, 10], _nested: [",
+ concat!(
+ "Example { _indexes: [(0, 2), (0, 3)], _counts: [4], _nested: [",
+ concat!(
+ "Example { _indexes: [(0, 2), (0, 3), (0, 4)], _counts: [], _nested: [] }, ",
+ "Example { _indexes: [(0, 2), (0, 3), (1, 4)], _counts: [], _nested: [] }, ",
+ "Example { _indexes: [(0, 2), (0, 3), (2, 4)], _counts: [], _nested: [] }, ",
+ "Example { _indexes: [(0, 2), (0, 3), (3, 4)], _counts: [], _nested: [] }",
+ ),
+ "] }, ",
+ "Example { _indexes: [(0, 2), (1, 3)], _counts: [4], _nested: [",
+ concat!(
+ "Example { _indexes: [(0, 2), (1, 3), (0, 4)], _counts: [], _nested: [] }, ",
+ "Example { _indexes: [(0, 2), (1, 3), (1, 4)], _counts: [], _nested: [] }, ",
+ "Example { _indexes: [(0, 2), (1, 3), (2, 4)], _counts: [], _nested: [] }, ",
+ "Example { _indexes: [(0, 2), (1, 3), (3, 4)], _counts: [], _nested: [] }",
+ ),
+ "] }, ",
+ "Example { _indexes: [(0, 2), (2, 3)], _counts: [2], _nested: [",
+ concat!(
+ "Example { _indexes: [(0, 2), (2, 3), (0, 2)], _counts: [], _nested: [] }, ",
+ "Example { _indexes: [(0, 2), (2, 3), (1, 2)], _counts: [], _nested: [] }",
+ ),
+ "] }",
+ ),
+ "] }, ",
+ "Example { _indexes: [(1, 2)], _counts: [1, 3], _nested: [",
+ concat!(
+ "Example { _indexes: [(1, 2), (0, 1)], _counts: [3], _nested: [",
+ concat!(
+ "Example { _indexes: [(1, 2), (0, 1), (0, 3)], _counts: [], _nested: [] }, ",
+ "Example { _indexes: [(1, 2), (0, 1), (1, 3)], _counts: [], _nested: [] }, ",
+ "Example { _indexes: [(1, 2), (0, 1), (2, 3)], _counts: [], _nested: [] }",
+ ),
+ "] }",
+ ),
+ "] }",
+ ),
+ "] }",
+);
+
+fn main() {
+ let e = example! {
+ [ ( A B C D ) ( E F G H ) ( I J ) ]
+ [ ( K L M ) ]
+ };
+ let debug = format!("{:?}", e);
+ assert_eq!(debug, EXPECTED);
+}
--- /dev/null
+#![feature(macro_metavar_expr)]
+
+macro_rules! a {
+ ( $( { $( [ $( ( $( $foo:ident )* ) )* ] )* } )* ) => {
+ (
+ ${count(foo, 0)},
+ ${count(foo, 10)},
+ //~^ ERROR count depth must be less than 4
+ )
+ };
+}
+
+macro_rules! b {
+ ( $( { $( [ $( $foo:ident )* ] )* } )* ) => {
+ (
+ $( $( $(
+ ${ignore(foo)}
+ ${index(0)},
+ ${index(10)},
+ //~^ ERROR index depth must be less than 3
+ )* )* )*
+ )
+ };
+}
+
+macro_rules! c {
+ ( $( { $( $foo:ident )* } )* ) => {
+ (
+ $( $(
+ ${ignore(foo)}
+ ${length(0)}
+ ${length(10)}
+ //~^ ERROR length depth must be less than 2
+ )* )*
+ )
+ };
+}
+
+
+fn main() {
+ a!( { [ (a) ] [ (b c) ] } );
+ b!( { [ a b ] } );
+ c!( { a } );
+}
--- /dev/null
+error: count depth must be less than 4
+ --> $DIR/out-of-bounds-arguments.rs:7:14
+ |
+LL | ${count(foo, 10)},
+ | ^^^^^^^^^^^^^^^^
+
+error: index depth must be less than 3
+ --> $DIR/out-of-bounds-arguments.rs:19:18
+ |
+LL | ${index(10)},
+ | ^^^^^^^^^^^
+
+error: length depth must be less than 2
+ --> $DIR/out-of-bounds-arguments.rs:32:18
+ |
+LL | ${length(10)}
+ | ^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
macro_rules! curly__no_rhs_dollar__no_round {
( $i:ident ) => { ${ count(i) } };
+ //~^ ERROR `count` can not be placed inside the inner-most repetition
}
macro_rules! curly__rhs_dollar__round {
//~| ERROR expected identifier
}
+macro_rules! unknown_count_ident {
+ ( $( $i:ident )* ) => {
+ ${count(foo)}
+ //~^ ERROR variable `foo` is not recognized in meta-variable expression
+ };
+}
+
+macro_rules! unknown_ignore_ident {
+ ( $( $i:ident )* ) => {
+ ${ignore(bar)}
+ //~^ ERROR variable `bar` is not recognized in meta-variable expression
+ };
+}
+
macro_rules! unknown_metavar {
( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } };
//~^ ERROR unrecognized meta-variable expression
//~^ ERROR cannot find value `a` in this scope
extra_garbage_after_metavar!(a);
- unknown_metavar!(a);
- metavar_without_parens!(a);
- metavar_token_without_ident!(a);
metavar_depth_is_not_literal!(a);
+ metavar_token_without_ident!(a);
metavar_with_literal_suffix!(a);
- open_brackets_without_tokens!(a)
+ metavar_without_parens!(a);
+ open_brackets_without_tokens!(a);
+ unknown_count_ident!(a);
+ unknown_ignore_ident!(a);
+ unknown_metavar!(a);
}
error: expected identifier, found `$`
- --> $DIR/syntax-errors.rs:16:33
+ --> $DIR/syntax-errors.rs:17:33
|
LL | ( $( $i:ident ),* ) => { ${ count($i) } };
| ^^^^^ - help: try removing `$`
error: expected identifier, found `$`
- --> $DIR/syntax-errors.rs:22:26
+ --> $DIR/syntax-errors.rs:23:26
|
LL | ( $i:ident ) => { ${ count($i) } };
| ^^^^^ - help: try removing `$`
error: unexpected token: $
- --> $DIR/syntax-errors.rs:52:8
+ --> $DIR/syntax-errors.rs:53:8
|
LL | ( $$ $a:ident ) => {
| ^
note: `$$` and meta-variable expressions are not allowed inside macro parameter definitions
- --> $DIR/syntax-errors.rs:52:8
+ --> $DIR/syntax-errors.rs:53:8
|
LL | ( $$ $a:ident ) => {
| ^
error: unexpected token: a
- --> $DIR/syntax-errors.rs:59:19
+ --> $DIR/syntax-errors.rs:60:19
|
LL | ${count() a b c}
| ^
|
note: meta-variable expression must not have trailing tokens
- --> $DIR/syntax-errors.rs:59:19
+ --> $DIR/syntax-errors.rs:60:19
|
LL | ${count() a b c}
| ^
error: unexpected token: a
- --> $DIR/syntax-errors.rs:62:19
+ --> $DIR/syntax-errors.rs:63:19
|
LL | ${count(i a b c)}
| ^
|
note: meta-variable expression must not have trailing tokens
- --> $DIR/syntax-errors.rs:62:19
+ --> $DIR/syntax-errors.rs:63:19
|
LL | ${count(i a b c)}
| ^
error: unexpected token: a
- --> $DIR/syntax-errors.rs:64:22
+ --> $DIR/syntax-errors.rs:65:22
|
LL | ${count(i, 1 a b c)}
| ^
|
note: meta-variable expression must not have trailing tokens
- --> $DIR/syntax-errors.rs:64:22
+ --> $DIR/syntax-errors.rs:65:22
|
LL | ${count(i, 1 a b c)}
| ^
error: unexpected token: a
- --> $DIR/syntax-errors.rs:66:20
+ --> $DIR/syntax-errors.rs:67:20
|
LL | ${count(i) a b c}
| ^
|
note: meta-variable expression must not have trailing tokens
- --> $DIR/syntax-errors.rs:66:20
+ --> $DIR/syntax-errors.rs:67:20
|
LL | ${count(i) a b c}
| ^
error: unexpected token: a
- --> $DIR/syntax-errors.rs:69:21
+ --> $DIR/syntax-errors.rs:70:21
|
LL | ${ignore(i) a b c}
| ^
|
note: meta-variable expression must not have trailing tokens
- --> $DIR/syntax-errors.rs:69:21
+ --> $DIR/syntax-errors.rs:70:21
|
LL | ${ignore(i) a b c}
| ^
error: unexpected token: a
- --> $DIR/syntax-errors.rs:71:20
+ --> $DIR/syntax-errors.rs:72:20
|
LL | ${ignore(i a b c)}
| ^
|
note: meta-variable expression must not have trailing tokens
- --> $DIR/syntax-errors.rs:71:20
+ --> $DIR/syntax-errors.rs:72:20
|
LL | ${ignore(i a b c)}
| ^
error: unexpected token: a
- --> $DIR/syntax-errors.rs:74:19
+ --> $DIR/syntax-errors.rs:75:19
|
LL | ${index() a b c}
| ^
|
note: meta-variable expression must not have trailing tokens
- --> $DIR/syntax-errors.rs:74:19
+ --> $DIR/syntax-errors.rs:75:19
|
LL | ${index() a b c}
| ^
error: unexpected token: a
- --> $DIR/syntax-errors.rs:76:19
+ --> $DIR/syntax-errors.rs:77:19
|
LL | ${index(1 a b c)}
| ^
|
note: meta-variable expression must not have trailing tokens
- --> $DIR/syntax-errors.rs:76:19
+ --> $DIR/syntax-errors.rs:77:19
|
LL | ${index(1 a b c)}
| ^
error: unexpected token: a
- --> $DIR/syntax-errors.rs:79:19
+ --> $DIR/syntax-errors.rs:80:19
|
LL | ${index() a b c}
| ^
|
note: meta-variable expression must not have trailing tokens
- --> $DIR/syntax-errors.rs:79:19
+ --> $DIR/syntax-errors.rs:80:19
|
LL | ${index() a b c}
| ^
error: unexpected token: a
- --> $DIR/syntax-errors.rs:81:19
+ --> $DIR/syntax-errors.rs:82:19
|
LL | ${index(1 a b c)}
| ^
|
note: meta-variable expression must not have trailing tokens
- --> $DIR/syntax-errors.rs:81:19
+ --> $DIR/syntax-errors.rs:82:19
|
LL | ${index(1 a b c)}
| ^
error: meta-variable expression depth must be a literal
- --> $DIR/syntax-errors.rs:88:33
+ --> $DIR/syntax-errors.rs:89:33
|
LL | ( $( $i:ident ),* ) => { ${ index(IDX) } };
| ^^^^^
error: unexpected token: {
- --> $DIR/syntax-errors.rs:94:8
+ --> $DIR/syntax-errors.rs:95:8
|
LL | ( ${ length() } ) => {
| ^^^^^^^^^^^^
note: `$$` and meta-variable expressions are not allowed inside macro parameter definitions
- --> $DIR/syntax-errors.rs:94:8
+ --> $DIR/syntax-errors.rs:95:8
|
LL | ( ${ length() } ) => {
| ^^^^^^^^^^^^
error: expected one of: `*`, `+`, or `?`
- --> $DIR/syntax-errors.rs:94:8
+ --> $DIR/syntax-errors.rs:95:8
|
LL | ( ${ length() } ) => {
| ^^^^^^^^^^^^
error: expected identifier
- --> $DIR/syntax-errors.rs:101:33
+ --> $DIR/syntax-errors.rs:102:33
|
LL | ( $( $i:ident ),* ) => { ${ ignore() } };
| ^^^^^^
error: only unsuffixes integer literals are supported in meta-variable expressions
- --> $DIR/syntax-errors.rs:107:33
+ --> $DIR/syntax-errors.rs:108:33
|
LL | ( $( $i:ident ),* ) => { ${ index(1u32) } };
| ^^^^^
error: meta-variable expression parameter must be wrapped in parentheses
- --> $DIR/syntax-errors.rs:113:33
+ --> $DIR/syntax-errors.rs:114:33
|
LL | ( $( $i:ident ),* ) => { ${ count{i} } };
| ^^^^^
error: expected identifier
- --> $DIR/syntax-errors.rs:119:31
+ --> $DIR/syntax-errors.rs:120:31
|
LL | ( $( $i:ident ),* ) => { ${ {} } };
| ^^^^^^
error: unrecognized meta-variable expression
- --> $DIR/syntax-errors.rs:125:33
+ --> $DIR/syntax-errors.rs:140:33
|
LL | ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } };
| ^^^^^^^^^^^^^^ help: supported expressions are count, ignore, index and length
+error: `count` can not be placed inside the inner-most repetition
+ --> $DIR/syntax-errors.rs:12:24
+ |
+LL | ( $i:ident ) => { ${ count(i) } };
+ | ^^^^^^^^^^^^
+
error: expected expression, found `$`
- --> $DIR/syntax-errors.rs:16:30
+ --> $DIR/syntax-errors.rs:17:30
|
LL | ( $( $i:ident ),* ) => { ${ count($i) } };
| ^ expected expression
= note: this error originates in the macro `curly__rhs_dollar__round` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected expression, found `$`
- --> $DIR/syntax-errors.rs:22:23
+ --> $DIR/syntax-errors.rs:23:23
|
LL | ( $i:ident ) => { ${ count($i) } };
| ^ expected expression
= note: this error originates in the macro `curly__rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info)
error: variable 'i' is still repeating at this depth
- --> $DIR/syntax-errors.rs:40:36
+ --> $DIR/syntax-errors.rs:41:36
|
LL | ( $( $i:ident ),* ) => { count($i) };
| ^^
error: expected expression, found `$`
- --> $DIR/syntax-errors.rs:59:9
+ --> $DIR/syntax-errors.rs:60:9
|
LL | ${count() a b c}
| ^ expected expression
= note: this error originates in the macro `extra_garbage_after_metavar` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected expression, found `$`
- --> $DIR/syntax-errors.rs:125:30
+ --> $DIR/syntax-errors.rs:89:30
|
-LL | ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } };
- | ^ expected expression
-...
-LL | unknown_metavar!(a);
- | ------------------- in this macro invocation
- |
- = note: this error originates in the macro `unknown_metavar` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: expected expression, found `$`
- --> $DIR/syntax-errors.rs:113:30
- |
-LL | ( $( $i:ident ),* ) => { ${ count{i} } };
+LL | ( $( $i:ident ),* ) => { ${ index(IDX) } };
| ^ expected expression
...
-LL | metavar_without_parens!(a);
- | -------------------------- in this macro invocation
+LL | metavar_depth_is_not_literal!(a);
+ | -------------------------------- in this macro invocation
|
- = note: this error originates in the macro `metavar_without_parens` (in Nightly builds, run with -Z macro-backtrace for more info)
+ = note: this error originates in the macro `metavar_depth_is_not_literal` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected expression, found `$`
- --> $DIR/syntax-errors.rs:101:30
+ --> $DIR/syntax-errors.rs:102:30
|
LL | ( $( $i:ident ),* ) => { ${ ignore() } };
| ^ expected expression
= note: this error originates in the macro `metavar_token_without_ident` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected expression, found `$`
- --> $DIR/syntax-errors.rs:88:30
+ --> $DIR/syntax-errors.rs:108:30
|
-LL | ( $( $i:ident ),* ) => { ${ index(IDX) } };
+LL | ( $( $i:ident ),* ) => { ${ index(1u32) } };
| ^ expected expression
...
-LL | metavar_depth_is_not_literal!(a);
- | -------------------------------- in this macro invocation
+LL | metavar_with_literal_suffix!(a);
+ | ------------------------------- in this macro invocation
|
- = note: this error originates in the macro `metavar_depth_is_not_literal` (in Nightly builds, run with -Z macro-backtrace for more info)
+ = note: this error originates in the macro `metavar_with_literal_suffix` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected expression, found `$`
- --> $DIR/syntax-errors.rs:107:30
+ --> $DIR/syntax-errors.rs:114:30
|
-LL | ( $( $i:ident ),* ) => { ${ index(1u32) } };
+LL | ( $( $i:ident ),* ) => { ${ count{i} } };
| ^ expected expression
...
-LL | metavar_with_literal_suffix!(a);
- | ------------------------------- in this macro invocation
+LL | metavar_without_parens!(a);
+ | -------------------------- in this macro invocation
|
- = note: this error originates in the macro `metavar_with_literal_suffix` (in Nightly builds, run with -Z macro-backtrace for more info)
+ = note: this error originates in the macro `metavar_without_parens` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected expression, found `$`
- --> $DIR/syntax-errors.rs:119:30
+ --> $DIR/syntax-errors.rs:120:30
|
LL | ( $( $i:ident ),* ) => { ${ {} } };
| ^ expected expression
...
-LL | open_brackets_without_tokens!(a)
+LL | open_brackets_without_tokens!(a);
| -------------------------------- in this macro invocation
|
= note: this error originates in the macro `open_brackets_without_tokens` (in Nightly builds, run with -Z macro-backtrace for more info)
+error: variable `foo` is not recognized in meta-variable expression
+ --> $DIR/syntax-errors.rs:127:17
+ |
+LL | ${count(foo)}
+ | ^^^
+
+error: variable `bar` is not recognized in meta-variable expression
+ --> $DIR/syntax-errors.rs:134:18
+ |
+LL | ${ignore(bar)}
+ | ^^^
+
+error: expected expression, found `$`
+ --> $DIR/syntax-errors.rs:140:30
+ |
+LL | ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } };
+ | ^ expected expression
+...
+LL | unknown_metavar!(a);
+ | ------------------- in this macro invocation
+ |
+ = note: this error originates in the macro `unknown_metavar` (in Nightly builds, run with -Z macro-backtrace for more info)
+
error[E0425]: cannot find function `count` in this scope
- --> $DIR/syntax-errors.rs:28:30
+ --> $DIR/syntax-errors.rs:29:30
|
LL | ( $( $i:ident ),* ) => { count(i) };
| ^^^^^ not found in this scope
= note: this error originates in the macro `no_curly__no_rhs_dollar__round` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0425]: cannot find value `i` in this scope
- --> $DIR/syntax-errors.rs:28:36
+ --> $DIR/syntax-errors.rs:29:36
|
LL | ( $( $i:ident ),* ) => { count(i) };
| ^ not found in this scope
= note: this error originates in the macro `no_curly__no_rhs_dollar__round` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0425]: cannot find function `count` in this scope
- --> $DIR/syntax-errors.rs:34:23
+ --> $DIR/syntax-errors.rs:35:23
|
LL | ( $i:ident ) => { count(i) };
| ^^^^^ not found in this scope
= note: this error originates in the macro `no_curly__no_rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0425]: cannot find value `i` in this scope
- --> $DIR/syntax-errors.rs:34:29
+ --> $DIR/syntax-errors.rs:35:29
|
LL | ( $i:ident ) => { count(i) };
| ^ not found in this scope
= note: this error originates in the macro `no_curly__no_rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0425]: cannot find function `count` in this scope
- --> $DIR/syntax-errors.rs:45:23
+ --> $DIR/syntax-errors.rs:46:23
|
LL | ( $i:ident ) => { count($i) };
| ^^^^^ not found in this scope
= note: this error originates in the macro `no_curly__rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0425]: cannot find value `a` in this scope
- --> $DIR/syntax-errors.rs:138:37
+ --> $DIR/syntax-errors.rs:153:37
|
LL | no_curly__rhs_dollar__no_round!(a);
| ^ not found in this scope
-error: aborting due to 37 previous errors
+error: aborting due to 40 previous errors
For more information about this error, try `rustc --explain E0425`.
--- /dev/null
+fn main() {
+ let x: i32 = 1;
+ println!("{:?}", x.count()); //~ ERROR is not an iterator
+}
--- /dev/null
+error[E0599]: `i32` is not an iterator
+ --> $DIR/issue-84495.rs:3:24
+ |
+LL | println!("{:?}", x.count());
+ | ^^^^^ `i32` is not an iterator
+ |
+ = note: the following trait bounds were not satisfied:
+ `i32: Iterator`
+ which is required by `&mut i32: Iterator`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
use std::iter::once;
fn main() {
once::<&str>("str").fuse().filter(|a: &str| true).count();
- //~^ ERROR not an iterator
+ //~^ ERROR the method
//~| ERROR type mismatch in closure arguments
}
LL | P: FnMut(&Self::Item) -> bool,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `filter`
-error[E0599]: `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` is not an iterator
+error[E0599]: the method `count` exists for struct `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>`, but its trait bounds were not satisfied
--> $DIR/issue-36053-2.rs:7:55
|
LL | once::<&str>("str").fuse().filter(|a: &str| true).count();
- | -------------- ^^^^^ `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` is not an iterator
+ | -------------- ^^^^^ method cannot be called on `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` due to unsatisfied trait bounds
| |
| doesn't satisfy `<_ as FnOnce<(&&str,)>>::Output = bool`
| doesn't satisfy `_: FnMut<(&&str,)>`
-pub enum Foo {
+pub enum HiddenEnum {
A,
B,
#[doc(hidden)]
C,
}
+
+#[derive(Default)]
+pub struct HiddenStruct {
+ pub one: u8,
+ pub two: bool,
+ #[doc(hidden)]
+ pub hide: usize,
+}
#![stable(feature = "stable_test_feature", since = "1.0.0")]
#[stable(feature = "stable_test_feature", since = "1.0.0")]
-pub enum Foo {
+pub enum UnstableEnum {
#[stable(feature = "stable_test_feature", since = "1.0.0")]
Stable,
#[stable(feature = "stable_test_feature", since = "1.0.0")]
#[unstable(feature = "unstable_test_feature", issue = "none")]
Unstable,
}
+
+#[derive(Default)]
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+pub struct UnstableStruct {
+ #[stable(feature = "stable_test_feature", since = "1.0.0")]
+ pub stable: bool,
+ #[stable(feature = "stable_test_feature", since = "1.0.0")]
+ pub stable2: usize,
+ #[unstable(feature = "unstable_test_feature", issue = "none")]
+ pub unstable: u8,
+}
--- /dev/null
+// aux-build:hidden.rs
+
+extern crate hidden;
+
+use hidden::HiddenStruct;
+
+struct InCrate {
+ a: usize,
+ b: bool,
+ #[doc(hidden)]
+ im_hidden: u8
+}
+
+fn main() {
+ let HiddenStruct { one, two } = HiddenStruct::default();
+ //~^ pattern requires `..` due to inaccessible fields
+
+ let HiddenStruct { one } = HiddenStruct::default();
+ //~^ pattern does not mention field `two` and inaccessible fields
+
+ let HiddenStruct { one, hide } = HiddenStruct::default();
+ //~^ pattern does not mention field `two`
+
+ let InCrate { a, b } = InCrate { a: 0, b: false, im_hidden: 0 };
+ //~^ pattern does not mention field `im_hidden`
+}
--- /dev/null
+error: pattern requires `..` due to inaccessible fields
+ --> $DIR/doc-hidden-fields.rs:15:9
+ |
+LL | let HiddenStruct { one, two } = HiddenStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: ignore the inaccessible and unused fields
+ |
+LL | let HiddenStruct { one, two, .. } = HiddenStruct::default();
+ | ++++
+
+error[E0027]: pattern does not mention field `two` and inaccessible fields
+ --> $DIR/doc-hidden-fields.rs:18:9
+ |
+LL | let HiddenStruct { one } = HiddenStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^ missing field `two` and inaccessible fields
+ |
+help: include the missing field in the pattern and ignore the inaccessible fields
+ |
+LL | let HiddenStruct { one, two, .. } = HiddenStruct::default();
+ | ~~~~~~~~~~~
+help: if you don't care about this missing field, you can explicitly ignore it
+ |
+LL | let HiddenStruct { one, .. } = HiddenStruct::default();
+ | ~~~~~~
+
+error[E0027]: pattern does not mention field `two`
+ --> $DIR/doc-hidden-fields.rs:21:9
+ |
+LL | let HiddenStruct { one, hide } = HiddenStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `two`
+ |
+help: include the missing field in the pattern
+ |
+LL | let HiddenStruct { one, hide, two } = HiddenStruct::default();
+ | ~~~~~~~
+help: if you don't care about this missing field, you can explicitly ignore it
+ |
+LL | let HiddenStruct { one, hide, .. } = HiddenStruct::default();
+ | ~~~~~~
+
+error[E0027]: pattern does not mention field `im_hidden`
+ --> $DIR/doc-hidden-fields.rs:24:9
+ |
+LL | let InCrate { a, b } = InCrate { a: 0, b: false, im_hidden: 0 };
+ | ^^^^^^^^^^^^^^^^ missing field `im_hidden`
+ |
+help: include the missing field in the pattern
+ |
+LL | let InCrate { a, b, im_hidden } = InCrate { a: 0, b: false, im_hidden: 0 };
+ | ~~~~~~~~~~~~~
+help: if you don't care about this missing field, you can explicitly ignore it
+ |
+LL | let InCrate { a, b, .. } = InCrate { a: 0, b: false, im_hidden: 0 };
+ | ~~~~~~
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0027`.
extern crate hidden;
-use hidden::Foo;
+use hidden::HiddenEnum;
+
+enum InCrate {
+ A,
+ B,
+ #[doc(hidden)]
+ C,
+}
fn main() {
- match Foo::A {
- Foo::A => {}
- Foo::B => {}
+ match HiddenEnum::A {
+ HiddenEnum::A => {}
+ HiddenEnum::B => {}
}
//~^^^^ non-exhaustive patterns: `_` not covered
- match Foo::A {
- Foo::A => {}
- Foo::C => {}
+ match HiddenEnum::A {
+ HiddenEnum::A => {}
+ HiddenEnum::C => {}
}
//~^^^^ non-exhaustive patterns: `B` not covered
- match Foo::A {
- Foo::A => {}
+ match HiddenEnum::A {
+ HiddenEnum::A => {}
}
//~^^^ non-exhaustive patterns: `B` and `_` not covered
match None {
None => {}
- Some(Foo::A) => {}
+ Some(HiddenEnum::A) => {}
}
//~^^^^ non-exhaustive patterns: `Some(B)` and `Some(_)` not covered
+
+ match InCrate::A {
+ InCrate::A => {}
+ InCrate::B => {}
+ }
+ //~^^^^ non-exhaustive patterns: `C` not covered
}
error[E0004]: non-exhaustive patterns: `_` not covered
- --> $DIR/doc-hidden-non-exhaustive.rs:8:11
+ --> $DIR/doc-hidden-non-exhaustive.rs:15:11
|
-LL | match Foo::A {
- | ^^^^^^ pattern `_` not covered
+LL | match HiddenEnum::A {
+ | ^^^^^^^^^^^^^ pattern `_` not covered
|
-note: `Foo` defined here
+note: `HiddenEnum` defined here
--> $DIR/auxiliary/hidden.rs:1:1
|
-LL | / pub enum Foo {
+LL | / pub enum HiddenEnum {
LL | | A,
LL | | B,
LL | | #[doc(hidden)]
LL | | C,
LL | | }
| |_^
- = note: the matched value is of type `Foo`
+ = note: the matched value is of type `HiddenEnum`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
-LL ~ Foo::B => {}
+LL ~ HiddenEnum::B => {}
LL + _ => todo!()
|
error[E0004]: non-exhaustive patterns: `B` not covered
- --> $DIR/doc-hidden-non-exhaustive.rs:14:11
+ --> $DIR/doc-hidden-non-exhaustive.rs:21:11
|
-LL | match Foo::A {
- | ^^^^^^ pattern `B` not covered
+LL | match HiddenEnum::A {
+ | ^^^^^^^^^^^^^ pattern `B` not covered
|
-note: `Foo` defined here
+note: `HiddenEnum` defined here
--> $DIR/auxiliary/hidden.rs:3:5
|
-LL | / pub enum Foo {
+LL | / pub enum HiddenEnum {
LL | | A,
LL | | B,
| | ^ not covered
LL | | C,
LL | | }
| |_-
- = note: the matched value is of type `Foo`
+ = note: the matched value is of type `HiddenEnum`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
-LL ~ Foo::C => {}
+LL ~ HiddenEnum::C => {}
LL + B => todo!()
|
error[E0004]: non-exhaustive patterns: `B` and `_` not covered
- --> $DIR/doc-hidden-non-exhaustive.rs:20:11
+ --> $DIR/doc-hidden-non-exhaustive.rs:27:11
|
-LL | match Foo::A {
- | ^^^^^^ patterns `B` and `_` not covered
+LL | match HiddenEnum::A {
+ | ^^^^^^^^^^^^^ patterns `B` and `_` not covered
|
-note: `Foo` defined here
+note: `HiddenEnum` defined here
--> $DIR/auxiliary/hidden.rs:3:5
|
-LL | / pub enum Foo {
+LL | / pub enum HiddenEnum {
LL | | A,
LL | | B,
| | ^ not covered
LL | | C,
LL | | }
| |_-
- = note: the matched value is of type `Foo`
+ = note: the matched value is of type `HiddenEnum`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
|
-LL ~ Foo::A => {}
+LL ~ HiddenEnum::A => {}
LL + B | _ => todo!()
|
error[E0004]: non-exhaustive patterns: `Some(B)` and `Some(_)` not covered
- --> $DIR/doc-hidden-non-exhaustive.rs:25:11
+ --> $DIR/doc-hidden-non-exhaustive.rs:32:11
|
LL | match None {
| ^^^^ patterns `Some(B)` and `Some(_)` not covered
|
-note: `Option<Foo>` defined here
+note: `Option<HiddenEnum>` defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
|
LL | / pub enum Option<T> {
| | ^^^^ not covered
LL | | }
| |_-
- = note: the matched value is of type `Option<Foo>`
+ = note: the matched value is of type `Option<HiddenEnum>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
|
-LL ~ Some(Foo::A) => {}
+LL ~ Some(HiddenEnum::A) => {}
LL + Some(B) | Some(_) => todo!()
|
-error: aborting due to 4 previous errors
+error[E0004]: non-exhaustive patterns: `C` not covered
+ --> $DIR/doc-hidden-non-exhaustive.rs:38:11
+ |
+LL | match InCrate::A {
+ | ^^^^^^^^^^ pattern `C` not covered
+ |
+note: `InCrate` defined here
+ --> $DIR/doc-hidden-non-exhaustive.rs:11:5
+ |
+LL | enum InCrate {
+ | -------
+...
+LL | C,
+ | ^ not covered
+ = note: the matched value is of type `InCrate`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+ |
+LL ~ InCrate::B => {}
+LL + C => todo!()
+ |
+
+error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0004`.
--- /dev/null
+// aux-build:unstable.rs
+
+extern crate unstable;
+
+use unstable::UnstableStruct;
+
+fn main() {
+ let UnstableStruct { stable } = UnstableStruct::default();
+ //~^ pattern does not mention field `stable2` and inaccessible fields
+
+ let UnstableStruct { stable, stable2 } = UnstableStruct::default();
+ //~^ pattern requires `..` due to inaccessible fields
+
+ // OK: stable field is matched
+ let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
+}
--- /dev/null
+error[E0027]: pattern does not mention field `stable2` and inaccessible fields
+ --> $DIR/stable-gated-fields.rs:8:9
+ |
+LL | let UnstableStruct { stable } = UnstableStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `stable2` and inaccessible fields
+ |
+help: include the missing field in the pattern and ignore the inaccessible fields
+ |
+LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
+ | ~~~~~~~~~~~~~~~
+help: if you don't care about this missing field, you can explicitly ignore it
+ |
+LL | let UnstableStruct { stable, .. } = UnstableStruct::default();
+ | ~~~~~~
+
+error: pattern requires `..` due to inaccessible fields
+ --> $DIR/stable-gated-fields.rs:11:9
+ |
+LL | let UnstableStruct { stable, stable2 } = UnstableStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: ignore the inaccessible and unused fields
+ |
+LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
+ | ++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0027`.
extern crate unstable;
-use unstable::Foo;
+use unstable::UnstableEnum;
fn main() {
- match Foo::Stable {
- Foo::Stable => {}
+ match UnstableEnum::Stable {
+ UnstableEnum::Stable => {}
}
//~^^^ non-exhaustive patterns: `Stable2` and `_` not covered
- match Foo::Stable {
- Foo::Stable => {}
- Foo::Stable2 => {}
+ match UnstableEnum::Stable {
+ UnstableEnum::Stable => {}
+ UnstableEnum::Stable2 => {}
}
//~^^^^ non-exhaustive patterns: `_` not covered
}
error[E0004]: non-exhaustive patterns: `Stable2` and `_` not covered
--> $DIR/stable-gated-patterns.rs:8:11
|
-LL | match Foo::Stable {
- | ^^^^^^^^^^^ patterns `Stable2` and `_` not covered
+LL | match UnstableEnum::Stable {
+ | ^^^^^^^^^^^^^^^^^^^^ patterns `Stable2` and `_` not covered
|
-note: `Foo` defined here
+note: `UnstableEnum` defined here
--> $DIR/auxiliary/unstable.rs:9:5
|
-LL | / pub enum Foo {
+LL | / pub enum UnstableEnum {
LL | | #[stable(feature = "stable_test_feature", since = "1.0.0")]
LL | | Stable,
LL | | #[stable(feature = "stable_test_feature", since = "1.0.0")]
LL | | Unstable,
LL | | }
| |_-
- = note: the matched value is of type `Foo`
+ = note: the matched value is of type `UnstableEnum`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
|
-LL ~ Foo::Stable => {}
+LL ~ UnstableEnum::Stable => {}
LL + Stable2 | _ => todo!()
|
error[E0004]: non-exhaustive patterns: `_` not covered
--> $DIR/stable-gated-patterns.rs:13:11
|
-LL | match Foo::Stable {
- | ^^^^^^^^^^^ pattern `_` not covered
+LL | match UnstableEnum::Stable {
+ | ^^^^^^^^^^^^^^^^^^^^ pattern `_` not covered
|
-note: `Foo` defined here
+note: `UnstableEnum` defined here
--> $DIR/auxiliary/unstable.rs:5:1
|
-LL | / pub enum Foo {
+LL | / pub enum UnstableEnum {
LL | | #[stable(feature = "stable_test_feature", since = "1.0.0")]
LL | | Stable,
LL | | #[stable(feature = "stable_test_feature", since = "1.0.0")]
LL | | Unstable,
LL | | }
| |_^
- = note: the matched value is of type `Foo`
+ = note: the matched value is of type `UnstableEnum`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
-LL ~ Foo::Stable2 => {}
+LL ~ UnstableEnum::Stable2 => {}
LL + _ => todo!()
|
--- /dev/null
+#![feature(unstable_test_feature)]
+
+// aux-build:unstable.rs
+
+extern crate unstable;
+
+use unstable::UnstableStruct;
+
+fn main() {
+ let UnstableStruct { stable, stable2, } = UnstableStruct::default();
+ //~^ pattern does not mention field `unstable`
+
+ let UnstableStruct { stable, unstable, } = UnstableStruct::default();
+ //~^ pattern does not mention field `stable2`
+
+ // OK: stable field is matched
+ let UnstableStruct { stable, stable2, unstable } = UnstableStruct::default();
+}
--- /dev/null
+error[E0027]: pattern does not mention field `unstable`
+ --> $DIR/unstable-gated-fields.rs:10:9
+ |
+LL | let UnstableStruct { stable, stable2, } = UnstableStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `unstable`
+ |
+help: include the missing field in the pattern
+ |
+LL | let UnstableStruct { stable, stable2, unstable } = UnstableStruct::default();
+ | ~~~~~~~~~~~~
+help: if you don't care about this missing field, you can explicitly ignore it
+ |
+LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
+ | ~~~~~~
+
+error[E0027]: pattern does not mention field `stable2`
+ --> $DIR/unstable-gated-fields.rs:13:9
+ |
+LL | let UnstableStruct { stable, unstable, } = UnstableStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `stable2`
+ |
+help: include the missing field in the pattern
+ |
+LL | let UnstableStruct { stable, unstable, stable2 } = UnstableStruct::default();
+ | ~~~~~~~~~~~
+help: if you don't care about this missing field, you can explicitly ignore it
+ |
+LL | let UnstableStruct { stable, unstable, .. } = UnstableStruct::default();
+ | ~~~~~~
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0027`.
extern crate unstable;
-use unstable::Foo;
+use unstable::UnstableEnum;
fn main() {
- match Foo::Stable {
- Foo::Stable => {}
- Foo::Stable2 => {}
+ match UnstableEnum::Stable {
+ UnstableEnum::Stable => {}
+ UnstableEnum::Stable2 => {}
}
//~^^^^ non-exhaustive patterns: `Unstable` not covered
// Ok: all variants are explicitly matched
- match Foo::Stable {
- Foo::Stable => {}
- Foo::Stable2 => {}
- Foo::Unstable => {}
+ match UnstableEnum::Stable {
+ UnstableEnum::Stable => {}
+ UnstableEnum::Stable2 => {}
+ UnstableEnum::Unstable => {}
}
}
error[E0004]: non-exhaustive patterns: `Unstable` not covered
--> $DIR/unstable-gated-patterns.rs:10:11
|
-LL | match Foo::Stable {
- | ^^^^^^^^^^^ pattern `Unstable` not covered
+LL | match UnstableEnum::Stable {
+ | ^^^^^^^^^^^^^^^^^^^^ pattern `Unstable` not covered
|
-note: `Foo` defined here
+note: `UnstableEnum` defined here
--> $DIR/auxiliary/unstable.rs:11:5
|
-LL | / pub enum Foo {
+LL | / pub enum UnstableEnum {
LL | | #[stable(feature = "stable_test_feature", since = "1.0.0")]
LL | | Stable,
LL | | #[stable(feature = "stable_test_feature", since = "1.0.0")]
| | ^^^^^^^^ not covered
LL | | }
| |_-
- = note: the matched value is of type `Foo`
+ = note: the matched value is of type `UnstableEnum`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
-LL ~ Foo::Stable2 => {}
+LL ~ UnstableEnum::Stable2 => {}
LL + Unstable => todo!()
|
Self::Unstable
}
}
+
+#[derive(Default)]
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[non_exhaustive]
+pub struct UnstableStruct {
+ #[stable(feature = "stable_test_feature", since = "1.0.0")]
+ pub stable: bool,
+ #[stable(feature = "stable_test_feature", since = "1.0.0")]
+ pub stable2: usize,
+ #[unstable(feature = "unstable_test_feature", issue = "none")]
+ pub unstable: u8,
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[non_exhaustive]
+pub struct OnlyUnstableStruct {
+ #[unstable(feature = "unstable_test_feature", issue = "none")]
+ pub unstable: u8,
+ #[unstable(feature = "unstable_test_feature", issue = "none")]
+ pub unstable2: bool,
+}
+
+impl OnlyUnstableStruct {
+ #[stable(feature = "stable_test_feature", since = "1.0.0")]
+ pub fn new() -> Self {
+ Self {
+ unstable: 0,
+ unstable2: false,
+ }
+ }
+}
EmptyNonExhaustiveEnum, NestedNonExhaustive, NonExhaustiveEnum, NonExhaustiveSingleVariant,
VariantNonExhaustive,
};
-use unstable::{UnstableEnum, OnlyUnstableEnum};
+use unstable::{UnstableEnum, OnlyUnstableEnum, UnstableStruct, OnlyUnstableStruct};
use structs::{FunctionalRecord, MixedVisFields, NestedStruct, NormalStruct};
#[non_exhaustive]
}
//~^^ some variants are not matched explicitly
+ // Ok: the feature is on and all variants are matched
#[deny(non_exhaustive_omitted_patterns)]
match UnstableEnum::Stable {
UnstableEnum::Stable => {}
_ => {}
}
//~^^ some variants are not matched explicitly
+
+ #[warn(non_exhaustive_omitted_patterns)]
+ let OnlyUnstableStruct { unstable, .. } = OnlyUnstableStruct::new();
+ //~^ some fields are not explicitly listed
+
+ // OK: both unstable fields are matched with feature on
+ #[warn(non_exhaustive_omitted_patterns)]
+ let OnlyUnstableStruct { unstable, unstable2, .. } = OnlyUnstableStruct::new();
+
+ #[warn(non_exhaustive_omitted_patterns)]
+ let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
+ //~^ some fields are not explicitly listed
+
+ // OK: both unstable and stable fields are matched with feature on
+ #[warn(non_exhaustive_omitted_patterns)]
+ let UnstableStruct { stable, stable2, unstable, .. } = UnstableStruct::default();
}
= help: ensure that all fields are mentioned explicitly by adding the suggested fields
= note: the pattern is of type `NestedStruct` and the `non_exhaustive_omitted_patterns` attribute was found
+warning: some fields are not explicitly listed
+ --> $DIR/omitted-patterns.rs:173:9
+ |
+LL | let OnlyUnstableStruct { unstable, .. } = OnlyUnstableStruct::new();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `unstable2` not listed
+ |
+note: the lint level is defined here
+ --> $DIR/omitted-patterns.rs:172:12
+ |
+LL | #[warn(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `OnlyUnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found
+
+warning: some fields are not explicitly listed
+ --> $DIR/omitted-patterns.rs:181:9
+ |
+LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `unstable` not listed
+ |
+note: the lint level is defined here
+ --> $DIR/omitted-patterns.rs:180:12
+ |
+LL | #[warn(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `UnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found
+
error: some variants are not matched explicitly
--> $DIR/omitted-patterns.rs:58:9
|
= note: the matched value is of type `UnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found
error: some variants are not matched explicitly
- --> $DIR/omitted-patterns.rs:167:9
+ --> $DIR/omitted-patterns.rs:168:9
|
LL | _ => {}
| ^ pattern `Unstable2` not covered
|
note: the lint level is defined here
- --> $DIR/omitted-patterns.rs:164:12
+ --> $DIR/omitted-patterns.rs:165:12
|
LL | #[deny(non_exhaustive_omitted_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: ensure that all variants are matched explicitly by adding the suggested match arms
= note: the matched value is of type `OnlyUnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found
-error: aborting due to 8 previous errors; 4 warnings emitted
+error: aborting due to 8 previous errors; 6 warnings emitted
// aux-build:unstable.rs
extern crate unstable;
-use unstable::{UnstableEnum, OnlyUnstableEnum};
+use unstable::{UnstableEnum, OnlyUnstableEnum, UnstableStruct, OnlyUnstableStruct};
fn main() {
// OK: this matches all the stable variants
match OnlyUnstableEnum::new() {
_ => {}
}
+
+ // Ok: Same as the above enum (no fields can be matched on)
+ #[warn(non_exhaustive_omitted_patterns)]
+ let OnlyUnstableStruct { .. } = OnlyUnstableStruct::new();
+
+ #[warn(non_exhaustive_omitted_patterns)]
+ let UnstableStruct { stable, .. } = UnstableStruct::default();
+ //~^ some fields are not explicitly listed
+
+ // OK: stable field is matched
+ #[warn(non_exhaustive_omitted_patterns)]
+ let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
}
+warning: some fields are not explicitly listed
+ --> $DIR/stable-omitted-patterns.rs:39:9
+ |
+LL | let UnstableStruct { stable, .. } = UnstableStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `stable2` not listed
+ |
+note: the lint level is defined here
+ --> $DIR/stable-omitted-patterns.rs:38:12
+ |
+LL | #[warn(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `UnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found
+
error: some variants are not matched explicitly
--> $DIR/stable-omitted-patterns.rs:23:9
|
= help: ensure that all variants are matched explicitly by adding the suggested match arms
= note: the matched value is of type `UnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
--- /dev/null
+struct Bug<S>{ //~ ERROR parameter `S` is never used [E0392]
+ A: [(); {
+ let x: [u8; Self::W] = [0; Self::W]; //~ ERROR generic `Self` types are currently not permitted in anonymous constants
+ //~^ ERROR generic `Self` types are currently not permitted in anonymous constants
+ //~^^ ERROR the size for values of type `S` cannot be known at compilation time [E0277]
+ F //~ ERROR cannot find value `F` in this scope [E0425]
+ }
+} //~ ERROR mismatched closing delimiter: `}`
+//~^ ERROR mismatched closing delimiter: `}`
+
+fn main() {}
--- /dev/null
+error: mismatched closing delimiter: `}`
+ --> $DIR/constrain-suggest-ice.rs:2:8
+ |
+LL | struct Bug<S>{
+ | - closing delimiter possibly meant for this
+LL | A: [(); {
+ | ^ unclosed delimiter
+...
+LL | }
+ | ^ mismatched closing delimiter
+
+error: mismatched closing delimiter: `}`
+ --> $DIR/constrain-suggest-ice.rs:2:8
+ |
+LL | struct Bug<S>{
+ | - closing delimiter possibly meant for this
+LL | A: [(); {
+ | ^ unclosed delimiter
+...
+LL | }
+ | ^ mismatched closing delimiter
+
+error[E0425]: cannot find value `F` in this scope
+ --> $DIR/constrain-suggest-ice.rs:6:9
+ |
+LL | F
+ | ^
+ |
+help: a local variable with a similar name exists
+ |
+LL | x
+ | ~
+help: you might be missing a type parameter
+ |
+LL | struct Bug<S, F>{
+ | +++
+
+error: generic `Self` types are currently not permitted in anonymous constants
+ --> $DIR/constrain-suggest-ice.rs:3:21
+ |
+LL | let x: [u8; Self::W] = [0; Self::W];
+ | ^^^^
+
+error: generic `Self` types are currently not permitted in anonymous constants
+ --> $DIR/constrain-suggest-ice.rs:3:36
+ |
+LL | let x: [u8; Self::W] = [0; Self::W];
+ | ^^^^
+
+error[E0277]: the size for values of type `S` cannot be known at compilation time
+ --> $DIR/constrain-suggest-ice.rs:3:36
+ |
+LL | struct Bug<S>{
+ | - this type parameter needs to be `std::marker::Sized`
+LL | A: [(); {
+LL | let x: [u8; Self::W] = [0; Self::W];
+ | ^^^^^^^ doesn't have a size known at compile-time
+ |
+note: required by a bound in `Bug`
+ --> $DIR/constrain-suggest-ice.rs:1:12
+ |
+LL | struct Bug<S>{
+ | ^ required by this bound in `Bug`
+help: consider relaxing the implicit `Sized` restriction
+ |
+LL | struct Bug<S: ?Sized>{
+ | ++++++++
+
+error[E0392]: parameter `S` is never used
+ --> $DIR/constrain-suggest-ice.rs:1:12
+ |
+LL | struct Bug<S>{
+ | ^ unused parameter
+ |
+ = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
+ = help: if you intended `S` to be a const parameter, use `const S: usize` instead
+
+error: aborting due to 7 previous errors
+
+Some errors have detailed explanations: E0277, E0392, E0425.
+For more information about an error, try `rustc --explain E0277`.
--- /dev/null
+mod foo {
+ struct A;
+ mod bar {
+ struct B;
+ }
+}
+
+struct Foo {
+ a: foo:A,
+ //~^ ERROR found single colon in a struct field type path
+ //~| expected `,`, or `}`, found `:`
+}
+
+struct Bar {
+ b: foo::bar:B,
+ //~^ ERROR found single colon in a struct field type path
+ //~| expected `,`, or `}`, found `:`
+}
+
+fn main() {}
--- /dev/null
+error: found single colon in a struct field type path
+ --> $DIR/struct-field-type-including-single-colon.rs:9:11
+ |
+LL | a: foo:A,
+ | ^
+ |
+help: write a path separator here
+ |
+LL | a: foo::A,
+ | ~~
+
+error: expected `,`, or `}`, found `:`
+ --> $DIR/struct-field-type-including-single-colon.rs:9:11
+ |
+LL | a: foo:A,
+ | ^
+
+error: found single colon in a struct field type path
+ --> $DIR/struct-field-type-including-single-colon.rs:15:16
+ |
+LL | b: foo::bar:B,
+ | ^
+ |
+help: write a path separator here
+ |
+LL | b: foo::bar::B,
+ | ~~
+
+error: expected `,`, or `}`, found `:`
+ --> $DIR/struct-field-type-including-single-colon.rs:15:16
+ |
+LL | b: foo::bar:B,
+ | ^
+
+error: aborting due to 4 previous errors
+
fn check_interior_types(cx: &LateContext<'_>, ty_causes: &[GeneratorInteriorTypeCause<'_>], span: Span) {
for ty_cause in ty_causes {
if let rustc_middle::ty::Adt(adt, _) = ty_cause.ty.kind() {
- if is_mutex_guard(cx, adt.did) {
+ if is_mutex_guard(cx, adt.did()) {
span_lint_and_then(
cx,
AWAIT_HOLDING_LOCK,
},
);
}
- if is_refcell_ref(cx, adt.did) {
+ if is_refcell_ref(cx, adt.did()) {
span_lint_and_then(
cx,
AWAIT_HOLDING_REFCELL_REF,
use clippy_utils::diagnostics::span_lint_and_help;
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
+use rustc_data_structures::intern::Interned;
use rustc_hir::{Expr, ExprKind, PathSegment};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
ty::Str => {
return Some(span);
},
- ty::Adt(&ty::AdtDef { did, .. }, _) => {
+ ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did, .. }, _)), _) => {
if ctx.tcx.is_diagnostic_item(sym::String, did) {
return Some(span);
}
&& let Res::Def(DefKind::Ctor(..), id) = cx.qpath_res(p, cast_expr.hir_id)
{
let i = def.variant_index_with_ctor_id(id);
- let variant = &def.variants[i];
- let nbits = utils::enum_value_nbits(get_discriminant_value(cx.tcx, def, i));
+ let variant = def.variant(i);
+ let nbits = utils::enum_value_nbits(get_discriminant_value(cx.tcx, *def, i));
(nbits, Some(variant))
} else {
- (utils::enum_ty_to_nbits(def, cx.tcx), None)
+ (utils::enum_ty_to_nbits(*def, cx.tcx), None)
};
let to_nbits = utils::int_ty_to_nbits(cast_to, cx.tcx);
- let cast_from_ptr_size = def.repr.int.map_or(true, |ty| {
+ let cast_from_ptr_size = def.repr().int.map_or(true, |ty| {
matches!(
ty,
IntType::SignedInt(ast::IntTy::Isize) | IntType::UnsignedInt(ast::UintTy::Usize)
.into()
}
-pub(super) fn enum_ty_to_nbits(adt: &AdtDef, tcx: TyCtxt<'_>) -> u64 {
+pub(super) fn enum_ty_to_nbits(adt: AdtDef<'_>, tcx: TyCtxt<'_>) -> u64 {
let mut explicit = 0i128;
let (start, end) = adt
- .variants
+ .variants()
.iter()
.fold((0, i128::MIN), |(start, end), variant| match variant.discr {
VariantDiscr::Relative(x) => match explicit.checked_add(i128::from(x)) {
then {
// TODO: Work out a way to put "whatever the imported way of referencing
// this type in this file" rather than a fully-qualified type.
- let replacement = format!("{}::default()", cx.tcx.def_path_str(def.did));
+ let replacement = format!("{}::default()", cx.tcx.def_path_str(def.did()));
span_lint_and_sugg(
cx,
DEFAULT_TRAIT_ACCESS,
if let Some(adt) = binding_type.ty_adt_def();
if adt.is_struct();
let variant = adt.non_enum_variant();
- if adt.did.is_local() || !variant.is_field_list_non_exhaustive();
+ if adt.did().is_local() || !variant.is_field_list_non_exhaustive();
let module_did = cx.tcx.parent_module(stmt.hir_id).to_def_id();
if variant
.fields
if let ty::Adt(adt_def, substs) = binding_type.kind();
if !substs.is_empty();
then {
- let adt_def_ty_name = cx.tcx.item_name(adt_def.did);
+ let adt_def_ty_name = cx.tcx.item_name(adt_def.did());
let generic_args = substs.iter().collect::<Vec<_>>();
let tys_str = generic_args
.iter()
if_chain! {
if let Some(adt_def) = ty.ty_adt_def();
if adt_def.is_struct();
- if let Some(variant) = adt_def.variants.iter().next();
+ if let Some(variant) = adt_def.variants().iter().next();
then {
let fields_def = &variant.fields;
_ => false,
};
if should_emit {
- let path_string = cx.tcx.def_path_str(adt_def.did);
+ let path_string = cx.tcx.def_path_str(adt_def.did());
span_lint_and_help(
cx,
DERIVABLE_IMPLS,
let has_copy_impl = cx.tcx.all_local_trait_impls(()).get(©_id).map_or(false, |impls| {
impls
.iter()
- .any(|&id| matches!(cx.tcx.type_of(id).kind(), ty::Adt(adt, _) if ty_adt.did == adt.did))
+ .any(|&id| matches!(cx.tcx.type_of(id).kind(), ty::Adt(adt, _) if ty_adt.did() == adt.did()))
});
if !has_copy_impl {
return;
if let Some(trait_def_id) = trait_ref.trait_def_id();
if match_def_path(cx, trait_def_id, &paths::SERDE_DESERIALIZE);
if let ty::Adt(def, _) = ty.kind();
- if let Some(local_def_id) = def.did.as_local();
+ if let Some(local_def_id) = def.did().as_local();
let adt_hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
if !is_lint_allowed(cx, UNSAFE_DERIVE_DESERIALIZE, adt_hir_id);
- if cx.tcx.inherent_impls(def.did)
+ if cx.tcx.inherent_impls(def.did())
.iter()
.map(|imp_did| cx.tcx.hir().expect_item(imp_did.expect_local()))
.any(|imp| has_unsafe(cx, imp));
if let ItemKind::Enum(..) = item.kind {
let ty = cx.tcx.type_of(item.def_id);
let adt = ty.ty_adt_def().expect("already checked whether this is an enum");
- if adt.variants.is_empty() {
+ if adt.variants().is_empty() {
span_lint_and_help(
cx,
EMPTY_ENUM,
if let Some(Constant::Int(val)) = constant.and_then(miri_to_const) {
if let ty::Adt(adt, _) = ty.kind() {
if adt.is_enum() {
- ty = adt.repr.discr_type().to_ty(cx.tcx);
+ ty = adt.repr().discr_type().to_ty(cx.tcx);
}
}
match ty.kind() {
fn are_equal<'tcx>(cx: &LateContext<'tcx>, middle_ty: Ty<'_>, hir_ty: &rustc_hir::Ty<'_>) -> bool {
if_chain! {
if let ty::Adt(adt_def, _) = middle_ty.kind();
- if let Some(local_did) = adt_def.did.as_local();
+ if let Some(local_did) = adt_def.did().as_local();
let item = cx.tcx.hir().expect_item(local_did);
let middle_ty_id = item.def_id.to_def_id();
if let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind;
ty::ImplContainer(def_id) => {
let ty = cx.tcx.type_of(def_id);
match ty.kind() {
- ty::Adt(adt, _) => cx.tcx.def_path_str(adt.did),
+ ty::Adt(adt, _) => cx.tcx.def_path_str(adt.did()),
_ => ty.to_string(),
}
},
if_chain! {
if format_args.format_string_parts == [kw::Empty];
if match cx.typeck_results().expr_ty(value).peel_refs().kind() {
- ty::Adt(adt, _) => cx.tcx.is_diagnostic_item(sym::String, adt.did),
+ ty::Adt(adt, _) => cx.tcx.is_diagnostic_item(sym::String, adt.did()),
ty::Str => true,
_ => false,
};
// primitive types are never mutable
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false,
ty::Adt(adt, substs) => {
- tys.insert(adt.did) && !ty.is_freeze(cx.tcx.at(span), cx.param_env)
- || KNOWN_WRAPPER_TYS.iter().any(|path| match_def_path(cx, adt.did, path))
+ tys.insert(adt.did()) && !ty.is_freeze(cx.tcx.at(span), cx.param_env)
+ || KNOWN_WRAPPER_TYS.iter().any(|path| match_def_path(cx, adt.did(), path))
&& substs.types().any(|ty| is_mutable_ty(cx, ty, span, tys))
},
ty::Tuple(substs) => substs.iter().any(|ty| is_mutable_ty(cx, ty, span, tys)),
let ty = cx.typeck_results().expr_ty(expr);
if let Some(adt_def) = ty.ty_adt_def();
if adt_def.is_struct();
- if let Some(variant) = adt_def.variants.iter().next();
+ if let Some(variant) = adt_def.variants().iter().next();
if fields.iter().all(|f| f.is_shorthand);
then {
let mut def_order_map = FxHashMap::default();
if let ItemKind::Enum(ref def, _) = item.kind {
let ty = cx.tcx.type_of(item.def_id);
let adt = ty.ty_adt_def().expect("already checked whether this is an enum");
- if adt.variants.len() <= 1 {
+ if adt.variants().len() <= 1 {
return;
}
let mut variants_size: Vec<VariantInfo> = Vec::new();
- for (i, variant) in adt.variants.iter().enumerate() {
+ for (i, variant) in adt.variants().iter().enumerate() {
let mut fields_size = Vec::new();
for (i, f) in variant.fields.iter().enumerate() {
let ty = cx.tcx.type_of(f.did);
fn parse_len_output<'tcx>(cx: &LateContext<'_>, sig: FnSig<'tcx>) -> Option<LenOutput<'tcx>> {
match *sig.output().kind() {
ty::Int(_) | ty::Uint(_) => Some(LenOutput::Integral),
- ty::Adt(adt, subs) if cx.tcx.is_diagnostic_item(sym::Option, adt.did) => {
- subs.type_at(0).is_integral().then(|| LenOutput::Option(adt.did))
+ ty::Adt(adt, subs) if cx.tcx.is_diagnostic_item(sym::Option, adt.did()) => {
+ subs.type_at(0).is_integral().then(|| LenOutput::Option(adt.did()))
},
- ty::Adt(adt, subs) if cx.tcx.is_diagnostic_item(sym::Result, adt.did) => subs
+ ty::Adt(adt, subs) if cx.tcx.is_diagnostic_item(sym::Result, adt.did()) => subs
.type_at(0)
.is_integral()
- .then(|| LenOutput::Result(adt.did, subs.type_at(1))),
+ .then(|| LenOutput::Result(adt.did(), subs.type_at(1))),
_ => None,
}
}
fn matches_is_empty_output(self, ty: Ty<'_>) -> bool {
match (self, ty.kind()) {
(_, &ty::Bool) => true,
- (Self::Option(id), &ty::Adt(adt, subs)) if id == adt.did => subs.type_at(0).is_bool(),
- (Self::Result(id, err_ty), &ty::Adt(adt, subs)) if id == adt.did => {
+ (Self::Option(id), &ty::Adt(adt, subs)) if id == adt.did() => subs.type_at(0).is_bool(),
+ (Self::Result(id, err_ty), &ty::Adt(adt, subs)) if id == adt.did() => {
subs.type_at(0).is_bool() && subs.type_at(1) == err_ty
},
_ => false,
.any(|item| is_is_empty(cx, item))
}),
ty::Projection(ref proj) => has_is_empty_impl(cx, proj.item_def_id),
- ty::Adt(id, _) => has_is_empty_impl(cx, id.did),
+ ty::Adt(id, _) => has_is_empty_impl(cx, id.did()),
ty::Array(..) | ty::Slice(..) | ty::Str => true,
_ => false,
}
fn get_slice_like_element_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
match ty.kind() {
- ty::Adt(adt, subs) if cx.tcx.is_diagnostic_item(sym::Vec, adt.did) => Some(subs.type_at(0)),
+ ty::Adt(adt, subs) if cx.tcx.is_diagnostic_item(sym::Vec, adt.did()) => Some(subs.type_at(0)),
ty::Ref(_, subty, _) => get_slice_like_element_ty(cx, *subty),
ty::Slice(ty) | ty::Array(ty, _) => Some(*ty),
_ => None,
// Accumulate the variants which should be put in place of the wildcard because they're not
// already covered.
- let has_hidden = adt_def.variants.iter().any(|x| is_hidden(cx, x));
- let mut missing_variants: Vec<_> = adt_def.variants.iter().filter(|x| !is_hidden(cx, x)).collect();
+ let has_hidden = adt_def.variants().iter().any(|x| is_hidden(cx, x));
+ let mut missing_variants: Vec<_> = adt_def.variants().iter().filter(|x| !is_hidden(cx, x)).collect();
let mut path_prefix = CommonPrefixSearcher::None;
for arm in arms {
}
s
} else {
- let mut s = cx.tcx.def_path_str(adt_def.did);
+ let mut s = cx.tcx.def_path_str(adt_def.did());
s.push_str("::");
s
},
if_chain! {
if let Some(adt) = cx.typeck_results().expr_ty(recv).ty_adt_def();
if let Ok(vid) = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM);
- if Some(adt.did) == cx.tcx.parent(vid);
+ if Some(adt.did()) == cx.tcx.parent(vid);
then {} else { return false; }
}
let inner_ty = match recv_ty.kind() {
// `Option<T>` -> `T`
ty::Adt(adt, subst)
- if cx.tcx.is_diagnostic_item(sym::Option, adt.did) && meets_msrv(msrv, &msrvs::OPTION_COPIED) =>
+ if cx.tcx.is_diagnostic_item(sym::Option, adt.did()) && meets_msrv(msrv, &msrvs::OPTION_COPIED) =>
{
subst.type_at(0)
},
if let PatKind::Binding(_, filter_param_id, _, None) = filter_pat.kind;
if let ExprKind::MethodCall(path, [filter_arg], _) = filter_body.value.kind;
if let Some(opt_ty) = cx.typeck_results().expr_ty(filter_arg).ty_adt_def();
- if let Some(is_result) = if cx.tcx.is_diagnostic_item(sym::Option, opt_ty.did) {
+ if let Some(is_result) = if cx.tcx.is_diagnostic_item(sym::Option, opt_ty.did()) {
Some(false)
- } else if cx.tcx.is_diagnostic_item(sym::Result, opt_ty.did) {
+ } else if cx.tcx.is_diagnostic_item(sym::Result, opt_ty.did()) {
Some(true)
} else {
None
let return_type = cx.typeck_results().expr_ty(expr);
let input_type = cx.typeck_results().expr_ty(recv);
let (input_type, ref_count) = peel_mid_ty_refs(input_type);
- if let Some(ty_name) = input_type.ty_adt_def().map(|adt_def| cx.tcx.item_name(adt_def.did));
+ if let Some(ty_name) = input_type.ty_adt_def().map(|adt_def| cx.tcx.item_name(adt_def.did()));
if return_type == input_type;
then {
let mut app = Applicability::MachineApplicable;
}
if let ty::Adt(adt, substs) = ty.kind() {
- match_def_path(cx, adt.did, &paths::COW) && substs.type_at(1).is_str()
+ match_def_path(cx, adt.did(), &paths::COW) && substs.type_at(1).is_str()
} else {
false
}
// lint if caller of `.map().flatten()` is an Option or Result
let caller_type = match cx.typeck_results().expr_ty(recv).kind() {
ty::Adt(adt, _) => {
- if cx.tcx.is_diagnostic_item(sym::Option, adt.did) {
+ if cx.tcx.is_diagnostic_item(sym::Option, adt.did()) {
"Option"
- } else if cx.tcx.is_diagnostic_item(sym::Result, adt.did) {
+ } else if cx.tcx.is_diagnostic_item(sym::Result, adt.did()) {
"Result"
} else {
return;
return if_chain! {
if match_def_path(cx, did, &paths::ITERTOOLS_NEXT_TUPLE);
if let ty::Adt(adt_def, subs) = cx.typeck_results().expr_ty(e).kind();
- if cx.tcx.is_diagnostic_item(sym::Option, adt_def.did);
+ if cx.tcx.is_diagnostic_item(sym::Option, adt_def.did());
if let ty::Tuple(subs) = subs.type_at(0).kind();
if subs.len() == 2;
then {
} else if !found_mapping && !mutates_arg {
let in_ty = cx.typeck_results().node_type(body.params[0].hir_id);
match cx.typeck_results().expr_ty(&body.value).kind() {
- ty::Adt(adt, subst) if cx.tcx.is_diagnostic_item(sym::Option, adt.did) && in_ty == subst.type_at(0) => {
+ ty::Adt(adt, subst) if cx.tcx.is_diagnostic_item(sym::Option, adt.did()) && in_ty == subst.type_at(0) => {
"filter"
},
_ => return,
if let Adt(def, substs) = ty.kind() {
let is_keyed_type = [sym::HashMap, sym::BTreeMap, sym::HashSet, sym::BTreeSet]
.iter()
- .any(|diag_item| cx.tcx.is_diagnostic_item(*diag_item, def.did));
+ .any(|diag_item| cx.tcx.is_diagnostic_item(*diag_item, def.did()));
if is_keyed_type && is_interior_mutable_type(cx, substs.type_at(0), span) {
span_lint(cx, MUTABLE_KEY_TYPE, span, "mutable key type");
}
sym::Arc,
]
.iter()
- .any(|diag_item| cx.tcx.is_diagnostic_item(*diag_item, def.did));
- let is_box = Some(def.did) == cx.tcx.lang_items().owned_box();
+ .any(|diag_item| cx.tcx.is_diagnostic_item(*diag_item, def.did()));
+ let is_box = Some(def.did()) == cx.tcx.lang_items().owned_box();
if is_std_collection || is_box {
// The type is mutable if any of its type parameters are
substs.types().any(|ty| is_interior_mutable_type(cx, ty, span))
// Dereference suggestion
let sugg = |diag: &mut Diagnostic| {
if let ty::Adt(def, ..) = ty.kind() {
- if let Some(span) = cx.tcx.hir().span_if_local(def.did) {
+ if let Some(span) = cx.tcx.hir().span_if_local(def.did()) {
if can_type_implement_copy(cx.tcx, cx.param_env, ty, traits::ObligationCause::dummy_with_span(span)).is_ok() {
diag.span_help(span, "consider marking this type as `Copy`");
}
let ty = cx.typeck_results().expr_ty(expr);
if let ty::Adt(def, _) = ty.kind() {
if fields.len() == def.non_enum_variant().fields.len()
- && !def.variants[0_usize.into()].is_field_list_non_exhaustive()
+ && !def.variant(0_usize.into()).is_field_list_non_exhaustive()
{
span_lint(
cx,
let mut impls = HirIdSet::default();
cx.tcx.for_each_impl(default_trait_id, |d| {
if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() {
- if let Some(local_def_id) = ty_def.did.as_local() {
+ if let Some(local_def_id) = ty_def.did().as_local() {
impls.insert(cx.tcx.hir().local_def_id_to_hir_id(local_def_id));
}
}
if_chain! {
if let Some(ref impling_types) = self.impling_types;
if let Some(self_def) = cx.tcx.type_of(self_def_id).ty_adt_def();
- if let Some(self_local_did) = self_def.did.as_local();
+ if let Some(self_local_did) = self_def.did().as_local();
let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_local_did);
if impling_types.contains(&self_id);
then {
match val.ty().kind() {
// the fact that we have to dig into every structs to search enums
// leads us to the point checking `UnsafeCell` directly is the only option.
- ty::Adt(ty_def, ..) if Some(ty_def.did) == cx.tcx.lang_items().unsafe_cell_type() => true,
+ ty::Adt(ty_def, ..) if Some(ty_def.did()) == cx.tcx.lang_items().unsafe_cell_type() => true,
ty::Array(..) | ty::Adt(..) | ty::Tuple(..) => {
let val = cx.tcx.destructure_const(cx.param_env.and(val));
val.fields.iter().any(|field| inner(cx, *field))
let mut non_send_fields = Vec::new();
let hir_map = cx.tcx.hir();
- for variant in &adt_def.variants {
+ for variant in adt_def.variants() {
for field in &variant.fields {
if_chain! {
if let Some(field_hir_id) = field
return true;
},
ty::Adt(adt_def, _) => {
- if match_def_path(cx, adt_def.did, &paths::PTR_NON_NULL) {
+ if match_def_path(cx, adt_def.did(), &paths::PTR_NON_NULL) {
return true;
}
},
// Check that the name as typed matches the actual name of the type.
// e.g. `fn foo(_: &Foo)` shouldn't trigger the lint when `Foo` is an alias for `Vec`
if let [.., name] = path.segments;
- if cx.tcx.item_name(adt.did) == name.ident.name;
+ if cx.tcx.item_name(adt.did()) == name.ident.name;
if !is_lint_allowed(cx, PTR_ARG, hir_ty.hir_id);
if params.get(i).map_or(true, |p| !is_lint_allowed(cx, PTR_ARG, p.hir_id));
then {
- let (method_renames, deref_ty, deref_impl_id) = match cx.tcx.get_diagnostic_name(adt.did) {
+ let (method_renames, deref_ty, deref_impl_id) = match cx.tcx.get_diagnostic_name(adt.did()) {
Some(sym::Vec) => (
[("clone", ".to_owned()")].as_slice(),
DerefTy::Slice(
return Some(PtrArg {
idx: i,
span: hir_ty.span,
- ty_did: adt.did,
+ ty_did: adt.did(),
ty_name: name.ident.name,
method_renames,
ref_prefix: RefPrefix {
.map(|sig| sig.input(i).skip_binder().peel_refs())
.map_or(true, |ty| match *ty.kind() {
ty::Param(_) => true,
- ty::Adt(def, _) => def.did == args.ty_did,
+ ty::Adt(def, _) => def.did() == args.ty_did,
_ => false,
})
{
// If the types match check for methods which exist on both types. e.g. `Vec::len` and
// `slice::len`
ty::Adt(def, _)
- if def.did == args.ty_did
+ if def.did() == args.ty_did
&& (i != 0
|| self.cx.tcx.trait_of_item(id).is_some()
|| !args.deref_assoc_items.map_or(false, |(id, items)| {
if_chain! {
if let Some(self_def) = self_ty.ty_adt_def();
- if let Some(self_local_did) = self_def.did.as_local();
+ if let Some(self_local_did) = self_def.did().as_local();
let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_local_did);
if let Some(Node::Item(x)) = cx.tcx.hir().find(self_id);
let type_name = x.ident.name.as_str().to_lowercase();
then {
diag.note(&format!(
"two instances of the same generic type (`{}`) may have different layouts",
- cx.tcx.item_name(from_def.did)
+ cx.tcx.item_name(from_def.did())
));
} else {
if from_ty_orig.peel_refs() != from_ty {
ty = sized_ty;
continue;
}
- if def.repr.inhibit_struct_field_reordering_opt() {
+ if def.repr().inhibit_struct_field_reordering_opt() {
ReducedTy::OrderedFields(ty)
} else {
ReducedTy::UnorderedFields(ty)
}
},
- ty::Adt(def, _) if def.is_enum() && (def.variants.is_empty() || is_c_void(cx, ty)) => {
+ ty::Adt(def, _) if def.is_enum() && (def.variants().is_empty() || is_c_void(cx, ty)) => {
ReducedTy::TypeErasure
},
ty::Foreign(_) => ReducedTy::TypeErasure,
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> bool {
match (&from_ty.kind(), &to_ty.kind()) {
(ty::Adt(from_adt, from_substs), ty::Adt(to_adt, to_substs)) => {
- if from_adt.did != to_adt.did {
+ if from_adt.did() != to_adt.did() {
return false;
}
if !matches!(
- cx.tcx.get_diagnostic_name(to_adt.did),
+ cx.tcx.get_diagnostic_name(to_adt.did()),
Some(
sym::BTreeMap
| sym::BTreeSet
fn poll_result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
if_chain! {
if let ty::Adt(def, subst) = ty.kind();
- if match_def_path(cx, def.did, &paths::POLL);
+ if match_def_path(cx, def.did(), &paths::POLL);
let ready_ty = subst.type_at(0);
if let ty::Adt(ready_def, ready_subst) = ready_ty.kind();
- if cx.tcx.is_diagnostic_item(sym::Result, ready_def.did);
+ if cx.tcx.is_diagnostic_item(sym::Result, ready_def.did());
then {
Some(ready_subst.type_at(1))
} else {
fn poll_option_result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
if_chain! {
if let ty::Adt(def, subst) = ty.kind();
- if match_def_path(cx, def.did, &paths::POLL);
+ if match_def_path(cx, def.did(), &paths::POLL);
let ready_ty = subst.type_at(0);
if let ty::Adt(ready_def, ready_subst) = ready_ty.kind();
- if cx.tcx.is_diagnostic_item(sym::Option, ready_def.did);
+ if cx.tcx.is_diagnostic_item(sym::Option, ready_def.did());
let some_ty = ready_subst.type_at(0);
if let ty::Adt(some_def, some_subst) = some_ty.kind();
- if cx.tcx.is_diagnostic_item(sym::Result, some_def.did);
+ if cx.tcx.is_diagnostic_item(sym::Result, some_def.did());
then {
Some(some_subst.type_at(1))
} else {
// Get the wrapper and inner types, if can't, abort.
let (return_type_label, lang_item, inner_type) = if let ty::Adt(adt_def, subst) = return_ty(cx, hir_id).kind() {
- if cx.tcx.is_diagnostic_item(sym::Option, adt_def.did) {
+ if cx.tcx.is_diagnostic_item(sym::Option, adt_def.did()) {
("Option", OptionSome, subst.type_at(0))
- } else if cx.tcx.is_diagnostic_item(sym::Result, adt_def.did) {
+ } else if cx.tcx.is_diagnostic_item(sym::Result, adt_def.did()) {
("Result", ResultOk, subst.type_at(0))
} else {
return;
// than marker traits.
// Due to the limited operations on these types functions should be fairly cheap.
if def
- .variants
+ .variants()
.iter()
.flat_map(|v| v.fields.iter())
.any(|x| matches!(cx.tcx.type_of(x.did).peel_refs().kind(), ty::Param(_)))
pub fn is_diag_item_method(cx: &LateContext<'_>, def_id: DefId, diag_item: Symbol) -> bool {
if let Some(impl_did) = cx.tcx.impl_of_method(def_id) {
if let Some(adt) = cx.tcx.type_of(impl_did).ty_adt_def() {
- return cx.tcx.is_diagnostic_item(diag_item, adt.did);
+ return cx.tcx.is_diagnostic_item(diag_item, adt.did());
}
}
false
if let Some(adt) = cx.tcx.type_of(impl_did).ty_adt_def() {
return std_types_symbols
.iter()
- .any(|&symbol| cx.tcx.is_diagnostic_item(symbol, adt.did));
+ .any(|&symbol| cx.tcx.is_diagnostic_item(symbol, adt.did()));
}
}
}
/// Walks into `ty` and returns `true` if any inner type is an instance of the given adt
/// constructor.
-pub fn contains_adt_constructor(ty: Ty<'_>, adt: &AdtDef) -> bool {
+pub fn contains_adt_constructor(ty: Ty<'_>, adt: AdtDef<'_>) -> bool {
ty.walk().any(|inner| match inner.unpack() {
GenericArgKind::Type(inner_ty) => inner_ty.ty_adt_def() == Some(adt),
GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
let def_id = match ty_to_check.kind() {
ty::Array(..) => return Some(sym::array),
ty::Slice(..) => return Some(sym::slice),
- ty::Adt(adt, _) => adt.did,
+ ty::Adt(adt, _) => adt.did(),
_ => return None,
};
// Returns whether the type has #[must_use] attribute
pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
match ty.kind() {
- ty::Adt(adt, _) => must_use_attr(cx.tcx.get_attrs(adt.did)).is_some(),
+ ty::Adt(adt, _) => must_use_attr(cx.tcx.get_attrs(adt.did())).is_some(),
ty::Foreign(ref did) => must_use_attr(cx.tcx.get_attrs(*did)).is_some(),
ty::Slice(ty) | ty::Array(ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _) => {
// for the Array case we don't need to care for the len == 0 case
let cause = rustc_middle::traits::ObligationCause::dummy();
if infcx.at(&cause, param_env).normalize(ty).is_ok() {
match ty.kind() {
- ty::Adt(def, substs) => def.variants.iter().all(|variant| {
+ ty::Adt(def, substs) => def.variants().iter().all(|variant| {
variant
.fields
.iter()
pub fn is_type_ref_to_diagnostic_item(cx: &LateContext<'_>, ty: Ty<'_>, diag_item: Symbol) -> bool {
match ty.kind() {
ty::Ref(_, ref_ty, _) => match ref_ty.kind() {
- ty::Adt(adt, _) => cx.tcx.is_diagnostic_item(diag_item, adt.did),
+ ty::Adt(adt, _) => cx.tcx.is_diagnostic_item(diag_item, adt.did()),
_ => false,
},
_ => false,
/// [Diagnostic Items]: https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-items.html
pub fn is_type_diagnostic_item(cx: &LateContext<'_>, ty: Ty<'_>, diag_item: Symbol) -> bool {
match ty.kind() {
- ty::Adt(adt, _) => cx.tcx.is_diagnostic_item(diag_item, adt.did),
+ ty::Adt(adt, _) => cx.tcx.is_diagnostic_item(diag_item, adt.did()),
_ => false,
}
}
/// Returns `false` if the `LangItem` is not defined.
pub fn is_type_lang_item(cx: &LateContext<'_>, ty: Ty<'_>, lang_item: hir::LangItem) -> bool {
match ty.kind() {
- ty::Adt(adt, _) => cx.tcx.lang_items().require(lang_item).map_or(false, |li| li == adt.did),
+ ty::Adt(adt, _) => cx.tcx.lang_items().require(lang_item).map_or(false, |li| li == adt.did()),
_ => false,
}
}
/// If you change the signature, remember to update the internal lint `MatchTypeOnDiagItem`
pub fn match_type(cx: &LateContext<'_>, ty: Ty<'_>, path: &[&str]) -> bool {
match ty.kind() {
- ty::Adt(adt, _) => match_def_path(cx, adt.did, path),
+ ty::Adt(adt, _) => match_def_path(cx, adt.did(), path),
_ => false,
}
}
match *ty.kind() {
ty::Array(component, _) => is_uninit_value_valid_for_ty(cx, component),
ty::Tuple(types) => types.iter().all(|ty| is_uninit_value_valid_for_ty(cx, ty)),
- ty::Adt(adt, _) => cx.tcx.lang_items().maybe_uninit() == Some(adt.did),
+ ty::Adt(adt, _) => cx.tcx.lang_items().maybe_uninit() == Some(adt.did()),
_ => false,
}
}
}
/// Gets the value of the given variant.
-pub fn get_discriminant_value(tcx: TyCtxt<'_>, adt: &'_ AdtDef, i: VariantIdx) -> EnumValue {
- let variant = &adt.variants[i];
+pub fn get_discriminant_value(tcx: TyCtxt<'_>, adt: AdtDef<'_>, i: VariantIdx) -> EnumValue {
+ let variant = &adt.variant(i);
match variant.discr {
VariantDiscr::Explicit(id) => read_explicit_enum_value(tcx, id).unwrap(),
- VariantDiscr::Relative(x) => match adt.variants[(i.as_usize() - x as usize).into()].discr {
+ VariantDiscr::Relative(x) => match adt.variant((i.as_usize() - x as usize).into()).discr {
VariantDiscr::Explicit(id) => read_explicit_enum_value(tcx, id).unwrap() + x,
VariantDiscr::Relative(_) => EnumValue::Unsigned(x.into()),
},
/// platform specific `libc::<platform>::c_void` types in libc.
pub fn is_c_void(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
if let ty::Adt(adt, _) = ty.kind()
- && let &[krate, .., name] = &*cx.get_def_path(adt.did)
+ && let &[krate, .., name] = &*cx.get_def_path(adt.did())
&& let sym::libc | sym::core | sym::std = krate
&& name.as_str() == "c_void"
{
-Subproject commit 722475ccc143d2dbf9fad5891207dcb5576e3d17
+Subproject commit a12a48bf723e0e13f043979a7f79861d975e7187