Re-implement a type-size based limit

This commit is contained in:
Michael Goulet 2024-05-24 14:09:40 -04:00
parent 9dc129ae82
commit 0f7f3f4045
25 changed files with 206 additions and 160 deletions

View File

@ -41,6 +41,9 @@ middle_cannot_be_normalized =
middle_conflict_types =
this expression supplies two conflicting concrete types for the same opaque type
middle_consider_type_length_limit =
consider adding a `#![type_length_limit="{$type_length}"]` attribute to your crate
middle_const_eval_non_int =
constant evaluation of enum discriminant resulted in non-integer
@ -94,8 +97,11 @@ middle_strict_coherence_needs_negative_coherence =
to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled
.label = due to this attribute
middle_type_length_limit = reached the type-length limit while instantiating `{$shrunk}`
middle_unknown_layout =
the type `{$ty}` has an unknown layout
middle_values_too_big =
values of the type `{$ty}` are too big for the current architecture
middle_written_to_path = the full type name has been written to '{$path}'

View File

@ -1,4 +1,5 @@
use std::fmt;
use std::path::PathBuf;
use rustc_errors::{codes::*, DiagArgName, DiagArgValue, DiagMessage};
use rustc_macros::{Diagnostic, Subdiagnostic};
@ -149,3 +150,16 @@ pub struct ErroneousConstant {
/// Used by `rustc_const_eval`
pub use crate::fluent_generated::middle_adjust_for_foreign_abi_error;
#[derive(Diagnostic)]
#[diag(middle_type_length_limit)]
#[help(middle_consider_type_length_limit)]
pub struct TypeLengthLimit {
#[primary_span]
pub span: Span,
pub shrunk: String,
#[note(middle_written_to_path)]
pub was_written: Option<()>,
pub path: PathBuf,
pub type_length: usize,
}

View File

@ -30,7 +30,7 @@ pub fn provide(providers: &mut Providers) {
tcx.hir().krate_attrs(),
tcx.sess,
sym::type_length_limit,
1048576,
2usize.pow(24),
),
}
}

View File

