Skip to content

Commit 83ebb00

Browse files
committed
Auto merge of rust-lang#84620 - Dylan-DPC:rollup-wkv97im, r=Dylan-DPC
Rollup of 5 pull requests Successful merges: - rust-lang#84132 (Ignore nonstandard lldb version strings in compiletest) - rust-lang#84521 (Reuse modules on `hermit`) - rust-lang#84563 (Update backtrace to 0.3.57) - rust-lang#84610 (Update Clippy) - rust-lang#84613 (move representability checks to rustc_ty_utils) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 1919b3f + 24782c7 commit 83ebb00

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+615
-611
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -4590,6 +4590,7 @@ dependencies = [
45904590
"rustc_span",
45914591
"rustc_target",
45924592
"rustc_trait_selection",
4593+
"rustc_ty_utils",
45934594
"smallvec",
45944595
"tracing",
45954596
]

compiler/rustc_middle/src/ty/util.rs

+2-189
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ use rustc_hir as hir;
1818
use rustc_hir::def::DefKind;
1919
use rustc_hir::def_id::DefId;
2020
use rustc_macros::HashStable;
21-
use rustc_span::{Span, DUMMY_SP};
21+
use rustc_span::DUMMY_SP;
2222
use rustc_target::abi::{Integer, Size, TargetDataLayout};
2323
use smallvec::SmallVec;
24-
use std::{cmp, fmt, iter};
24+
use std::{fmt, iter};
2525

2626
#[derive(Copy, Clone, Debug)]
2727
pub struct Discr<'tcx> {
@@ -135,21 +135,6 @@ impl IntTypeExt for attr::IntType {
135135
}
136136
}
137137

138-
/// Describes whether a type is representable. For types that are not
139-
/// representable, 'SelfRecursive' and 'ContainsRecursive' are used to
140-
/// distinguish between types that are recursive with themselves and types that
141-
/// contain a different recursive type. These cases can therefore be treated
142-
/// differently when reporting errors.
143-
///
144-
/// The ordering of the cases is significant. They are sorted so that cmp::max
145-
/// will keep the "more erroneous" of two values.
146-
#[derive(Clone, PartialOrd, Ord, Eq, PartialEq, Debug)]
147-
pub enum Representability {
148-
Representable,
149-
ContainsRecursive,
150-
SelfRecursive(Vec<Span>),
151-
}
152-
153138
impl<'tcx> TyCtxt<'tcx> {
154139
/// Creates a hash of the type `Ty` which will be the same no matter what crate
155140
/// context it's calculated within. This is used by the `type_id` intrinsic.
@@ -870,178 +855,6 @@ impl<'tcx> ty::TyS<'tcx> {
870855
}
871856
}
872857

