1
Fork 0

Better handling for exponential-sized types in misc places

Mostly to fix ui/issues/issue-37311-type-length-limit/issue-37311.rs.

Most parts of the compiler can handle deeply nested types with a lot
of duplicates just fine, but some parts still attempt to naively
traverse type tree.

Before such problems were caught by type length limit check,
but now these places will have to be changed to handle
duplicated types gracefully.
This commit is contained in:
Valerii Lashmanov 2020-09-15 18:22:24 -05:00
parent 2f3296192b
commit 17d2e3b5d2
12 changed files with 91 additions and 43 deletions

View file

@ -4,6 +4,7 @@ use crate::ty::{self, DefIdTree, Ty, TyCtxt};
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::{CrateNum, DefId};
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
use rustc_middle::ty::walk::MiniSet;
// `pretty` is a separate module only for organization.
mod pretty;
@ -263,22 +264,34 @@ pub trait Printer<'tcx>: Sized {
/// function tries to find a "characteristic `DefId`" for a
/// type. It's just a heuristic so it makes some questionable
/// decisions and we may want to adjust it later.
pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
///
/// Visited set is needed in to avoid full iteration over
/// deeply nested tuples that have no DefId.
fn characteristic_def_id_of_type_cached<'a>(
ty: Ty<'a>,
visited: &mut MiniSet<Ty<'a>>,
) -> Option<DefId> {
match *ty.kind() {
ty::Adt(adt_def, _) => Some(adt_def.did),
ty::Dynamic(data, ..) => data.principal_def_id(),
ty::Array(subty, _) | ty::Slice(subty) => characteristic_def_id_of_type(subty),
ty::RawPtr(mt) => characteristic_def_id_of_type(mt.ty),
ty::Ref(_, ty, _) => characteristic_def_id_of_type(ty),
ty::Tuple(ref tys) => {
tys.iter().find_map(|ty| characteristic_def_id_of_type(ty.expect_ty()))
ty::Array(subty, _) | ty::Slice(subty) => {
characteristic_def_id_of_type_cached(subty, visited)
}
ty::RawPtr(mt) => characteristic_def_id_of_type_cached(mt.ty, visited),
ty::Ref(_, ty, _) => characteristic_def_id_of_type_cached(ty, visited),
ty::Tuple(ref tys) => tys.iter().find_map(|ty| {
let ty = ty.expect_ty();
if visited.insert(ty) {
return characteristic_def_id_of_type_cached(ty, visited);
}
return None;
}),
ty::FnDef(def_id, _)
| ty::Closure(def_id, _)
| ty::Generator(def_id, _, _)
@ -302,6 +315,9 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
| ty::Float(_) => None,
}
}
pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
characteristic_def_id_of_type_cached(ty, &mut MiniSet::new())
}
impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::RegionKind {
type Output = P::Region;

View file

@ -1264,6 +1264,7 @@ pub struct FmtPrinterData<'a, 'tcx, F> {
used_region_names: FxHashSet<Symbol>,
region_index: usize,
binder_depth: usize,
printed_type_count: usize,
pub region_highlight_mode: RegionHighlightMode,
@ -1294,6 +1295,7 @@ impl<F> FmtPrinter<'a, 'tcx, F> {
used_region_names: Default::default(),
region_index: 0,
binder_depth: 0,
printed_type_count: 0,
region_highlight_mode: RegionHighlightMode::default(),
name_resolver: None,
}))
@ -1411,8 +1413,14 @@ impl<F: fmt::Write> Printer<'tcx> for FmtPrinter<'_, 'tcx, F> {
self.pretty_print_region(region)
}
fn print_type(self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
self.pretty_print_type(ty)
fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
if self.tcx.sess.type_length_limit().value_within_limit(self.printed_type_count) {
self.printed_type_count += 1;
self.pretty_print_type(ty)
} else {
write!(self, "...")?;
Ok(self)
}
}
fn print_dyn_existential(