@ -1,23 +1,25 @@
use crate::error;
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::ty::print::{FmtPrinter, Printer};
use crate::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable};
use crate::ty::{EarlyBinder, GenericArgs, GenericArgsRef, TypeVisitableExt};
use crate::ty::print::{shrunk_instance_name, FmtPrinter, Printer};
use crate::ty::{
self, EarlyBinder, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
};
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def::Namespace;
use rustc_hir::def_id::{CrateNum, DefId};
use rustc_hir::lang_items::LangItem;
use rustc_index::bit_set::FiniteBitSet;
use rustc_macros::{
Decodable, Encodable, HashStable, Lift, TyDecodable, TyEncodable, TypeVisitable,
};
use rustc_macros::{Decodable, Encodable, HashStable, Lift, TyDecodable, TyEncodable};
use rustc_middle::ty::normalize_erasing_regions::NormalizationError;
use rustc_span::def_id::LOCAL_CRATE;
use rustc_span::{Span, Symbol};
use rustc_span::{Span, Symbol, DUMMY_SP};
use tracing::{debug, instrument};
use std::assert_matches::assert_matches;
use std::fmt;
use std::path::PathBuf;
/// An `InstanceKind` along with the args that are needed to substitute the instance.
///
@ -385,7 +387,28 @@ impl<'tcx> InstanceKind<'tcx> {
}
}
fn fmt_instance(
fn type_length<'tcx>(item: impl TypeVisitable<TyCtxt<'tcx>>) -> usize {
struct Visitor {
type_length: usize,
}
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Visitor {
fn visit_ty(&mut self, t: Ty<'tcx>) {
self.type_length += 1;
t.super_visit_with(self);
}
fn visit_const(&mut self, ct: ty::Const<'tcx>) {
self.type_length += 1;
ct.super_visit_with(self);
}
}
let mut visitor = Visitor { type_length: 0 };
item.visit_with(&mut visitor);
visitor.type_length
}
pub fn fmt_instance(
f: &mut fmt::Formatter<'_>,
instance: Instance<'_>,
type_length: Option<rustc_session::Limit>,
@ -485,7 +508,8 @@ impl<'tcx> Instance<'tcx> {
///
/// Presuming that coherence and type-check have succeeded, if this method is invoked
/// in a monomorphic context (i.e., like during codegen), then it is guaranteed to return
/// `Ok(Some(instance))`.
/// `Ok(Some(instance))`, **except** for when the instance's inputs hit the type size limit,
/// in which case it may bail out and return `Ok(None)`.
///
/// Returns `Err(ErrorGuaranteed)` when the `Instance` resolution process
/// couldn't complete due to errors elsewhere - this is distinct
@ -498,6 +522,16 @@ impl<'tcx> Instance<'tcx> {
def_id: DefId,
args: GenericArgsRef<'tcx>,
) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
// Rust code can easily create exponentially-long types using only a
// polynomial recursion depth. Even with the default recursion
// depth, you can easily get cases that take >2^60 steps to run,
// which means that rustc basically hangs.
//
// Bail out in these cases to avoid that bad user experience.
if !tcx.type_length_limit().value_within_limit(type_length(args)) {
return Ok(None);
}
// All regions in the result of this query are erased, so it's
// fine to erase all of the input regions.
@ -517,6 +551,36 @@ impl<'tcx> Instance<'tcx> {
) -> Instance<'tcx> {
match ty::Instance::resolve(tcx, param_env, def_id, args) {
Ok(Some(instance)) => instance,
Ok(None) => {
let type_length = type_length(args);
if !tcx.type_length_limit().value_within_limit(type_length) {
let (shrunk, written_to_path) =
shrunk_instance_name(tcx, Instance::new(def_id, args));
let mut path = PathBuf::new();
let was_written = if let Some(path2) = written_to_path {
path = path2;
Some(())
} else {
None
};
tcx.dcx().emit_fatal(error::TypeLengthLimit {
// We don't use `def_span(def_id)` so that diagnostics point
// to the crate root during mono instead of to foreign items.
// This is arguably better.
span: span.unwrap_or(DUMMY_SP),
shrunk,
was_written,
path,
type_length,
});
} else {
span_bug!(
span.unwrap_or(tcx.def_span(def_id)),
"failed to resolve instance for {}",
tcx.def_path_str_with_args(def_id, args)
)
}
}
instance => span_bug!(
span.unwrap_or(tcx.def_span(def_id)),
"failed to resolve instance for {}: {instance:#?}",

View File

@ -1,5 +1,7 @@
use std::path::PathBuf;
use crate::ty::GenericArg;
use crate::ty::{self, Ty, TyCtxt};
use crate::ty::{self, ShortInstance, Ty, TyCtxt};
use hir::def::Namespace;
use rustc_data_structures::fx::FxHashSet;
@ -356,3 +358,31 @@ where
with_no_trimmed_paths!(Self::print(t, fmt))
}
}
/// Format instance name that is already known to be too long for rustc.
/// Show only the first 2 types if it is longer than 32 characters to avoid blasting
/// the user's terminal with thousands of lines of type-name.
///
/// If the type name is longer than before+after, it will be written to a file.
pub fn shrunk_instance_name<'tcx>(
tcx: TyCtxt<'tcx>,
instance: ty::Instance<'tcx>,
) -> (String, Option<PathBuf>) {
let s = instance.to_string();
// Only use the shrunk version if it's really shorter.
// This also avoids the case where before and after slices overlap.
if s.chars().nth(33).is_some() {
let shrunk = format!("{}", ShortInstance(instance, 4));
if shrunk == s {
return (s, None);
}
let path = tcx.output_filenames(()).temp_path_ext("long-type.txt", None);
let written_to_path = std::fs::write(&path, s).ok().map(|_| path);
(shrunk, written_to_path)
} else {
(s, None)
}
}

View File

@ -1,6 +1,3 @@
monomorphize_consider_type_length_limit =
consider adding a `#![type_length_limit="{$type_length}"]` attribute to your crate
monomorphize_couldnt_dump_mono_stats =
unexpected error occurred while dumping monomorphization stats: {$error}
@ -25,8 +22,6 @@ monomorphize_start_not_found = using `fn main` requires the standard library
monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined
monomorphize_type_length_limit = reached the type-length limit while instantiating `{$shrunk}`
monomorphize_unknown_cgu_collection_mode =
unknown codegen-item collection mode '{$mode}', falling back to 'lazy' mode

View File

@ -222,12 +222,12 @@ use rustc_middle::mir::{self, Location, MentionedItem};
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCoercion};
use rustc_middle::ty::layout::ValidityRequirement;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::print::{shrunk_instance_name, with_no_trimmed_paths};
use rustc_middle::ty::GenericArgs;
use rustc_middle::ty::{
self, AssocKind, GenericParamDefKind, Instance, InstanceKind, Ty, TyCtxt, TypeFoldable,
TypeVisitableExt, VtblEntry,
};
use rustc_middle::ty::{GenericArgKind, GenericArgs};
use rustc_middle::{bug, span_bug};
use rustc_session::config::EntryFnType;
use rustc_session::Limit;
@ -238,9 +238,7 @@ use rustc_target::abi::Size;
use std::path::PathBuf;
use tracing::{debug, instrument, trace};
use crate::errors::{
self, EncounteredErrorWhileInstantiating, NoOptimizedMir, RecursionLimit, TypeLengthLimit,
};
use crate::errors::{self, EncounteredErrorWhileInstantiating, NoOptimizedMir, RecursionLimit};
use move_check::MoveCheckState;
#[derive(PartialEq)]
@ -443,7 +441,6 @@ fn collect_items_rec<'tcx>(
recursion_depths,
recursion_limit,
));
check_type_length_limit(tcx, instance);
rustc_data_structures::stack::ensure_sufficient_stack(|| {
collect_items_of_instance(
@ -554,34 +551,6 @@ fn collect_items_rec<'tcx>(
}
}
/// Format instance name that is already known to be too long for rustc.
/// Show only the first 2 types if it is longer than 32 characters to avoid blasting
/// the user's terminal with thousands of lines of type-name.
///
/// If the type name is longer than before+after, it will be written to a file.
fn shrunk_instance_name<'tcx>(
tcx: TyCtxt<'tcx>,
instance: Instance<'tcx>,
) -> (String, Option<PathBuf>) {
let s = instance.to_string();
// Only use the shrunk version if it's really shorter.
// This also avoids the case where before and after slices overlap.
if s.chars().nth(33).is_some() {
let shrunk = format!("{}", ty::ShortInstance(instance, 4));
if shrunk == s {
return (s, None);
}
let path = tcx.output_filenames(()).temp_path_ext("long-type.txt", None);
let written_to_path = std::fs::write(&path, s).ok().map(|_| path);
(shrunk, written_to_path)
} else {
(s, None)
}
}
fn check_recursion_limit<'tcx>(
tcx: TyCtxt<'tcx>,
instance: Instance<'tcx>,
@ -630,38 +599,6 @@ fn check_recursion_limit<'tcx>(
(def_id, recursion_depth)
}
fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
let type_length = instance
.args
.iter()
.flat_map(|arg| arg.walk())
.filter(|arg| match arg.unpack() {
GenericArgKind::Type(_) | GenericArgKind::Const(_) => true,
GenericArgKind::Lifetime(_) => false,
})
.count();
debug!(" => type length={}", type_length);
// Rust code can easily create exponentially-long types using only a
// polynomial recursion depth. Even with the default recursion
// depth, you can easily get cases that take >2^60 steps to run,
// which means that rustc basically hangs.
//
// Bail out in these cases to avoid that bad user experience.
if !tcx.type_length_limit().value_within_limit(type_length) {
let (shrunk, written_to_path) = shrunk_instance_name(tcx, instance);
let span = tcx.def_span(instance.def_id());
let mut path = PathBuf::new();
let was_written = if let Some(path2) = written_to_path {
path = path2;
Some(())
} else {
None
};
tcx.dcx().emit_fatal(TypeLengthLimit { span, shrunk, was_written, path, type_length });
}
}
struct MirUsedCollector<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
body: &'a mir::Body<'tcx>,

