diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 5f51888019b9d..14f277d1767bb 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -13,6 +13,7 @@ use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::mir::*; use rustc::mir::transform::{MirSuite, MirPassIndex, MirSource}; use rustc::ty::TyCtxt; +use rustc::ty::item_path; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::{Idx}; use std::fmt::Display; @@ -48,7 +49,9 @@ pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return; } - let node_path = tcx.item_path_str(tcx.hir.local_def_id(source.item_id())); + let node_path = item_path::with_forced_impl_filename_line(|| { // see notes on #41697 below + tcx.item_path_str(tcx.hir.local_def_id(source.item_id())) + }); dump_matched_mir_node(tcx, pass_num, pass_name, &node_path, disambiguator, source, mir); for (index, promoted_mir) in mir.promoted.iter_enumerated() { @@ -67,7 +70,9 @@ pub fn dump_enabled<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Some(ref filters) => filters, }; let node_id = source.item_id(); - let node_path = tcx.item_path_str(tcx.hir.local_def_id(node_id)); + let node_path = item_path::with_forced_impl_filename_line(|| { // see notes on #41697 below + tcx.item_path_str(tcx.hir.local_def_id(node_id)) + }); filters.split("&") .any(|filter| { filter == "all" || @@ -76,6 +81,10 @@ pub fn dump_enabled<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }) } +// #41697 -- we use `with_forced_impl_filename_line()` because +// `item_path_str()` would otherwise trigger `type_of`, and this can +// run while we are already attempting to evaluate `type_of`. + fn dump_matched_mir_node<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pass_num: Option<(MirSuite, MirPassIndex)>, pass_name: &str, diff --git a/src/test/run-pass/issue-41697.rs b/src/test/run-pass/issue-41697.rs new file mode 100644 index 0000000000000..d59b6a16562ac --- /dev/null +++ b/src/test/run-pass/issue-41697.rs @@ -0,0 +1,50 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-Zdump-mir=NEVER_MATCHED + +// Regression test for #41697. Using dump-mir was triggering +// artificial cycles: during type-checking, we had to get the MIR for +// the constant expressions in `[u8; 2]`, which in turn would trigger +// an attempt to get the item-path, which in turn would request the +// types of the impl, which would trigger a cycle. We supressed this +// cycle now by forcing mir-dump to avoid asking for types of an impl. + +#![feature(rustc_attrs)] + +use std::sync::Arc; + +trait Foo { + fn get(&self) -> [u8; 2]; +} + +impl Foo for [u8; 2] { + fn get(&self) -> [u8; 2] { + *self + } +} + +struct Bar(T); + +fn unsize_fat_ptr<'a>(x: &'a Bar) -> &'a Bar { + x +} + +fn unsize_nested_fat_ptr(x: Arc) -> Arc { + x +} + +fn main() { + let x: Box> = Box::new(Bar([1,2])); + assert_eq!(unsize_fat_ptr(&*x).0.get(), [1, 2]); + + let x: Arc = Arc::new([3, 4]); + assert_eq!(unsize_nested_fat_ptr(x).get(), [3, 4]); +}