873-
/// Check whether a type is representable. This means it cannot contain unboxed
874-
/// structural recursion. This check is needed for structs and enums.
875-
pub fn is_representable(&'tcx self, tcx: TyCtxt<'tcx>, sp: Span) -> Representability {
876-
// Iterate until something non-representable is found
877-
fn fold_repr<It: Iterator<Item = Representability>>(iter: It) -> Representability {
878-
iter.fold(Representability::Representable, |r1, r2| match (r1, r2) {
879-
(Representability::SelfRecursive(v1), Representability::SelfRecursive(v2)) => {
880-
Representability::SelfRecursive(v1.into_iter().chain(v2).collect())
881-
}
882-
(r1, r2) => cmp::max(r1, r2),
883-
})
884-
}
885-
886-
fn are_inner_types_recursive<'tcx>(
887-
tcx: TyCtxt<'tcx>,
888-
sp: Span,
889-
seen: &mut Vec<Ty<'tcx>>,
890-
representable_cache: &mut FxHashMap<Ty<'tcx>, Representability>,
891-
ty: Ty<'tcx>,
892-
) -> Representability {
893-
match ty.kind() {
894-
Tuple(..) => {
895-
// Find non representable
896-
fold_repr(ty.tuple_fields().map(|ty| {
897-
is_type_structurally_recursive(tcx, sp, seen, representable_cache, ty)
898-
}))
899-
}
900-
// Fixed-length vectors.
901-
// FIXME(#11924) Behavior undecided for zero-length vectors.
902-
Array(ty, _) => {
903-
is_type_structurally_recursive(tcx, sp, seen, representable_cache, ty)
904-
}
905-
Adt(def, substs) => {
906-
// Find non representable fields with their spans
907-
fold_repr(def.all_fields().map(|field| {
908-
let ty = field.ty(tcx, substs);
909-
let span = match field
910-
.did
911-
.as_local()
912-
.map(|id| tcx.hir().local_def_id_to_hir_id(id))
913-
.and_then(|id| tcx.hir().find(id))
914-
{
915-
Some(hir::Node::Field(field)) => field.ty.span,
916-
_ => sp,
917-
};
918-
match is_type_structurally_recursive(
919-
tcx,
920-
span,
921-
seen,
922-
representable_cache,
923-
ty,
924-
) {
925-
Representability::SelfRecursive(_) => {
926-
Representability::SelfRecursive(vec![span])
927-
}
928-
x => x,
929-
}
930-
}))
931-
}
932-
Closure(..) => {
933-
// this check is run on type definitions, so we don't expect
934-
// to see closure types
935-
bug!("requires check invoked on inapplicable type: {:?}", ty)
936-
}
937-
_ => Representability::Representable,
938-
}
939-
}
940-
941-
fn same_struct_or_enum<'tcx>(ty: Ty<'tcx>, def: &'tcx ty::AdtDef) -> bool {
942-
match *ty.kind() {
943-
Adt(ty_def, _) => ty_def == def,
944-
_ => false,
945-
}
946-
}
947-
948-
// Does the type `ty` directly (without indirection through a pointer)
949-
// contain any types on stack `seen`?
950-
fn is_type_structurally_recursive<'tcx>(
951-
tcx: TyCtxt<'tcx>,
952-
sp: Span,
953-
seen: &mut Vec<Ty<'tcx>>,
954-
representable_cache: &mut FxHashMap<Ty<'tcx>, Representability>,
955-
ty: Ty<'tcx>,
956-
) -> Representability {
957-
debug!("is_type_structurally_recursive: {:?} {:?}", ty, sp);
958-
if let Some(representability) = representable_cache.get(ty) {
959-
debug!(
960-
"is_type_structurally_recursive: {:?} {:?} - (cached) {:?}",
961-
ty, sp, representability
962-
);
963-
return representability.clone();
964-
}
965-
966-
let representability =
967-
is_type_structurally_recursive_inner(tcx, sp, seen, representable_cache, ty);
968-
969-
representable_cache.insert(ty, representability.clone());
970-
representability
971-
}
972-
973-
fn is_type_structurally_recursive_inner<'tcx>(
974-
tcx: TyCtxt<'tcx>,
975-
sp: Span,
976-
seen: &mut Vec<Ty<'tcx>>,
977-
representable_cache: &mut FxHashMap<Ty<'tcx>, Representability>,
978-
ty: Ty<'tcx>,
979-
) -> Representability {
980-
match ty.kind() {
981-
Adt(def, _) => {
982-
{
983-
// Iterate through stack of previously seen types.
984-
let mut iter = seen.iter();
985-
986-
// The first item in `seen` is the type we are actually curious about.
987-
// We want to return SelfRecursive if this type contains itself.
988-
// It is important that we DON'T take generic parameters into account
989-
// for this check, so that Bar<T> in this example counts as SelfRecursive:
990-
//
991-
// struct Foo;
992-
// struct Bar<T> { x: Bar<Foo> }
993-
994-
if let Some(&seen_type) = iter.next() {
995-
if same_struct_or_enum(seen_type, *def) {
996-
debug!("SelfRecursive: {:?} contains {:?}", seen_type, ty);
997-
return Representability::SelfRecursive(vec![sp]);
998-
}
999-
}
1000-
1001-
// We also need to know whether the first item contains other types
1002-
// that are structurally recursive. If we don't catch this case, we
1003-
// will recurse infinitely for some inputs.
1004-
//
1005-
// It is important that we DO take generic parameters into account
1006-
// here, so that code like this is considered SelfRecursive, not
1007-
// ContainsRecursive:
1008-
//
1009-
// struct Foo { Option<Option<Foo>> }
1010-
1011-
for &seen_type in iter {
1012-
if ty::TyS::same_type(ty, seen_type) {
1013-
debug!("ContainsRecursive: {:?} contains {:?}", seen_type, ty);
1014-
return Representability::ContainsRecursive;
1015-
}
1016-
}
1017-
}
1018-
1019-
// For structs and enums, track all previously seen types by pushing them
1020-
// onto the 'seen' stack.
1021-
seen.push(ty);
1022-
let out = are_inner_types_recursive(tcx, sp, seen, representable_cache, ty);
1023-
seen.pop();
1024-
out
1025-
}
1026-
_ => {
1027-
// No need to push in other cases.
1028-
are_inner_types_recursive(tcx, sp, seen, representable_cache, ty)
1029-
}
1030-
}
1031-
}
1032-
1033-
debug!("is_type_representable: {:?}", self);
1034-
1035-
// To avoid a stack overflow when checking an enum variant or struct that
1036-
// contains a different, structurally recursive type, maintain a stack
1037-
// of seen types and check recursion for each of them (issues #3008, #3779).
1038-
let mut seen: Vec<Ty<'_>> = Vec::new();
1039-
let mut representable_cache = FxHashMap::default();
1040-
let r = is_type_structurally_recursive(tcx, sp, &mut seen, &mut representable_cache, self);
1041-
debug!("is_type_representable: {:?} is {:?}", self, r);
1042-
r
1043-
}
1044-
1045858
/// Peel off all reference types in this type until there are none left.
1046859
///
1047860
/// This method is idempotent, i.e. `ty.peel_refs().peel_refs() == ty.peel_refs()`.

compiler/rustc_ty_utils/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use rustc_middle::ty::query::Providers;
2020
mod common_traits;
2121
pub mod instance;
2222
mod needs_drop;
23+
pub mod representability;
2324
mod ty;
2425

2526
pub fn provide(providers: &mut Providers) {

0 commit comments

Comments
 (0)