View File

@ -19,19 +19,6 @@ pub struct RecursionLimit {
pub path: PathBuf,
}
#[derive(Diagnostic)]
#[diag(monomorphize_type_length_limit)]
#[help(monomorphize_consider_type_length_limit)]
pub struct TypeLengthLimit {
#[primary_span]
pub span: Span,
pub shrunk: String,
#[note(monomorphize_written_to_path)]
pub was_written: Option<()>,
pub path: PathBuf,
pub type_length: usize,
}
#[derive(Diagnostic)]
#[diag(monomorphize_no_optimized_mir)]
pub struct NoOptimizedMir {

View File

@ -1,5 +1,4 @@
//@ build-pass
//@ ignore-compare-mode-next-solver (hangs)
//@ build-fail
// Closures include captured types twice in a type tree.
//
@ -46,6 +45,7 @@ fn main() {
let f = dup(f);
let f = dup(f);
//~^ ERROR reached the type-length limit
let f = dup(f);
let f = dup(f);
let f = dup(f);

View File

@ -0,0 +1,10 @@
error: reached the type-length limit while instantiating `dup::<{closure@$DIR/issue-72408-nested-closures-exponential.rs:13:5: 13:13}>`
--> $DIR/issue-72408-nested-closures-exponential.rs:47:13
|
LL | let f = dup(f);
| ^^^^^^
|
= help: consider adding a `#![type_length_limit="29360121"]` attribute to your crate
error: aborting due to 1 previous error

View File

@ -1,5 +1,4 @@
//@ build-fail
//~^ ERROR overflow evaluating the requirement
#![recursion_limit = "32"]

View File

@ -1,11 +1,8 @@
error[E0275]: overflow evaluating the requirement `{closure@$DIR/overflow-during-mono.rs:13:41: 13:44}: Sized`
error: reached the type-length limit while instantiating `<Filter<Filter<std::array::IntoIter<i32, 11>, {closure@$DIR/overflow-during-mono.rs:12:41: 12:44}>, ...> as Iterator>::try_fold::<..., ..., ...>`
--> $SRC_DIR/core/src/iter/adapters/filter.rs:LL:COL
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "64"]` attribute to your crate (`overflow_during_mono`)
= note: required for `Filter<std::array::IntoIter<i32, 11>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>` to implement `Iterator`
= note: 31 redundant requirements hidden
= note: required for `Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<std::array::IntoIter<i32, 11>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>` to implement `Iterator`
= note: required for `Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<std::array::IntoIter<i32, 11>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>` to implement `IntoIterator`
= help: consider adding a `#![type_length_limit="20156994"]` attribute to your crate
= note: the full type name has been written to '$TEST_BUILD_DIR/codegen/overflow-during-mono/overflow-during-mono.long-type.txt'
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0275`.

View File

@ -1,7 +1,4 @@
//@ build-fail
//@ normalize-stderr-test: "<\{closure@.+`" -> "$$CLOSURE`"
//@ normalize-stderr-test: ".nll/" -> "/"
//@ ignore-compare-mode-next-solver (hangs)
#![allow(unused)]
@ -43,6 +40,7 @@ impl C {
pub fn matches<F: Fn()>(&self, f: &F) {
let &C(ref base) = self;
base.matches(&|| {
//~^ ERROR reached the type-length limit
C(base.clone()).matches(f)
})
}
@ -55,7 +53,6 @@ impl D {
pub fn matches<F: Fn()>(&self, f: &F) {
let &D(ref a) = self;
a.matches(f)
//~^ ERROR reached the recursion limit while instantiating `A::matches::<{closure
}
}

