Skip to content

Rollup of 5 pull requests #84620

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 32 commits into from
Apr 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
afaefea
Ignore nonstandard lldb version strings in compiletest
Manishearth Apr 12, 2021
b48699e
`single_component_path_imports`: ignore `pub(crate) use some_macro;` …
cherryblossom000 Apr 22, 2021
5625d58
add detection unused_io_amount of "or", "or_else" and "ok"
ABouttefeux Apr 16, 2021
0ab7acc
Auto merge of #7100 - ABouttefeux:unused_io_amount, r=camsteffen
bors Apr 22, 2021
74f5599
Auto merge of #7120 - cherryblossom000:7106, r=Manishearth
bors Apr 22, 2021
6c42375
Fix lintcheck on windows
Jarcho Apr 22, 2021
08e36d7
Auto merge of #7124 - Jarcho:lintcheck-windows, r=phansch
bors Apr 23, 2021
36e9382
Reuse `unix::path` and `unsupported::{io, thread_local_key}` on `hermit`
CDirkx Apr 24, 2021
db7ad64
Fix ICE checking for feature gated const fn
Jarcho Apr 25, 2021
3f5be5e
Fix cloned_instead_of_copied MSRV
camsteffen Apr 25, 2021
c4e2d36
Auto merge of #7129 - camsteffen:copied-msrv, r=Manishearth
bors Apr 25, 2021
d21fb2b
Update backtrace to 0.3.57
jclulow Apr 23, 2021
efc4c6c
extend `single_element_loop` to match `.iter()`
llogiq Apr 25, 2021
1bb3b12
Auto merge of #7132 - rust-lang:single_element_loop_iter, r=Manishearth
bors Apr 26, 2021
dcf4e07
Finish MSRV for cloned_instead_of_copied
camsteffen Apr 26, 2021
a362a4d
Auto merge of #7134 - camsteffen:copied-msrv, r=Manishearth
bors Apr 26, 2021
84003aa
fix invalid code suggestion in `manual_unwrap_or`, due to macro expan…
mgacek8 Apr 26, 2021
d7627dc
Fix FN in `iter_cloned_collect` with a large array
mgacek8 Apr 26, 2021
33ed8b5
Remove needless_question_mark MSRV
camsteffen Apr 26, 2021
340b570
Refactor MSRV aliases
camsteffen Apr 26, 2021
3a8e759
Update MSRV contribution docs
camsteffen Apr 26, 2021
f33d86d
Auto merge of #7137 - camsteffen:msrv-mod, r=llogiq
bors Apr 26, 2021
0a330e6
Auto merge of #7136 - mgacek8:issue6965_manual_unwrap_or_invalid_sugg…
bors Apr 26, 2021
b3629d2
move `representability` out of `rustc_middle`
lcnr Apr 27, 2021
9af07e6
Auto merge of #7138 - mgacek8:issue6808_iter_cloned_collect_FN_with_l…
bors Apr 27, 2021
7c7683c
Auto merge of #7128 - Jarcho:const_fn_ice, r=flip1995
bors Apr 27, 2021
d4af90e
Merge commit '7c7683c8efe447b251d6c5ca6cce51233060f6e8' into clippyup
flip1995 Apr 27, 2021
78e0f2f
Rollup merge of #84132 - Manishearth:lldb-nonstandard, r=Mark-Simulacrum
Dylan-DPC Apr 27, 2021
e7be5dd
Rollup merge of #84521 - CDirkx:hermit-dedup, r=Mark-Simulacrum
Dylan-DPC Apr 27, 2021
7969de2
Rollup merge of #84563 - jclulow:backtrace-upgrade, r=Mark-Simulacrum
Dylan-DPC Apr 27, 2021
38e0dbd
Rollup merge of #84610 - flip1995:clippyup, r=Manishearth,flip1995
Dylan-DPC Apr 27, 2021
24782c7
Rollup merge of #84613 - lcnr:recursive-types, r=jackh726
Dylan-DPC Apr 27, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4590,6 +4590,7 @@ dependencies = [
"rustc_span",
"rustc_target",
"rustc_trait_selection",
"rustc_ty_utils",
"smallvec",
"tracing",
]
Expand Down
191 changes: 2 additions & 189 deletions compiler/rustc_middle/src/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_macros::HashStable;
use rustc_span::{Span, DUMMY_SP};
use rustc_span::DUMMY_SP;
use rustc_target::abi::{Integer, Size, TargetDataLayout};
use smallvec::SmallVec;
use std::{cmp, fmt, iter};
use std::{fmt, iter};

