1
Fork 0

Re-implement a type-size based limit

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

View file

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

View file

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