View File

@ -1,14 +1,13 @@
error: reached the recursion limit while instantiating `A::matches::$CLOSURE`
--> $DIR/issue-22638.rs:57:9
error: reached the type-length limit while instantiating `D::matches::<{closure@$DIR/issue-22638.rs:42:23: 42:25}>`
--> $DIR/issue-22638.rs:42:9
|
LL | a.matches(f)
| ^^^^^^^^^^^^
LL | / base.matches(&|| {
LL | |
LL | | C(base.clone()).matches(f)
LL | | })
| |__________^
|
note: `A::matches` defined here
--> $DIR/issue-22638.rs:16:5
|
LL | pub fn matches<F: Fn()>(&self, f: &F) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: consider adding a `#![type_length_limit="30408681"]` attribute to your crate
error: aborting due to 1 previous error

View File

@ -1,6 +1,5 @@
//@ build-fail
//@ normalize-stderr-test: ".nll/" -> "/"
//@ ignore-compare-mode-next-solver (hangs)
trait Mirror {
type Image;
@ -15,7 +14,8 @@ trait Foo {
impl<T> Foo for T {
#[allow(unconditional_recursion)]
fn recurse(&self) {
(self, self).recurse(); //~ ERROR reached the recursion limit
(self, self).recurse();
//~^ ERROR reached the type-length limit
}
}

View File

@ -1,14 +1,10 @@
error: reached the recursion limit while instantiating `<(&(&(..., ...), ...), ...) as Foo>::recurse`
--> $DIR/issue-37311.rs:18:9
error: reached the type-length limit while instantiating `<(&(&(..., ...), ...), ...) as Foo>::recurse`
--> $DIR/issue-37311.rs:17:9
|
LL | (self, self).recurse();
| ^^^^^^^^^^^^^^^^^^^^^^
|
note: `<T as Foo>::recurse` defined here
--> $DIR/issue-37311.rs:17:5
|
LL | fn recurse(&self) {
| ^^^^^^^^^^^^^^^^^
= help: consider adding a `#![type_length_limit="33554429"]` attribute to your crate
= note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-37311-type-length-limit/issue-37311/issue-37311.long-type.txt'
error: aborting due to 1 previous error

View File

@ -1,5 +1,4 @@
//@ run-pass
//@ ignore-compare-mode-next-solver (hangs)
//@ build-fail
//! This snippet causes the type length to blowup exponentially,
//! so check that we don't accidentally exceed the type length limit.
@ -30,5 +29,9 @@ fn main() {
.filter(|a| b.clone().any(|b| *b == *a))
.filter(|a| b.clone().any(|b| *b == *a))
.filter(|a| b.clone().any(|b| *b == *a))
.filter(|a| b.clone().any(|b| *b == *a))
.filter(|a| b.clone().any(|b| *b == *a))
.filter(|a| b.clone().any(|b| *b == *a))
.filter(|a| b.clone().any(|b| *b == *a))
.collect::<VecDeque<_>>();
}

View File

@ -0,0 +1,8 @@
error: reached the type-length limit while instantiating `<std::vec::IntoIter<i32> as Iterator>::try_fold::<vec::in_place_drop::InPlaceDrop<i32>, {closure@iter::adapters::filter::filter_try_fold<'_, ..., ..., ..., ..., ...>::{closure#0}}, ...>`
--> $SRC_DIR/core/src/iter/adapters/filter.rs:LL:COL
|
= help: consider adding a `#![type_length_limit="21233607"]` attribute to your crate
= note: the full type name has been written to '$TEST_BUILD_DIR/iterators/issue-58952-filter-type-length/issue-58952-filter-type-length.long-type.txt'
error: aborting due to 1 previous error

View File

@ -3,7 +3,7 @@
//!
//! The normal limit is a million, and this test used to exceed 1.5 million, but
//! now we can survive an even tighter limit. Still seems excessive though...
#![type_length_limit = "256000"]
#![type_length_limit = "1327047"]
// Custom wrapper so Iterator methods aren't specialized.
struct Iter<I>(I);

View File

@ -1,7 +1,6 @@
//@ build-fail
//@ compile-flags: -Copt-level=0
//@ normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
//~^^^ ERROR overflow evaluating the requirement
//@ ignore-compare-mode-next-solver (hangs)
fn main() {
@ -9,6 +8,8 @@ fn main() {
func(&mut iter)
}
fn func<T: Iterator<Item = u8>>(iter: &mut T) { //~ WARN function cannot return without recursing
fn func<T: Iterator<Item = u8>>(iter: &mut T) {
//~^ WARN function cannot return without recursing
func(&mut iter.map(|x| x + 1))
//~^ ERROR reached the type-length limit
}

View File

@ -1,21 +1,23 @@
warning: function cannot return without recursing
--> $DIR/issue-83150.rs:12:1
--> $DIR/issue-83150.rs:11:1
|
LL | fn func<T: Iterator<Item = u8>>(iter: &mut T) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
LL |
LL | func(&mut iter.map(|x| x + 1))
| ------------------------------ recursive call site
|
= help: a `loop` may express intention better if this is on purpose
= note: `#[warn(unconditional_recursion)]` on by default
error[E0275]: overflow evaluating the requirement `Map<&mut std::ops::Range<u8>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>: Iterator`
error: reached the type-length limit while instantiating `<&mut Map<&mut Map<&mut ..., ...>, ...> as Iterator>::map::<..., ...>`
--> $DIR/issue-83150.rs:13:15
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`)
= note: required for `&mut Map<&mut std::ops::Range<u8>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>` to implement `Iterator`
= note: 65 redundant requirements hidden
= note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range<u8>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>` to implement `Iterator`
LL | func(&mut iter.map(|x| x + 1))
| ^^^^^^^^^^^^^^^^^^^
|
= help: consider adding a `#![type_length_limit="23068663"]` attribute to your crate
= note: the full type name has been written to '$TEST_BUILD_DIR/recursion/issue-83150/issue-83150.long-type.txt'
error: aborting due to 1 previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0275`.

View File

@ -1,9 +1,5 @@
//@ build-fail
//@ compile-flags: -Zinline-mir=no
//@ error-pattern: overflow evaluating the requirement `<std::iter::Empty<()> as Iterator>::Item == ()`
//@ error-pattern: function cannot return without recursing
//@ normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
//@ ignore-compare-mode-next-solver (hangs)
// Regression test for #91949.
// This hanged *forever* on 1.56, fixed by #90423.
@ -22,10 +18,12 @@ impl<T, I: Iterator<Item = T>> Iterator for IteratorOfWrapped<T, I> {
}
fn recurse<T>(elements: T) -> Vec<char>
//~^ WARN function cannot return without recursing
where
T: Iterator<Item = ()>,
{
recurse(IteratorOfWrapped(elements).map(|t| t.0))
//~^ ERROR reached the type-length limit
}
fn main() {

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,6 @@
//@ build-fail
//@ error-pattern: reached the type-length limit while instantiating
//@ compile-flags: -Copt-level=0
//@ normalize-stderr-test: ".nll/" -> "/"
//~^^ ERROR reached the type-length limit
// Test that the type length limit can be changed.
// The exact type depends on optimizations, so disable them.
@ -31,4 +30,5 @@ pub struct G<T, K>(std::marker::PhantomData::<(T, K)>);
fn main() {
drop::<Option<A>>(None);
//~^ ERROR reached the type-length limit
}

View File

@ -1,8 +1,15 @@
error: reached the type-length limit while instantiating `std::mem::drop::<Option<((((..., ..., ...), ..., ...), ..., ...), ..., ...)>>`
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
--> $DIR/type_length_limit.rs:32:5
|
= help: consider adding a `#![type_length_limit="10"]` attribute to your crate
LL | drop::<Option<A>>(None);
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding a `#![type_length_limit="4010"]` attribute to your crate
= note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt'
error: aborting due to 1 previous error
error: reached the type-length limit while instantiating `<{closure@rt::lang_start<()>::{closure#0}} as FnMut<()>>::call_mut`
|
= help: consider adding a `#![type_length_limit="10"]` attribute to your crate
error: aborting due to 2 previous errors