#[derive(Copy, Clone, Debug)]
pub struct Discr<'tcx> {
Expand Down Expand Up @@ -135,21 +135,6 @@ impl IntTypeExt for attr::IntType {
}
}

/// Describes whether a type is representable. For types that are not
/// representable, 'SelfRecursive' and 'ContainsRecursive' are used to
/// distinguish between types that are recursive with themselves and types that
/// contain a different recursive type. These cases can therefore be treated
/// differently when reporting errors.
///
/// The ordering of the cases is significant. They are sorted so that cmp::max
/// will keep the "more erroneous" of two values.
#[derive(Clone, PartialOrd, Ord, Eq, PartialEq, Debug)]
pub enum Representability {
Representable,
ContainsRecursive,
SelfRecursive(Vec<Span>),
}

impl<'tcx> TyCtxt<'tcx> {
/// Creates a hash of the type `Ty` which will be the same no matter what crate
/// context it's calculated within. This is used by the `type_id` intrinsic.
Expand Down Expand Up @@ -870,178 +855,6 @@ impl<'tcx> ty::TyS<'tcx> {
}
}

/// Check whether a type is representable. This means it cannot contain unboxed
/// structural recursion. This check is needed for structs and enums.
pub fn is_representable(&'tcx self, tcx: TyCtxt<'tcx>, sp: Span) -> Representability {
// Iterate until something non-representable is found
fn fold_repr<It: Iterator<Item = Representability>>(iter: It) -> Representability {
iter.fold(Representability::Representable, |r1, r2| match (r1, r2) {
(Representability::SelfRecursive(v1), Representability::SelfRecursive(v2)) => {
Representability::SelfRecursive(v1.into_iter().chain(v2).collect())
}
(r1, r2) => cmp::max(r1, r2),
})
}

fn are_inner_types_recursive<'tcx>(
tcx: TyCtxt<'tcx>,
sp: Span,
seen: &mut Vec<Ty<'tcx>>,
representable_cache: &mut FxHashMap<Ty<'tcx>, Representability>,
ty: Ty<'tcx>,
) -> Representability {
match ty.kind() {
Tuple(..) => {
// Find non representable
fold_repr(ty.tuple_fields().map(|ty| {
is_type_structurally_recursive(tcx, sp, seen, representable_cache, ty)
}))
}
// Fixed-length vectors.
// FIXME(#11924) Behavior undecided for zero-length vectors.
Array(ty, _) => {
is_type_structurally_recursive(tcx, sp, seen, representable_cache, ty)
}
Adt(def, substs) => {
// Find non representable fields with their spans
fold_repr(def.all_fields().map(|field| {
let ty = field.ty(tcx, substs);
let span = match field
.did
.as_local()
.map(|id| tcx.hir().local_def_id_to_hir_id(id))
.and_then(|id| tcx.hir().find(id))
{
Some(hir::Node::Field(field)) => field.ty.span,
_ => sp,
};
match is_type_structurally_recursive(
tcx,
span,
seen,
representable_cache,
ty,
) {
Representability::SelfRecursive(_) => {
Representability::SelfRecursive(vec![span])
}
x => x,
}
}))
}
Closure(..) => {
// this check is run on type definitions, so we don't expect
// to see closure types
bug!("requires check invoked on inapplicable type: {:?}", ty)
}
_ => Representability::Representable,
}
}

