Point at the call spawn when overflow occurs during monomorphization

This improves the output for issue #72577, but there's still more work
to be done.

Currently, an overflow error during monomorphization results in an error
that points at the function we were unable to monomorphize. However, we
don't point at the call that caused the monomorphization to happen. In
the overflow occurs in a large recursive function, it may be difficult
to determine where the issue is.

This commit tracks and `Span` information during collection of
`MonoItem`s, which is used when emitting an overflow error. `MonoItem`
itself is unchanged, so this only affects
`src/librustc_mir/monomorphize/collector.rs`
This commit is contained in:
Aaron Hill 2020-06-21 22:32:35 -04:00
parent 1a4e2b6f9c
commit 3ed96a6d63
No known key found for this signature in database
GPG Key ID: B4087E510E98B164
10 changed files with 132 additions and 80 deletions

View File

@ -178,7 +178,7 @@ use crate::monomorphize;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator}; use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator};
use rustc_errors::ErrorReported; use rustc_errors::{ErrorReported, FatalError};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::itemlikevisit::ItemLikeVisitor;
@ -195,6 +195,7 @@ use rustc_middle::ty::print::obsolete::DefPathBasedNames;
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
use rustc_middle::ty::{self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable}; use rustc_middle::ty::{self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable};
use rustc_session::config::EntryFnType; use rustc_session::config::EntryFnType;
use rustc_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP};
use smallvec::SmallVec; use smallvec::SmallVec;
use std::iter; use std::iter;
@ -294,7 +295,13 @@ pub fn collect_crate_mono_items(
tcx.sess.time("monomorphization_collector_graph_walk", || { tcx.sess.time("monomorphization_collector_graph_walk", || {
par_iter(roots).for_each(|root| { par_iter(roots).for_each(|root| {
let mut recursion_depths = DefIdMap::default(); let mut recursion_depths = DefIdMap::default();
collect_items_rec(tcx, root, visited, &mut recursion_depths, inlining_map); collect_items_rec(
tcx,
dummy_spanned(root),
visited,
&mut recursion_depths,
inlining_map,
);
}); });
}); });
} }
@ -323,29 +330,30 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<
// We can only codegen items that are instantiable - items all of // We can only codegen items that are instantiable - items all of
// whose predicates hold. Luckily, items that aren't instantiable // whose predicates hold. Luckily, items that aren't instantiable
// can't actually be used, so we can just skip codegenning them. // can't actually be used, so we can just skip codegenning them.
roots.retain(|root| root.is_instantiable(tcx));
roots roots
.into_iter()
.filter_map(|root| root.node.is_instantiable(tcx).then_some(root.node))
.collect()
} }
// Collect all monomorphized items reachable from `starting_point` // Collect all monomorphized items reachable from `starting_point`
fn collect_items_rec<'tcx>( fn collect_items_rec<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
starting_point: MonoItem<'tcx>, starting_point: Spanned<MonoItem<'tcx>>,
visited: MTRef<'_, MTLock<FxHashSet<MonoItem<'tcx>>>>, visited: MTRef<'_, MTLock<FxHashSet<MonoItem<'tcx>>>>,
recursion_depths: &mut DefIdMap<usize>, recursion_depths: &mut DefIdMap<usize>,
inlining_map: MTRef<'_, MTLock<InliningMap<'tcx>>>, inlining_map: MTRef<'_, MTLock<InliningMap<'tcx>>>,
) { ) {
if !visited.lock_mut().insert(starting_point) { if !visited.lock_mut().insert(starting_point.node) {
// We've been here already, no need to search again. // We've been here already, no need to search again.
return; return;
} }
debug!("BEGIN collect_items_rec({})", starting_point.to_string(tcx, true)); debug!("BEGIN collect_items_rec({})", starting_point.node.to_string(tcx, true));
let mut neighbors = Vec::new(); let mut neighbors = Vec::new();
let recursion_depth_reset; let recursion_depth_reset;
match starting_point { match starting_point.node {
MonoItem::Static(def_id) => { MonoItem::Static(def_id) => {
let instance = Instance::mono(tcx, def_id); let instance = Instance::mono(tcx, def_id);
@ -353,7 +361,7 @@ fn collect_items_rec<'tcx>(
debug_assert!(should_monomorphize_locally(tcx, &instance)); debug_assert!(should_monomorphize_locally(tcx, &instance));
let ty = instance.monomorphic_ty(tcx); let ty = instance.monomorphic_ty(tcx);
visit_drop_use(tcx, ty, true, &mut neighbors); visit_drop_use(tcx, ty, true, starting_point.span, &mut neighbors);
recursion_depth_reset = None; recursion_depth_reset = None;
@ -366,7 +374,8 @@ fn collect_items_rec<'tcx>(
debug_assert!(should_monomorphize_locally(tcx, &instance)); debug_assert!(should_monomorphize_locally(tcx, &instance));
// Keep track of the monomorphization recursion depth // Keep track of the monomorphization recursion depth
recursion_depth_reset = Some(check_recursion_limit(tcx, instance, recursion_depths)); recursion_depth_reset =
Some(check_recursion_limit(tcx, instance, starting_point.span, recursion_depths));
check_type_length_limit(tcx, instance); check_type_length_limit(tcx, instance);
rustc_data_structures::stack::ensure_sufficient_stack(|| { rustc_data_structures::stack::ensure_sufficient_stack(|| {
@ -378,7 +387,7 @@ fn collect_items_rec<'tcx>(
} }
} }
record_accesses(tcx, starting_point, &neighbors[..], inlining_map); record_accesses(tcx, starting_point.node, neighbors.iter().map(|i| &i.node), inlining_map);
for neighbour in neighbors { for neighbour in neighbors {
collect_items_rec(tcx, neighbour, visited, recursion_depths, inlining_map); collect_items_rec(tcx, neighbour, visited, recursion_depths, inlining_map);
@ -388,13 +397,13 @@ fn collect_items_rec<'tcx>(
recursion_depths.insert(def_id, depth); recursion_depths.insert(def_id, depth);
} }
debug!("END collect_items_rec({})", starting_point.to_string(tcx, true)); debug!("END collect_items_rec({})", starting_point.node.to_string(tcx, true));
} }
fn record_accesses<'tcx>( fn record_accesses<'a, 'tcx: 'a>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
caller: MonoItem<'tcx>, caller: MonoItem<'tcx>,
callees: &[MonoItem<'tcx>], callees: impl Iterator<Item = &'a MonoItem<'tcx>>,
inlining_map: MTRef<'_, MTLock<InliningMap<'tcx>>>, inlining_map: MTRef<'_, MTLock<InliningMap<'tcx>>>,
) { ) {
let is_inlining_candidate = |mono_item: &MonoItem<'tcx>| { let is_inlining_candidate = |mono_item: &MonoItem<'tcx>| {
@ -405,7 +414,7 @@ fn record_accesses<'tcx>(
// FIXME: Call `is_inlining_candidate` when pushing to `neighbors` in `collect_items_rec` // FIXME: Call `is_inlining_candidate` when pushing to `neighbors` in `collect_items_rec`
// instead to avoid creating this `SmallVec`. // instead to avoid creating this `SmallVec`.
let accesses: SmallVec<[_; 128]> = let accesses: SmallVec<[_; 128]> =
callees.iter().map(|mono_item| (*mono_item, is_inlining_candidate(mono_item))).collect(); callees.map(|mono_item| (*mono_item, is_inlining_candidate(mono_item))).collect();
inlining_map.lock_mut().record_accesses(caller, &accesses); inlining_map.lock_mut().record_accesses(caller, &accesses);
} }
@ -413,6 +422,7 @@ fn record_accesses<'tcx>(
fn check_recursion_limit<'tcx>( fn check_recursion_limit<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
instance: Instance<'tcx>, instance: Instance<'tcx>,
span: Span,
recursion_depths: &mut DefIdMap<usize>, recursion_depths: &mut DefIdMap<usize>,
) -> (DefId, usize) { ) -> (DefId, usize) {
let def_id = instance.def_id(); let def_id = instance.def_id();
@ -432,12 +442,13 @@ fn check_recursion_limit<'tcx>(
// infinite expansion. // infinite expansion.
if !tcx.sess.recursion_limit().value_within_limit(adjusted_recursion_depth) { if !tcx.sess.recursion_limit().value_within_limit(adjusted_recursion_depth) {
let error = format!("reached the recursion limit while instantiating `{}`", instance); let error = format!("reached the recursion limit while instantiating `{}`", instance);
if let Some(def_id) = def_id.as_local() { let mut err = tcx.sess.struct_span_fatal(span, &error);
let hir_id = tcx.hir().as_local_hir_id(def_id); err.span_note(
tcx.sess.span_fatal(tcx.hir().span(hir_id), &error); tcx.def_span(def_id),
} else { &format!("`{}` defined here", tcx.def_path_str(def_id)),
tcx.sess.fatal(&error); );
} err.emit();
FatalError.raise();
} }
recursion_depths.insert(def_id, recursion_depth + 1); recursion_depths.insert(def_id, recursion_depth + 1);
@ -498,7 +509,7 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
struct MirNeighborCollector<'a, 'tcx> { struct MirNeighborCollector<'a, 'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
body: &'a mir::Body<'tcx>, body: &'a mir::Body<'tcx>,
output: &'a mut Vec<MonoItem<'tcx>>, output: &'a mut Vec<Spanned<MonoItem<'tcx>>>,
instance: Instance<'tcx>, instance: Instance<'tcx>,
} }
@ -520,6 +531,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) { fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
debug!("visiting rvalue {:?}", *rvalue); debug!("visiting rvalue {:?}", *rvalue);
let span = self.body.source_info(location).span;
match *rvalue { match *rvalue {
// When doing an cast from a regular pointer to a fat pointer, we // When doing an cast from a regular pointer to a fat pointer, we
// have to instantiate all methods of the trait being cast to, so we // have to instantiate all methods of the trait being cast to, so we
@ -542,6 +555,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
self.tcx, self.tcx,
target_ty, target_ty,
source_ty, source_ty,
span,
self.output, self.output,
); );
} }
@ -553,7 +567,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
) => { ) => {
let fn_ty = operand.ty(self.body, self.tcx); let fn_ty = operand.ty(self.body, self.tcx);
let fn_ty = self.monomorphize(fn_ty); let fn_ty = self.monomorphize(fn_ty);
visit_fn_use(self.tcx, fn_ty, false, &mut self.output); visit_fn_use(self.tcx, fn_ty, false, span, &mut self.output);
} }
mir::Rvalue::Cast( mir::Rvalue::Cast(
mir::CastKind::Pointer(PointerCast::ClosureFnPointer(_)), mir::CastKind::Pointer(PointerCast::ClosureFnPointer(_)),
@ -571,7 +585,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
ty::ClosureKind::FnOnce, ty::ClosureKind::FnOnce,
); );
if should_monomorphize_locally(self.tcx, &instance) { if should_monomorphize_locally(self.tcx, &instance) {
self.output.push(create_fn_mono_item(instance)); self.output.push(create_fn_mono_item(instance, span));
} }
} }
_ => bug!(), _ => bug!(),
@ -583,7 +597,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
tcx.require_lang_item(ExchangeMallocFnLangItem, None); tcx.require_lang_item(ExchangeMallocFnLangItem, None);
let instance = Instance::mono(tcx, exchange_malloc_fn_def_id); let instance = Instance::mono(tcx, exchange_malloc_fn_def_id);
if should_monomorphize_locally(tcx, &instance) { if should_monomorphize_locally(tcx, &instance) {
self.output.push(create_fn_mono_item(instance)); self.output.push(create_fn_mono_item(instance, span));
} }
} }
mir::Rvalue::ThreadLocalRef(def_id) => { mir::Rvalue::ThreadLocalRef(def_id) => {
@ -591,7 +605,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
let instance = Instance::mono(self.tcx, def_id); let instance = Instance::mono(self.tcx, def_id);
if should_monomorphize_locally(self.tcx, &instance) { if should_monomorphize_locally(self.tcx, &instance) {
trace!("collecting thread-local static {:?}", def_id); trace!("collecting thread-local static {:?}", def_id);
self.output.push(MonoItem::Static(def_id)); self.output.push(respan(span, MonoItem::Static(def_id)));
} }
} }
_ => { /* not interesting */ } _ => { /* not interesting */ }
@ -626,32 +640,33 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Location) { fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Location) {
debug!("visiting terminator {:?} @ {:?}", terminator, location); debug!("visiting terminator {:?} @ {:?}", terminator, location);
let source = self.body.source_info(location).span;
let tcx = self.tcx; let tcx = self.tcx;
match terminator.kind { match terminator.kind {
mir::TerminatorKind::Call { ref func, .. } => { mir::TerminatorKind::Call { ref func, .. } => {
let callee_ty = func.ty(self.body, tcx); let callee_ty = func.ty(self.body, tcx);
let callee_ty = self.monomorphize(callee_ty); let callee_ty = self.monomorphize(callee_ty);
visit_fn_use(self.tcx, callee_ty, true, &mut self.output); visit_fn_use(self.tcx, callee_ty, true, source, &mut self.output);
} }
mir::TerminatorKind::Drop { ref place, .. } mir::TerminatorKind::Drop { ref place, .. }
| mir::TerminatorKind::DropAndReplace { ref place, .. } => { | mir::TerminatorKind::DropAndReplace { ref place, .. } => {
let ty = place.ty(self.body, self.tcx).ty; let ty = place.ty(self.body, self.tcx).ty;
let ty = self.monomorphize(ty); let ty = self.monomorphize(ty);
visit_drop_use(self.tcx, ty, true, self.output); visit_drop_use(self.tcx, ty, true, source, self.output);
} }
mir::TerminatorKind::InlineAsm { ref operands, .. } => { mir::TerminatorKind::InlineAsm { ref operands, .. } => {
for op in operands { for op in operands {
match *op { match *op {
mir::InlineAsmOperand::SymFn { ref value } => { mir::InlineAsmOperand::SymFn { ref value } => {
let fn_ty = self.monomorphize(value.literal.ty); let fn_ty = self.monomorphize(value.literal.ty);
visit_fn_use(self.tcx, fn_ty, false, &mut self.output); visit_fn_use(self.tcx, fn_ty, false, source, &mut self.output);
} }
mir::InlineAsmOperand::SymStatic { def_id } => { mir::InlineAsmOperand::SymStatic { def_id } => {
let instance = Instance::mono(self.tcx, def_id); let instance = Instance::mono(self.tcx, def_id);
if should_monomorphize_locally(self.tcx, &instance) { if should_monomorphize_locally(self.tcx, &instance) {
trace!("collecting asm sym static {:?}", def_id); trace!("collecting asm sym static {:?}", def_id);
self.output.push(MonoItem::Static(def_id)); self.output.push(respan(source, MonoItem::Static(def_id)));
} }
} }
_ => {} _ => {}
@ -687,17 +702,19 @@ fn visit_drop_use<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
is_direct_call: bool, is_direct_call: bool,
output: &mut Vec<MonoItem<'tcx>>, source: Span,
output: &mut Vec<Spanned<MonoItem<'tcx>>>,
) { ) {
let instance = Instance::resolve_drop_in_place(tcx, ty); let instance = Instance::resolve_drop_in_place(tcx, ty);
visit_instance_use(tcx, instance, is_direct_call, output); visit_instance_use(tcx, instance, is_direct_call, source, output);
} }
fn visit_fn_use<'tcx>( fn visit_fn_use<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
is_direct_call: bool, is_direct_call: bool,
output: &mut Vec<MonoItem<'tcx>>, source: Span,
output: &mut Vec<Spanned<MonoItem<'tcx>>>,
) { ) {
if let ty::FnDef(def_id, substs) = ty.kind { if let ty::FnDef(def_id, substs) = ty.kind {
let instance = if is_direct_call { let instance = if is_direct_call {
@ -706,7 +723,7 @@ fn visit_fn_use<'tcx>(
ty::Instance::resolve_for_fn_ptr(tcx, ty::ParamEnv::reveal_all(), def_id, substs) ty::Instance::resolve_for_fn_ptr(tcx, ty::ParamEnv::reveal_all(), def_id, substs)
.unwrap() .unwrap()
}; };
visit_instance_use(tcx, instance, is_direct_call, output); visit_instance_use(tcx, instance, is_direct_call, source, output);
} }
} }
@ -714,7 +731,8 @@ fn visit_instance_use<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
instance: ty::Instance<'tcx>, instance: ty::Instance<'tcx>,
is_direct_call: bool, is_direct_call: bool,
output: &mut Vec<MonoItem<'tcx>>, source: Span,
output: &mut Vec<Spanned<MonoItem<'tcx>>>,
) { ) {
debug!("visit_item_use({:?}, is_direct_call={:?})", instance, is_direct_call); debug!("visit_item_use({:?}, is_direct_call={:?})", instance, is_direct_call);
if !should_monomorphize_locally(tcx, &instance) { if !should_monomorphize_locally(tcx, &instance) {
@ -730,7 +748,7 @@ fn visit_instance_use<'tcx>(
ty::InstanceDef::DropGlue(_, None) => { ty::InstanceDef::DropGlue(_, None) => {
// Don't need to emit noop drop glue if we are calling directly. // Don't need to emit noop drop glue if we are calling directly.
if !is_direct_call { if !is_direct_call {
output.push(create_fn_mono_item(instance)); output.push(create_fn_mono_item(instance, source));
} }
} }
ty::InstanceDef::DropGlue(_, Some(_)) ty::InstanceDef::DropGlue(_, Some(_))
@ -740,7 +758,7 @@ fn visit_instance_use<'tcx>(
| ty::InstanceDef::Item(..) | ty::InstanceDef::Item(..)
| ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::FnPtrShim(..)
| ty::InstanceDef::CloneShim(..) => { | ty::InstanceDef::CloneShim(..) => {
output.push(create_fn_mono_item(instance)); output.push(create_fn_mono_item(instance, source));
} }
} }
} }
@ -832,7 +850,6 @@ fn find_vtable_types_for_unsizing<'tcx>(
let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| { let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| {
let param_env = ty::ParamEnv::reveal_all(); let param_env = ty::ParamEnv::reveal_all();
let type_has_metadata = |ty: Ty<'tcx>| -> bool { let type_has_metadata = |ty: Ty<'tcx>| -> bool {
use rustc_span::DUMMY_SP;
if ty.is_sized(tcx.at(DUMMY_SP), param_env) { if ty.is_sized(tcx.at(DUMMY_SP), param_env) {
return false; return false;
} }
@ -886,9 +903,9 @@ fn find_vtable_types_for_unsizing<'tcx>(
} }
} }
fn create_fn_mono_item(instance: Instance<'_>) -> MonoItem<'_> { fn create_fn_mono_item(instance: Instance<'_>, source: Span) -> Spanned<MonoItem<'_>> {
debug!("create_fn_mono_item(instance={})", instance); debug!("create_fn_mono_item(instance={})", instance);
MonoItem::Fn(instance) respan(source, MonoItem::Fn(instance))
} }
/// Creates a `MonoItem` for each method that is referenced by the vtable for /// Creates a `MonoItem` for each method that is referenced by the vtable for
@ -897,7 +914,8 @@ fn create_mono_items_for_vtable_methods<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
trait_ty: Ty<'tcx>, trait_ty: Ty<'tcx>,
impl_ty: Ty<'tcx>, impl_ty: Ty<'tcx>,
output: &mut Vec<MonoItem<'tcx>>, source: Span,
output: &mut Vec<Spanned<MonoItem<'tcx>>>,
) { ) {
assert!( assert!(
!trait_ty.needs_subst() !trait_ty.needs_subst()
@ -927,12 +945,12 @@ fn create_mono_items_for_vtable_methods<'tcx>(
.unwrap() .unwrap()
}) })
.filter(|&instance| should_monomorphize_locally(tcx, &instance)) .filter(|&instance| should_monomorphize_locally(tcx, &instance))
.map(create_fn_mono_item); .map(|item| create_fn_mono_item(item, source));
output.extend(methods); output.extend(methods);
} }
// Also add the destructor. // Also add the destructor.
visit_drop_use(tcx, impl_ty, false, output); visit_drop_use(tcx, impl_ty, false, source, output);
} }
} }
@ -943,7 +961,7 @@ fn create_mono_items_for_vtable_methods<'tcx>(
struct RootCollector<'a, 'tcx> { struct RootCollector<'a, 'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
mode: MonoItemCollectionMode, mode: MonoItemCollectionMode,
output: &'a mut Vec<MonoItem<'tcx>>, output: &'a mut Vec<Spanned<MonoItem<'tcx>>>,
entry_fn: Option<(LocalDefId, EntryFnType)>, entry_fn: Option<(LocalDefId, EntryFnType)>,
} }
@ -980,7 +998,7 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> {
let ty = Instance::new(def_id.to_def_id(), InternalSubsts::empty()) let ty = Instance::new(def_id.to_def_id(), InternalSubsts::empty())
.monomorphic_ty(self.tcx); .monomorphic_ty(self.tcx);
visit_drop_use(self.tcx, ty, true, self.output); visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output);
} }
} }
} }
@ -989,12 +1007,12 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> {
"RootCollector: ItemKind::GlobalAsm({})", "RootCollector: ItemKind::GlobalAsm({})",
def_id_to_string(self.tcx, self.tcx.hir().local_def_id(item.hir_id)) def_id_to_string(self.tcx, self.tcx.hir().local_def_id(item.hir_id))
); );
self.output.push(MonoItem::GlobalAsm(item.hir_id)); self.output.push(dummy_spanned(MonoItem::GlobalAsm(item.hir_id)));
} }
hir::ItemKind::Static(..) => { hir::ItemKind::Static(..) => {
let def_id = self.tcx.hir().local_def_id(item.hir_id); let def_id = self.tcx.hir().local_def_id(item.hir_id);
debug!("RootCollector: ItemKind::Static({})", def_id_to_string(self.tcx, def_id)); debug!("RootCollector: ItemKind::Static({})", def_id_to_string(self.tcx, def_id));
self.output.push(MonoItem::Static(def_id.to_def_id())); self.output.push(dummy_spanned(MonoItem::Static(def_id.to_def_id())));
} }
hir::ItemKind::Const(..) => { hir::ItemKind::Const(..) => {
// const items only generate mono items if they are // const items only generate mono items if they are
@ -1051,7 +1069,7 @@ impl RootCollector<'_, 'v> {
debug!("RootCollector::push_if_root: found root def_id={:?}", def_id); debug!("RootCollector::push_if_root: found root def_id={:?}", def_id);
let instance = Instance::mono(self.tcx, def_id.to_def_id()); let instance = Instance::mono(self.tcx, def_id.to_def_id());
self.output.push(create_fn_mono_item(instance)); self.output.push(create_fn_mono_item(instance, DUMMY_SP));
} }
} }
@ -1088,7 +1106,7 @@ impl RootCollector<'_, 'v> {
.unwrap() .unwrap()
.unwrap(); .unwrap();
self.output.push(create_fn_mono_item(start_instance)); self.output.push(create_fn_mono_item(start_instance, DUMMY_SP));
} }
} }
@ -1100,7 +1118,7 @@ fn item_requires_monomorphization(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
fn create_mono_items_for_default_impls<'tcx>( fn create_mono_items_for_default_impls<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
item: &'tcx hir::Item<'tcx>, item: &'tcx hir::Item<'tcx>,
output: &mut Vec<MonoItem<'tcx>>, output: &mut Vec<Spanned<MonoItem<'tcx>>>,
) { ) {
match item.kind { match item.kind {
hir::ItemKind::Impl { ref generics, ref items, .. } => { hir::ItemKind::Impl { ref generics, ref items, .. } => {
@ -1145,8 +1163,9 @@ fn create_mono_items_for_default_impls<'tcx>(
.unwrap() .unwrap()
.unwrap(); .unwrap();
let mono_item = create_fn_mono_item(instance); let mono_item = create_fn_mono_item(instance, DUMMY_SP);
if mono_item.is_instantiable(tcx) && should_monomorphize_locally(tcx, &instance) if mono_item.node.is_instantiable(tcx)
&& should_monomorphize_locally(tcx, &instance)
{ {
output.push(mono_item); output.push(mono_item);
} }
@ -1158,14 +1177,18 @@ fn create_mono_items_for_default_impls<'tcx>(
} }
/// Scans the miri alloc in order to find function calls, closures, and drop-glue. /// Scans the miri alloc in order to find function calls, closures, and drop-glue.
fn collect_miri<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut Vec<MonoItem<'tcx>>) { fn collect_miri<'tcx>(
tcx: TyCtxt<'tcx>,
alloc_id: AllocId,
output: &mut Vec<Spanned<MonoItem<'tcx>>>,
) {
match tcx.global_alloc(alloc_id) { match tcx.global_alloc(alloc_id) {
GlobalAlloc::Static(def_id) => { GlobalAlloc::Static(def_id) => {
assert!(!tcx.is_thread_local_static(def_id)); assert!(!tcx.is_thread_local_static(def_id));
let instance = Instance::mono(tcx, def_id); let instance = Instance::mono(tcx, def_id);
if should_monomorphize_locally(tcx, &instance) { if should_monomorphize_locally(tcx, &instance) {
trace!("collecting static {:?}", def_id); trace!("collecting static {:?}", def_id);
output.push(MonoItem::Static(def_id)); output.push(dummy_spanned(MonoItem::Static(def_id)));
} }
} }
GlobalAlloc::Memory(alloc) => { GlobalAlloc::Memory(alloc) => {
@ -1179,7 +1202,7 @@ fn collect_miri<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut Vec<Mon
GlobalAlloc::Function(fn_instance) => { GlobalAlloc::Function(fn_instance) => {
if should_monomorphize_locally(tcx, &fn_instance) { if should_monomorphize_locally(tcx, &fn_instance) {
trace!("collecting {:?} with {:#?}", alloc_id, fn_instance); trace!("collecting {:?} with {:#?}", alloc_id, fn_instance);
output.push(create_fn_mono_item(fn_instance)); output.push(create_fn_mono_item(fn_instance, DUMMY_SP));
} }
} }
} }
@ -1189,7 +1212,7 @@ fn collect_miri<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut Vec<Mon
fn collect_neighbours<'tcx>( fn collect_neighbours<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
instance: Instance<'tcx>, instance: Instance<'tcx>,
output: &mut Vec<MonoItem<'tcx>>, output: &mut Vec<Spanned<MonoItem<'tcx>>>,
) { ) {
debug!("collect_neighbours: {:?}", instance.def_id()); debug!("collect_neighbours: {:?}", instance.def_id());
let body = tcx.instance_mir(instance.def); let body = tcx.instance_mir(instance.def);
@ -1207,7 +1230,7 @@ fn def_id_to_string(tcx: TyCtxt<'_>, def_id: LocalDefId) -> String {
fn collect_const_value<'tcx>( fn collect_const_value<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
value: ConstValue<'tcx>, value: ConstValue<'tcx>,
output: &mut Vec<MonoItem<'tcx>>, output: &mut Vec<Spanned<MonoItem<'tcx>>>,
) { ) {
match value { match value {
ConstValue::Scalar(Scalar::Ptr(ptr)) => collect_miri(tcx, ptr.alloc_id, output), ConstValue::Scalar(Scalar::Ptr(ptr)) => collect_miri(tcx, ptr.alloc_id, output),

View File

@ -1,9 +1,3 @@
//
// We get an error message at the top of file (dummy span).
// This is not helpful, but also kind of annoying to prevent,
// so for now just live with it.
// This test case was originally for issue #2258.
// build-fail // build-fail
trait ToOpt: Sized { trait ToOpt: Sized {
@ -23,11 +17,9 @@ impl<T:Clone> ToOpt for Option<T> {
} }
fn function<T:ToOpt + Clone>(counter: usize, t: T) { fn function<T:ToOpt + Clone>(counter: usize, t: T) {
//~^ ERROR reached the recursion limit while instantiating `function::<std::option::Option<
if counter > 0 { if counter > 0 {
function(counter - 1, t.to_option()); function(counter - 1, t.to_option());
// FIXME(#4287) Error message should be here. It should be //~^ ERROR reached the recursion limit while instantiating `function::<std::option::Option<
// a type error to instantiate `test` at a type other than T.
} }
} }

View File

@ -1,11 +1,16 @@
error: reached the recursion limit while instantiating `function::<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<usize>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` error: reached the recursion limit while instantiating `function::<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<usize>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
--> $DIR/infinite-instantiation.rs:25:1 --> $DIR/infinite-instantiation.rs:21:9
|
LL | function(counter - 1, t.to_option());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: `function` defined here
--> $DIR/infinite-instantiation.rs:19:1
| |
LL | / fn function<T:ToOpt + Clone>(counter: usize, t: T) { LL | / fn function<T:ToOpt + Clone>(counter: usize, t: T) {
LL | |
LL | | if counter > 0 { LL | | if counter > 0 {
LL | | function(counter - 1, t.to_option()); LL | | function(counter - 1, t.to_option());
... | LL | |
LL | | } LL | | }
LL | | } LL | | }
| |_^ | |_^

View File

@ -18,7 +18,6 @@ fn identity<T>(x: T) -> T {
} }
fn rec<T>(mut it: T) fn rec<T>(mut it: T)
//~^ ERROR reached the recursion limit while instantiating
where where
T: Iterator, T: Iterator,
{ {
@ -26,5 +25,6 @@ where
T::count(it); T::count(it);
} else { } else {
rec(identity(&mut it)) rec(identity(&mut it))
//~^ ERROR reached the recursion limit while instantiating
} }
} }

View File

@ -1,10 +1,16 @@
error: reached the recursion limit while instantiating `rec::<&mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut Empty>` error: reached the recursion limit while instantiating `rec::<&mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut Empty>`
--> $DIR/issue-67552.rs:27:9
|
LL | rec(identity(&mut it))
| ^^^^^^^^^^^^^^^^^^^^^^
|
note: `rec` defined here
--> $DIR/issue-67552.rs:20:1 --> $DIR/issue-67552.rs:20:1
| |
LL | / fn rec<T>(mut it: T) LL | / fn rec<T>(mut it: T)
LL | |
LL | | where LL | | where
LL | | T: Iterator, LL | | T: Iterator,
LL | | {
... | ... |
LL | | } LL | | }
LL | | } LL | | }

View File

@ -3,12 +3,10 @@
// build-fail // build-fail
fn generic<T>() { fn generic<T>() { //~ WARN function cannot return without recursing
generic::<Option<T>>(); generic::<Option<T>>();
} }
//~^^^ ERROR reached the recursion limit while instantiating `generic::<std::option::Option< //~^^ ERROR reached the recursion limit while instantiating `generic::<std::option::Option<
//~| WARN function cannot return without recursing
fn main () { fn main () {

View File

@ -10,6 +10,12 @@ LL | generic::<Option<T>>();
= help: a `loop` may express intention better if this is on purpose = help: a `loop` may express intention better if this is on purpose
error: reached the recursion limit while instantiating `generic::<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` error: reached the recursion limit while instantiating `generic::<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
--> $DIR/issue-8727.rs:7:5
|
LL | generic::<Option<T>>();
| ^^^^^^^^^^^^^^^^^^^^^^
|
note: `generic` defined here
--> $DIR/issue-8727.rs:6:1 --> $DIR/issue-8727.rs:6:1
| |
LL | / fn generic<T>() { LL | / fn generic<T>() {

View File

@ -1,4 +1,22 @@
error: reached the recursion limit while instantiating `std::intrinsics::drop_in_place::<S<fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(u32))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))>> - shim(Some(S<fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(u32))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))>))` error: reached the recursion limit while instantiating `std::intrinsics::drop_in_place::<S<fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(u32))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))>> - shim(Some(S<fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(u32))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))>))`
--> $SRC_DIR/libcore/ptr/mod.rs:LL:COL
|
LL | / pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
LL | | // Code here does not matter - this is replaced by the
LL | | // real drop glue by the compiler.
LL | | drop_in_place(to_drop)
LL | | }
| |_^
|
note: `std::intrinsics::drop_in_place` defined here
--> $SRC_DIR/libcore/ptr/mod.rs:LL:COL
|
LL | / pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
LL | | // Code here does not matter - this is replaced by the
LL | | // real drop glue by the compiler.
LL | | drop_in_place(to_drop)
LL | | }
| |_^
error: aborting due to previous error error: aborting due to previous error

View File

@ -12,11 +12,10 @@ impl<T:Dot> Dot for Cons<T> {
self.head * other.head + self.tail.dot(other.tail) self.head * other.head + self.tail.dot(other.tail)
} }
} }
fn test<T:Dot> (n:isize, i:isize, first:T, second:T) ->isize { //~ ERROR recursion limit fn test<T:Dot> (n:isize, i:isize, first:T, second:T) ->isize {
match n { 0 => {first.dot(second)} match n { 0 => {first.dot(second)}
// FIXME(#4287) Error message should be here. It should be
// a type error to instantiate `test` at a type other than T.
_ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})} _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})}
//~^ ERROR recursion limit
} }
} }
pub fn main() { pub fn main() {

View File

@ -1,11 +1,16 @@
error: reached the recursion limit while instantiating `test::<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Nil>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` error: reached the recursion limit while instantiating `test::<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Nil>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
--> $DIR/recursion.rs:17:11
|
LL | _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: `test` defined here
--> $DIR/recursion.rs:15:1 --> $DIR/recursion.rs:15:1
| |
LL | / fn test<T:Dot> (n:isize, i:isize, first:T, second:T) ->isize { LL | / fn test<T:Dot> (n:isize, i:isize, first:T, second:T) ->isize {
LL | | match n { 0 => {first.dot(second)} LL | | match n { 0 => {first.dot(second)}
LL | | // FIXME(#4287) Error message should be here. It should be
LL | | // a type error to instantiate `test` at a type other than T.
LL | | _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})} LL | | _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})}
LL | |
LL | | } LL | | }
LL | | } LL | | }
| |_^ | |_^