diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index bd5a88769059f..0a0c33976a89d 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -370,9 +370,14 @@ pub(crate) fn codegen_terminator_call<'tcx>( // Handle special calls like intrinsics and empty drop glue. let instance = if let ty::FnDef(def_id, fn_args) = *func.layout().ty.kind() { - let instance = - ty::Instance::expect_resolve(fx.tcx, ty::ParamEnv::reveal_all(), def_id, fn_args) - .polymorphize(fx.tcx); + let instance = ty::Instance::expect_resolve( + fx.tcx, + ty::ParamEnv::reveal_all(), + def_id, + fn_args, + Some(source_info.span), + ) + .polymorphize(fx.tcx); if is_call_from_compiler_builtins_to_upstream_monomorphization(fx.tcx, instance) { if target.is_some() { diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs index f9a729618a51a..6aa6f206d98da 100644 --- a/compiler/rustc_codegen_cranelift/src/main_shim.rs +++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs @@ -121,6 +121,7 @@ pub(crate) fn maybe_create_entry_wrapper( ParamEnv::reveal_all(), report.def_id, tcx.mk_args(&[GenericArg::from(main_ret_ty)]), + None, ) .polymorphize(tcx); @@ -146,6 +147,7 @@ pub(crate) fn maybe_create_entry_wrapper( ParamEnv::reveal_all(), start_def_id, tcx.mk_args(&[main_ret_ty.into()]), + None, ) .polymorphize(tcx); let start_func_id = import_function(tcx, m, start_instance); diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index 4a1f5188a8013..58641288b5a6c 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -483,6 +483,7 @@ impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> { ty::ParamEnv::reveal_all(), def_id, ty::List::empty(), + None, ); let symbol_name = tcx.symbol_name(instance).name; diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 53a098d178e41..c181238b05e3e 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -566,6 +566,7 @@ impl<'ll, 'tcx> MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { ty::ParamEnv::reveal_all(), def_id, ty::List::empty(), + None, )), _ => { let name = name.unwrap_or("rust_eh_personality"); diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index f372d3a052267..f2b5a8a1b7829 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -468,6 +468,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( ty::ParamEnv::reveal_all(), start_def_id, cx.tcx().mk_args(&[main_ret_ty.into()]), + None, ); let start_fn = cx.get_fn_addr(start_instance); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index bd9704b37aea9..f6e3fd6b18117 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -843,6 +843,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ty::ParamEnv::reveal_all(), def_id, args, + Some(fn_span), ) .polymorphize(bx.tcx()), ), diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 79a161d3f03d7..b5615584c266c 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -252,6 +252,7 @@ impl<'tcx> CompileTimeEvalContext<'tcx> { ty::ParamEnv::reveal_all(), const_def_id, instance.args, + Some(self.find_closest_untracked_caller_location()), ); return Ok(Some(new_instance)); diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 0649bb5617cee..9b66647e51240 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -871,13 +871,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ty::ExistentialTraitRef::erase_self_ty(tcx, virtual_trait_ref); let concrete_trait_ref = existential_trait_ref.with_self_ty(tcx, dyn_ty); - let concrete_method = Instance::resolve_for_vtable( + let concrete_method = Instance::expect_resolve_for_vtable( tcx, self.param_env, def_id, instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args), - ) - .unwrap(); + ); assert_eq!(fn_inst, concrete_method); } diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl index f4d619329eb9c..2b9d9a07a98ef 100644 --- a/compiler/rustc_middle/messages.ftl +++ b/compiler/rustc_middle/messages.ftl @@ -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}' diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index 6e622b0405f0a..711db4e0a6bdb 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -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, +} diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index d72ad09f95484..bdb5717e1f26b 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -2152,8 +2152,8 @@ rustc_queries! { /// * `Err(ErrorGuaranteed)` when the `Instance` resolution process /// couldn't complete due to errors elsewhere - this is distinct /// from `Ok(None)` to avoid misleading diagnostics when an error - /// has already been/will be emitted, for the original cause - query resolve_instance( + /// has already been/will be emitted, for the original cause. + query resolve_instance_raw( key: ty::ParamEnvAnd<'tcx, (DefId, GenericArgsRef<'tcx>)> ) -> Result>, ErrorGuaranteed> { desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index a887047f62f21..1201c11f1d5c2 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -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::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; /// A monomorphized `InstanceDef`. /// @@ -376,7 +378,28 @@ impl<'tcx> InstanceDef<'tcx> { } } -fn fmt_instance( +fn type_length<'tcx>(item: impl TypeVisitable>) -> usize { + struct Visitor { + type_length: usize, + } + impl<'tcx> TypeVisitor> 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, @@ -476,7 +499,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 @@ -489,6 +513,16 @@ impl<'tcx> Instance<'tcx> { def_id: DefId, args: GenericArgsRef<'tcx>, ) -> Result>, 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. @@ -496,7 +530,7 @@ impl<'tcx> Instance<'tcx> { // below is more likely to ignore the bounds in scope (e.g. if the only // generic parameters mentioned by `args` were lifetime ones). let args = tcx.erase_regions(args); - tcx.resolve_instance(tcx.erase_regions(param_env.and((def_id, args)))) + tcx.resolve_instance_raw(tcx.erase_regions(param_env.and((def_id, args)))) } pub fn expect_resolve( @@ -504,9 +538,36 @@ impl<'tcx> Instance<'tcx> { param_env: ty::ParamEnv<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>, + span: Option, ) -> 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 { + span: span.unwrap_or(DUMMY_SP), + shrunk, + was_written, + path, + type_length, + }); + } else { + bug!( + "failed to resolve instance for {}", + tcx.def_path_str_with_args(def_id, args) + ) + } + } instance => bug!( "failed to resolve instance for {}: {instance:#?}", tcx.def_path_str_with_args(def_id, args) @@ -562,77 +623,81 @@ impl<'tcx> Instance<'tcx> { }) } - pub fn resolve_for_vtable( + pub fn expect_resolve_for_vtable( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>, - ) -> Option> { + ) -> Instance<'tcx> { debug!("resolve_for_vtable(def_id={:?}, args={:?})", def_id, args); let fn_sig = tcx.fn_sig(def_id).instantiate_identity(); let is_vtable_shim = !fn_sig.inputs().skip_binder().is_empty() && fn_sig.input(0).skip_binder().is_param(0) && tcx.generics_of(def_id).has_self; + if is_vtable_shim { debug!(" => associated item with unsizeable self: Self"); - Some(Instance { def: InstanceDef::VTableShim(def_id), args }) - } else { - let reason = tcx.sess.is_sanitizer_kcfi_enabled().then_some(ReifyReason::Vtable); - Instance::resolve(tcx, param_env, def_id, args).ok().flatten().map(|mut resolved| { - match resolved.def { - InstanceDef::Item(def) => { - // We need to generate a shim when we cannot guarantee that - // the caller of a trait object method will be aware of - // `#[track_caller]` - this ensures that the caller - // and callee ABI will always match. - // - // The shim is generated when all of these conditions are met: - // - // 1) The underlying method expects a caller location parameter - // in the ABI - if resolved.def.requires_caller_location(tcx) - // 2) The caller location parameter comes from having `#[track_caller]` - // on the implementation, and *not* on the trait method. - && !tcx.should_inherit_track_caller(def) - // If the method implementation comes from the trait definition itself - // (e.g. `trait Foo { #[track_caller] my_fn() { /* impl */ } }`), - // then we don't need to generate a shim. This check is needed because - // `should_inherit_track_caller` returns `false` if our method - // implementation comes from the trait block, and not an impl block - && !matches!( - tcx.opt_associated_item(def), - Some(ty::AssocItem { - container: ty::AssocItemContainer::TraitContainer, - .. - }) - ) - { - if tcx.is_closure_like(def) { - debug!(" => vtable fn pointer created for closure with #[track_caller]: {:?} for method {:?} {:?}", - def, def_id, args); - - // Create a shim for the `FnOnce/FnMut/Fn` method we are calling - // - unlike functions, invoking a closure always goes through a - // trait. - resolved = Instance { def: InstanceDef::ReifyShim(def_id, reason), args }; - } else { - debug!( - " => vtable fn pointer created for function with #[track_caller]: {:?}", def - ); - resolved.def = InstanceDef::ReifyShim(def, reason); - } - } - } - InstanceDef::Virtual(def_id, _) => { - debug!(" => vtable fn pointer created for virtual call"); - resolved.def = InstanceDef::ReifyShim(def_id, reason) + return Instance { def: InstanceDef::VTableShim(def_id), args }; + } + + let mut resolved = Instance::expect_resolve(tcx, param_env, def_id, args, None); + + let reason = tcx.sess.is_sanitizer_kcfi_enabled().then_some(ReifyReason::Vtable); + match resolved.def { + InstanceDef::Item(def) => { + // We need to generate a shim when we cannot guarantee that + // the caller of a trait object method will be aware of + // `#[track_caller]` - this ensures that the caller + // and callee ABI will always match. + // + // The shim is generated when all of these conditions are met: + // + // 1) The underlying method expects a caller location parameter + // in the ABI + if resolved.def.requires_caller_location(tcx) + // 2) The caller location parameter comes from having `#[track_caller]` + // on the implementation, and *not* on the trait method. + && !tcx.should_inherit_track_caller(def) + // If the method implementation comes from the trait definition itself + // (e.g. `trait Foo { #[track_caller] my_fn() { /* impl */ } }`), + // then we don't need to generate a shim. This check is needed because + // `should_inherit_track_caller` returns `false` if our method + // implementation comes from the trait block, and not an impl block + && !matches!( + tcx.opt_associated_item(def), + Some(ty::AssocItem { + container: ty::AssocItemContainer::TraitContainer, + .. + }) + ) + { + if tcx.is_closure_like(def) { + debug!( + " => vtable fn pointer created for closure with #[track_caller]: {:?} for method {:?} {:?}", + def, def_id, args + ); + + // Create a shim for the `FnOnce/FnMut/Fn` method we are calling + // - unlike functions, invoking a closure always goes through a + // trait. + resolved = Instance { def: InstanceDef::ReifyShim(def_id, reason), args }; + } else { + debug!( + " => vtable fn pointer created for function with #[track_caller]: {:?}", + def + ); + resolved.def = InstanceDef::ReifyShim(def, reason); } - _ => {} } - - resolved - }) + } + InstanceDef::Virtual(def_id, _) => { + debug!(" => vtable fn pointer created for virtual call"); + resolved.def = InstanceDef::ReifyShim(def_id, reason) + } + _ => {} } + + resolved } pub fn resolve_closure( @@ -652,13 +717,13 @@ impl<'tcx> Instance<'tcx> { pub fn resolve_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> { let def_id = tcx.require_lang_item(LangItem::DropInPlace, None); let args = tcx.mk_args(&[ty.into()]); - Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, args) + Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, args, None) } pub fn resolve_async_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> { let def_id = tcx.require_lang_item(LangItem::AsyncDropInPlace, None); let args = tcx.mk_args(&[ty.into()]); - Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, args) + Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, args, None) } #[instrument(level = "debug", skip(tcx), ret)] diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 3c27df9529aa1..c165790548d75 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -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) { + 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) + } +} diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl index 94b553a07a755..7210701d4828c 100644 --- a/compiler/rustc_monomorphize/messages.ftl +++ b/compiler/rustc_monomorphize/messages.ftl @@ -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 diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 9487692662bb7..91797360321ee 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -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, InstanceDef, 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) { - 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>, @@ -916,7 +853,13 @@ fn visit_fn_use<'tcx>( ) { if let ty::FnDef(def_id, args) = *ty.kind() { let instance = if is_direct_call { - ty::Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, args) + ty::Instance::expect_resolve( + tcx, + ty::ParamEnv::reveal_all(), + def_id, + args, + Some(source), + ) } else { match ty::Instance::resolve_for_fn_ptr(tcx, ty::ParamEnv::reveal_all(), def_id, args) { Some(instance) => instance, @@ -1318,8 +1261,13 @@ fn visit_mentioned_item<'tcx>( match *item { MentionedItem::Fn(ty) => { if let ty::FnDef(def_id, args) = *ty.kind() { - let instance = - Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, args); + let instance = Instance::expect_resolve( + tcx, + ty::ParamEnv::reveal_all(), + def_id, + args, + Some(span), + ); // `visit_instance_use` was written for "used" item collection but works just as well // for "mentioned" item collection. // We can set `is_direct_call`; that just means we'll skip a bunch of shims that anyway @@ -1544,6 +1492,7 @@ impl<'v> RootCollector<'_, 'v> { ty::ParamEnv::reveal_all(), start_def_id, self.tcx.mk_args(&[main_ret_ty.into()]), + None, ); self.output.push(create_fn_mono_item(self.tcx, start_instance, DUMMY_SP)); @@ -1614,7 +1563,7 @@ fn create_mono_items_for_default_impls<'tcx>( // As mentioned above, the method is legal to eagerly instantiate if it // only has lifetime generic parameters. This is validated by let args = trait_ref.args.extend_to(tcx, method.def_id, only_region_params); - let instance = ty::Instance::expect_resolve(tcx, param_env, method.def_id, args); + let instance = ty::Instance::expect_resolve(tcx, param_env, method.def_id, args, None); let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP); if mono_item.node.is_instantiable(tcx) && should_codegen_locally(tcx, instance) { diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index 35fc78f204533..9ea77f4612a7c 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -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 { diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index c93ec43944ad2..8964a583b525a 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -289,13 +289,13 @@ fn vtable_entries<'tcx>( return VtblEntry::Vacant; } - let instance = ty::Instance::resolve_for_vtable( + let instance = ty::Instance::expect_resolve_for_vtable( tcx, ty::ParamEnv::reveal_all(), def_id, args, - ) - .expect("resolution failed during building vtable representation"); + ); + VtblEntry::Method(instance) }); diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index e4dcea785d411..f1dd99f6202ac 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -15,7 +15,7 @@ use traits::{translate_args, Reveal}; use crate::errors::UnexpectedFnPtrAssociatedItem; -fn resolve_instance<'tcx>( +fn resolve_instance_raw<'tcx>( tcx: TyCtxt<'tcx>, key: ty::ParamEnvAnd<'tcx, (DefId, GenericArgsRef<'tcx>)>, ) -> Result>, ErrorGuaranteed> { @@ -354,5 +354,5 @@ fn resolve_associated_item<'tcx>( } pub(crate) fn provide(providers: &mut Providers) { - *providers = Providers { resolve_instance, ..*providers }; + *providers = Providers { resolve_instance_raw, ..*providers }; } diff --git a/tests/ui/closures/issue-72408-nested-closures-exponential.rs b/tests/ui/closures/issue-72408-nested-closures-exponential.rs index 682508f928082..4208d0fcf9c42 100644 --- a/tests/ui/closures/issue-72408-nested-closures-exponential.rs +++ b/tests/ui/closures/issue-72408-nested-closures-exponential.rs @@ -1,5 +1,4 @@ -//@ build-pass -//@ ignore-compare-mode-next-solver (hangs) +//@ build-fail // Closures include captured types twice in a type tree. // @@ -38,6 +37,7 @@ fn main() { let f = dup(f); let f = dup(f); let f = dup(f); + //~^ ERROR reached the type-length limit let f = dup(f); let f = dup(f); diff --git a/tests/ui/closures/issue-72408-nested-closures-exponential.stderr b/tests/ui/closures/issue-72408-nested-closures-exponential.stderr new file mode 100644 index 0000000000000..132f3e6961d6f --- /dev/null +++ b/tests/ui/closures/issue-72408-nested-closures-exponential.stderr @@ -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:39:13 + | +LL | let f = dup(f); + | ^^^^^^ + | + = help: consider adding a `#![type_length_limit="1835001"]` attribute to your crate + +error: aborting due to 1 previous error + diff --git a/tests/ui/codegen/overflow-during-mono.rs b/tests/ui/codegen/overflow-during-mono.rs index 919f1a8120e0b..278298f27ff0e 100644 --- a/tests/ui/codegen/overflow-during-mono.rs +++ b/tests/ui/codegen/overflow-during-mono.rs @@ -1,5 +1,4 @@ //@ build-fail -//~^ ERROR overflow evaluating the requirement #![recursion_limit = "32"] diff --git a/tests/ui/codegen/overflow-during-mono.stderr b/tests/ui/codegen/overflow-during-mono.stderr index f7a3e2df3dbaa..c431eb1aff314 100644 --- a/tests/ui/codegen/overflow-during-mono.stderr +++ b/tests/ui/codegen/overflow-during-mono.stderr @@ -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 `, {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, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>` to implement `Iterator` - = note: 31 redundant requirements hidden - = note: required for `Filter, {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, {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="1120534"]` 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`. diff --git a/tests/ui/issues/issue-22638.rs b/tests/ui/issues/issue-22638.rs index 3e04eb41b98de..3e401e99fb48d 100644 --- a/tests/ui/issues/issue-22638.rs +++ b/tests/ui/issues/issue-22638.rs @@ -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(&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(&self, f: &F) { let &D(ref a) = self; a.matches(f) - //~^ ERROR reached the recursion limit while instantiating `A::matches::<{closure } } diff --git a/tests/ui/issues/issue-22638.stderr b/tests/ui/issues/issue-22638.stderr index 45290f6afe9de..1344409c77040 100644 --- a/tests/ui/issues/issue-22638.stderr +++ b/tests/ui/issues/issue-22638.stderr @@ -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(&self, f: &F) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: consider adding a `#![type_length_limit="30408681"]` attribute to your crate error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-37311-type-length-limit/issue-37311.rs b/tests/ui/issues/issue-37311-type-length-limit/issue-37311.rs index 1646f16e1ecea..131c7535537f6 100644 --- a/tests/ui/issues/issue-37311-type-length-limit/issue-37311.rs +++ b/tests/ui/issues/issue-37311-type-length-limit/issue-37311.rs @@ -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 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 } } diff --git a/tests/ui/issues/issue-37311-type-length-limit/issue-37311.stderr b/tests/ui/issues/issue-37311-type-length-limit/issue-37311.stderr index ccee9ed4daadb..5ba80bcf31c37 100644 --- a/tests/ui/issues/issue-37311-type-length-limit/issue-37311.stderr +++ b/tests/ui/issues/issue-37311-type-length-limit/issue-37311.stderr @@ -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: `::recurse` defined here - --> $DIR/issue-37311.rs:17:5 - | -LL | fn recurse(&self) { - | ^^^^^^^^^^^^^^^^^ + = help: consider adding a `#![type_length_limit="2097149"]` 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 diff --git a/tests/ui/iterators/issue-58952-filter-type-length.rs b/tests/ui/iterators/issue-58952-filter-type-length.rs index 9904eddb598ce..ef77a2f603965 100644 --- a/tests/ui/iterators/issue-58952-filter-type-length.rs +++ b/tests/ui/iterators/issue-58952-filter-type-length.rs @@ -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. diff --git a/tests/ui/iterators/issue-58952-filter-type-length.stderr b/tests/ui/iterators/issue-58952-filter-type-length.stderr new file mode 100644 index 0000000000000..858fb28b2949e --- /dev/null +++ b/tests/ui/iterators/issue-58952-filter-type-length.stderr @@ -0,0 +1,8 @@ +error: reached the type-length limit while instantiating ` as Iterator>::try_fold::, {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="1327047"]` 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 + diff --git a/tests/ui/iterators/iter-map-fold-type-length.rs b/tests/ui/iterators/iter-map-fold-type-length.rs index 6444fb9dada98..5f9567d68e819 100644 --- a/tests/ui/iterators/iter-map-fold-type-length.rs +++ b/tests/ui/iterators/iter-map-fold-type-length.rs @@ -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); diff --git a/tests/ui/recursion/issue-83150.rs b/tests/ui/recursion/issue-83150.rs index b74b2adfeab47..b3ddf88c4493f 100644 --- a/tests/ui/recursion/issue-83150.rs +++ b/tests/ui/recursion/issue-83150.rs @@ -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>(iter: &mut T) { //~ WARN function cannot return without recursing +fn func>(iter: &mut T) { + //~^ WARN function cannot return without recursing func(&mut iter.map(|x| x + 1)) + //~^ ERROR reached the type-length limit } diff --git a/tests/ui/recursion/issue-83150.stderr b/tests/ui/recursion/issue-83150.stderr index 783f9cf763254..3432289edc3da 100644 --- a/tests/ui/recursion/issue-83150.stderr +++ b/tests/ui/recursion/issue-83150.stderr @@ -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>(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, {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, {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, {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="1441783"]` 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`. diff --git a/tests/ui/traits/issue-91949-hangs-on-recursion.rs b/tests/ui/traits/issue-91949-hangs-on-recursion.rs index ddbbcdd052965..d9c422e6f7096 100644 --- a/tests/ui/traits/issue-91949-hangs-on-recursion.rs +++ b/tests/ui/traits/issue-91949-hangs-on-recursion.rs @@ -1,9 +1,5 @@ //@ build-fail //@ compile-flags: -Zinline-mir=no -//@ error-pattern: overflow evaluating the requirement ` 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> Iterator for IteratorOfWrapped { } fn recurse(elements: T) -> Vec +//~^ WARN function cannot return without recursing where T: Iterator, { recurse(IteratorOfWrapped(elements).map(|t| t.0)) + //~^ ERROR reached the type-length limit } fn main() { diff --git a/tests/ui/traits/issue-91949-hangs-on-recursion.stderr b/tests/ui/traits/issue-91949-hangs-on-recursion.stderr index c4324f0f0a872..c8c95b147b3a7 100644 --- a/tests/ui/traits/issue-91949-hangs-on-recursion.stderr +++ b/tests/ui/traits/issue-91949-hangs-on-recursion.stderr @@ -1,7 +1,8 @@ warning: function cannot return without recursing - --> $DIR/issue-91949-hangs-on-recursion.rs:24:1 + --> $DIR/issue-91949-hangs-on-recursion.rs:20:1 | LL | / fn recurse(elements: T) -> Vec +LL | | LL | | where LL | | T: Iterator, | |___________________________^ cannot return without recursing @@ -12,19 +13,14 @@ LL | recurse(IteratorOfWrapped(elements).map(|t| t.0)) = 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 ` as Iterator>::Item == ()` +error: reached the type-length limit while instantiating `, ...>> as Iterator>::map::<..., ...>` + --> $DIR/issue-91949-hangs-on-recursion.rs:25:13 | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "512"]` attribute to your crate (`issue_91949_hangs_on_recursion`) -note: required for `IteratorOfWrapped<(), std::iter::Empty<()>>` to implement `Iterator` - --> $DIR/issue-91949-hangs-on-recursion.rs:17:32 +LL | recurse(IteratorOfWrapped(elements).map(|t| t.0)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -LL | impl> Iterator for IteratorOfWrapped { - | -------- ^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ - | | - | unsatisfied trait bound introduced here - = note: 256 redundant requirements hidden - = note: required for `IteratorOfWrapped<(), Map>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>` to implement `Iterator` + = help: consider adding a `#![type_length_limit="1703925"]` attribute to your crate + = note: the full type name has been written to '$TEST_BUILD_DIR/traits/issue-91949-hangs-on-recursion/issue-91949-hangs-on-recursion.long-type.txt' error: aborting due to 1 previous error; 1 warning emitted -For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/type_length_limit.rs b/tests/ui/type_length_limit.rs index c60f1be06c671..d6937481a1551 100644 --- a/tests/ui/type_length_limit.rs +++ b/tests/ui/type_length_limit.rs @@ -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(std::marker::PhantomData::<(T, K)>); fn main() { drop::>(None); + //~^ ERROR reached the type-length limit } diff --git a/tests/ui/type_length_limit.stderr b/tests/ui/type_length_limit.stderr index 32290a2f5bfc7..83353547d34db 100644 --- a/tests/ui/type_length_limit.stderr +++ b/tests/ui/type_length_limit.stderr @@ -1,8 +1,15 @@ error: reached the type-length limit while instantiating `std::mem::drop::>` - --> $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::>(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