fn same_struct_or_enum<'tcx>(ty: Ty<'tcx>, def: &'tcx ty::AdtDef) -> bool {
match *ty.kind() {
Adt(ty_def, _) => ty_def == def,
_ => false,
}
}

// Does the type `ty` directly (without indirection through a pointer)
// contain any types on stack `seen`?
fn is_type_structurally_recursive<'tcx>(
tcx: TyCtxt<'tcx>,
sp: Span,
seen: &mut Vec<Ty<'tcx>>,
representable_cache: &mut FxHashMap<Ty<'tcx>, Representability>,
ty: Ty<'tcx>,
) -> Representability {
debug!("is_type_structurally_recursive: {:?} {:?}", ty, sp);
if let Some(representability) = representable_cache.get(ty) {
debug!(
"is_type_structurally_recursive: {:?} {:?} - (cached) {:?}",
ty, sp, representability
);
return representability.clone();
}

let representability =
is_type_structurally_recursive_inner(tcx, sp, seen, representable_cache, ty);

representable_cache.insert(ty, representability.clone());
representability
}

fn is_type_structurally_recursive_inner<'tcx>(
tcx: TyCtxt<'tcx>,
sp: Span,
seen: &mut Vec<Ty<'tcx>>,
representable_cache: &mut FxHashMap<Ty<'tcx>, Representability>,
ty: Ty<'tcx>,
) -> Representability {
match ty.kind() {
Adt(def, _) => {
{
// Iterate through stack of previously seen types.
let mut iter = seen.iter();

// The first item in `seen` is the type we are actually curious about.
// We want to return SelfRecursive if this type contains itself.
// It is important that we DON'T take generic parameters into account
// for this check, so that Bar<T> in this example counts as SelfRecursive:
//
// struct Foo;
// struct Bar<T> { x: Bar<Foo> }

if let Some(&seen_type) = iter.next() {
if same_struct_or_enum(seen_type, *def) {
debug!("SelfRecursive: {:?} contains {:?}", seen_type, ty);
return Representability::SelfRecursive(vec![sp]);
}
}

// We also need to know whether the first item contains other types
// that are structurally recursive. If we don't catch this case, we
// will recurse infinitely for some inputs.
//
// It is important that we DO take generic parameters into account
// here, so that code like this is considered SelfRecursive, not
// ContainsRecursive:
//
// struct Foo { Option<Option<Foo>> }

for &seen_type in iter {
if ty::TyS::same_type(ty, seen_type) {
debug!("ContainsRecursive: {:?} contains {:?}", seen_type, ty);
return Representability::ContainsRecursive;
}
}
}

// For structs and enums, track all previously seen types by pushing them
// onto the 'seen' stack.
seen.push(ty);
let out = are_inner_types_recursive(tcx, sp, seen, representable_cache, ty);
seen.pop();
out
}
_ => {
// No need to push in other cases.
are_inner_types_recursive(tcx, sp, seen, representable_cache, ty)
}
}
}

debug!("is_type_representable: {:?}", self);

// To avoid a stack overflow when checking an enum variant or struct that
// contains a different, structurally recursive type, maintain a stack
// of seen types and check recursion for each of them (issues #3008, #3779).
let mut seen: Vec<Ty<'_>> = Vec::new();
let mut representable_cache = FxHashMap::default();
let r = is_type_structurally_recursive(tcx, sp, &mut seen, &mut representable_cache, self);
debug!("is_type_representable: {:?} is {:?}", self, r);
r
}

/// Peel off all reference types in this type until there are none left.
///
/// This method is idempotent, i.e. `ty.peel_refs().peel_refs() == ty.peel_refs()`.
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_ty_utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use rustc_middle::ty::query::Providers;
mod common_traits;
pub mod instance;
mod needs_drop;
pub mod representability;
mod ty;

pub fn provide(providers: &mut Providers) {
Expand Down
Loading