Improve AdtDef
interning.
This commit makes `AdtDef` use `Interned`. Much the commit is tedious changes to introduce getter functions. The interesting changes are in `compiler/rustc_middle/src/ty/adt.rs`.
This commit is contained in:
parent
5f4e067719
commit
ca5525d564
169 changed files with 702 additions and 687 deletions
|
@ -658,7 +658,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
|
|||
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,
|
||||
};
|
||||
|
@ -841,7 +841,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
@ -2535,9 +2535,9 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
|
|||
|
||||
/// 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
|
||||
}
|
||||
|
||||
|
@ -2571,7 +2571,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
|
|||
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.)
|
||||
|
@ -2592,12 +2592,12 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
|
|||
_ => {}
|
||||
}
|
||||
// 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)| {
|
||||
|
@ -2622,8 +2622,8 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
|
|||
}
|
||||
// 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),
|
||||
|
@ -2819,15 +2819,15 @@ impl ClashingExternDeclarations {
|
|||
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",
|
||||
|
@ -2892,8 +2892,8 @@ impl ClashingExternDeclarations {
|
|||
}
|
||||
|
||||
// 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(
|
||||
|
|
|
@ -1050,7 +1050,7 @@ impl<'tcx> LateContext<'tcx> {
|
|||
) -> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -202,7 +202,7 @@ fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, ty: &Ty<'_>) -> Option<String> {
|
|||
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>`
|
||||
|
|
|
@ -84,9 +84,9 @@ fn lint_cstring_as_ptr(
|
|||
) {
|
||||
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`");
|
||||
|
|
|
@ -149,7 +149,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
|
|||
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| {
|
||||
|
|
|
@ -57,8 +57,8 @@ fn path_for_pass_by_value(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Option<Stri
|
|||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -667,8 +667,8 @@ enum FfiResult<'tcx> {
|
|||
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
|
||||
|
@ -692,8 +692,8 @@ fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: CItemKi
|
|||
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;
|
||||
|
@ -701,11 +701,11 @@ fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: CItemKi
|
|||
|
||||
// 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))
|
||||
|
@ -721,8 +721,10 @@ fn get_nullable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'t
|
|||
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,
|
||||
|
@ -771,7 +773,7 @@ crate fn repr_nullable_ptr<'tcx>(
|
|||
) -> 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,
|
||||
|
@ -845,13 +847,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
&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) {
|
||||
|
@ -925,7 +927,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
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),
|
||||
|
@ -939,7 +941,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
|
||||
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),
|
||||
|
@ -958,14 +960,15 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
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 {
|
||||
|
@ -981,7 +984,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
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(),
|
||||
|
@ -990,7 +993,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
}
|
||||
|
||||
// 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 {
|
||||
|
@ -1161,7 +1164,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
}
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
@ -1464,9 +1467,9 @@ impl InvalidAtomicOrdering {
|
|||
&& 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));
|
||||
}
|
||||
|
|
|
@ -202,7 +202,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
|||
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) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue