Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit d6646f6

Browse files
committedOct 3, 2020
Auto merge of #77490 - Mark-Simulacrum:beta-backports, r=Mark-Simulacrum
[beta] backports This backports a number of PRs to beta, not all of which have been approved (yet). * Switch to environment files to change the environment on GHA #77418 * cache types during normalization #76928 * Fixing memory exhaustion when formatting short code suggestion #76598 * Issue 72408 nested closures exponential #72412 r? `@Mark-Simulacrum`
2 parents 6d3dc31 + bf38fa5 commit d6646f6

File tree

33 files changed

+410
-94
lines changed

33 files changed

+410
-94
lines changed
 

‎Cargo.lock

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3424,6 +3424,7 @@ dependencies = [
34243424
name = "rustc_data_structures"
34253425
version = "0.0.0"
34263426
dependencies = [
3427+
"arrayvec",
34273428
"bitflags",
34283429
"cfg-if",
34293430
"crossbeam-utils 0.7.2",
@@ -3599,6 +3600,7 @@ dependencies = [
35993600
name = "rustc_infer"
36003601
version = "0.0.0"
36013602
dependencies = [
3603+
"arrayvec",
36023604
"rustc_ast",
36033605
"rustc_data_structures",
36043606
"rustc_errors",
@@ -3738,6 +3740,7 @@ dependencies = [
37383740
name = "rustc_middle"
37393741
version = "0.0.0"
37403742
dependencies = [
3743+
"arrayvec",
37413744
"bitflags",
37423745
"byteorder",
37433746
"chalk-ir",

‎src/ci/shared.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ function ciCommandAddPath {
104104
if isAzurePipelines; then
105105
echo "##vso[task.prependpath]${path}"
106106
elif isGitHubActions; then
107-
echo "::add-path::${path}"
107+
echo "${path}" >> "${GITHUB_PATH}"
108108
else
109109
echo "ciCommandAddPath only works inside CI!"
110110
exit 1
@@ -122,7 +122,7 @@ function ciCommandSetEnv {
122122
if isAzurePipelines; then
123123
echo "##vso[task.setvariable variable=${name}]${value}"
124124
elif isGitHubActions; then
125-
echo "::set-env name=${name}::${value}"
125+
echo "${name}=${value}" >> "${GITHUB_ENV}"
126126
else
127127
echo "ciCommandSetEnv only works inside CI!"
128128
exit 1

‎src/librustc_data_structures/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ path = "lib.rs"
1010
doctest = false
1111

1212
[dependencies]
13+
arrayvec = { version = "0.5.1", default-features = false }
1314
ena = "0.14"
1415
indexmap = "1.5.1"
1516
tracing = "0.1"

‎src/librustc_data_structures/lib.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,24 +85,26 @@ pub mod sorted_map;
8585
pub mod stable_set;
8686
#[macro_use]
8787
pub mod stable_hasher;
88+
mod atomic_ref;
89+
pub mod fingerprint;
90+
pub mod profiling;
8891
pub mod sharded;
8992
pub mod stack;
9093
pub mod sync;
9194
pub mod thin_vec;
9295
pub mod tiny_list;
9396
pub mod transitive_relation;
94-
pub use ena::undo_log;
95-
pub use ena::unify;
96-
mod atomic_ref;
97-
pub mod fingerprint;
98-
pub mod profiling;
9997
pub mod vec_linked_list;
10098
pub mod work_queue;
10199
pub use atomic_ref::AtomicRef;
102100
pub mod frozen;
101+
pub mod mini_map;
103102
pub mod tagged_ptr;
104103
pub mod temp_dir;
105104

105+
pub use ena::undo_log;
106+
pub use ena::unify;
107+
106108
pub struct OnDrop<F: Fn()>(pub F);
107109

108110
impl<F: Fn()> OnDrop<F> {
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
use crate::fx::FxHashMap;
2+
use arrayvec::ArrayVec;
3+
4+
use std::hash::Hash;
5+
6+
/// Small-storage-optimized implementation of a map
7+
/// made specifically for caching results.
8+
///
9+
/// Stores elements in a small array up to a certain length
10+
/// and switches to `HashMap` when that length is exceeded.
11+
pub enum MiniMap<K, V> {
12+
Array(ArrayVec<[(K, V); 8]>),
13+
Map(FxHashMap<K, V>),
14+
}
15+
16+
impl<K: Eq + Hash, V> MiniMap<K, V> {
17+
/// Creates an empty `MiniMap`.
18+
pub fn new() -> Self {
19+
MiniMap::Array(ArrayVec::new())
20+
}
21+
22+
/// Inserts or updates value in the map.
23+
pub fn insert(&mut self, key: K, value: V) {
24+
match self {
25+
MiniMap::Array(array) => {
26+
for pair in array.iter_mut() {
27+
if pair.0 == key {
28+
pair.1 = value;
29+
return;
30+
}
31+
}
32+
if let Err(error) = array.try_push((key, value)) {
33+
let mut map: FxHashMap<K, V> = array.drain(..).collect();
34+
let (key, value) = error.element();
35+
map.insert(key, value);
36+
*self = MiniMap::Map(map);
37+
}
38+
}
39+
MiniMap::Map(map) => {
40+
map.insert(key, value);
41+
}
42+
}
43+
}
44+
45+
/// Return value by key if any.
46+
pub fn get(&self, key: &K) -> Option<&V> {
47+
match self {
48+
MiniMap::Array(array) => {
49+
for pair in array {
50+
if pair.0 == *key {
51+
return Some(&pair.1);
52+
}
53+
}
54+
return None;
55+
}
56+
MiniMap::Map(map) => {
57+
return map.get(key);
58+
}
59+
}
60+
}
61+
}

‎src/librustc_errors/emitter.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -959,15 +959,15 @@ impl EmitterWriter {
959959
'_',
960960
line_offset + pos,
961961
width_offset + depth,
962-
code_offset + annotation.start_col - left,
962+
(code_offset + annotation.start_col).saturating_sub(left),
963963
style,
964964
);
965965
}
966966
_ if self.teach => {
967967
buffer.set_style_range(
968968
line_offset,
969-
code_offset + annotation.start_col - left,
970-
code_offset + annotation.end_col - left,
969+
(code_offset + annotation.start_col).saturating_sub(left),
970+
(code_offset + annotation.end_col).saturating_sub(left),
971971
style,
972972
annotation.is_primary,
973973
);

‎src/librustc_index/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ path = "lib.rs"
1010
doctest = false
1111

1212
[dependencies]
13-
arrayvec = "0.5.1"
13+
arrayvec = { version = "0.5.1", default-features = false }
1414
rustc_serialize = { path = "../librustc_serialize" }
1515
rustc_macros = { path = "../librustc_macros" }

‎src/librustc_infer/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@ rustc_serialize = { path = "../librustc_serialize" }
2323
rustc_span = { path = "../librustc_span" }
2424
rustc_target = { path = "../librustc_target" }
2525
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
26+
arrayvec = { version = "0.5.1", default-features = false }
2627
rustc_ast = { path = "../librustc_ast" }

‎src/librustc_infer/infer/combine.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ use super::{InferCtxt, MiscVariable, TypeTrace};
3535
use crate::traits::{Obligation, PredicateObligations};
3636

3737
use rustc_ast as ast;
38+
use rustc_data_structures::mini_map::MiniMap;
3839
use rustc_hir::def_id::DefId;
3940
use rustc_middle::traits::ObligationCause;
4041
use rustc_middle::ty::error::TypeError;
@@ -379,6 +380,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
379380
needs_wf: false,
380381
root_ty: ty,
381382
param_env: self.param_env,
383+
cache: MiniMap::new(),
382384
};
383385

384386
let ty = match generalize.relate(ty, ty) {
@@ -438,6 +440,8 @@ struct Generalizer<'cx, 'tcx> {
438440
root_ty: Ty<'tcx>,
439441

440442
param_env: ty::ParamEnv<'tcx>,
443+
444+
cache: MiniMap<Ty<'tcx>, RelateResult<'tcx, Ty<'tcx>>>,
441445
}
442446

443447
/// Result from a generalization operation. This includes
@@ -535,13 +539,16 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
535539
fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
536540
assert_eq!(t, t2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
537541

542+
if let Some(result) = self.cache.get(&t) {
543+
return result.clone();
544+
}
538545
debug!("generalize: t={:?}", t);
539546

540547
// Check to see whether the type we are generalizing references
541548
// any other type variable related to `vid` via
542549
// subtyping. This is basically our "occurs check", preventing
543550
// us from creating infinitely sized types.
544-
match t.kind {
551+
let result = match t.kind {
545552
ty::Infer(ty::TyVar(vid)) => {
546553
let vid = self.infcx.inner.borrow_mut().type_variables().root_var(vid);
547554
let sub_vid = self.infcx.inner.borrow_mut().type_variables().sub_root_var(vid);
@@ -598,7 +605,10 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
598605
Ok(t)
599606
}
600607
_ => relate::super_relate_tys(self, t, t),
601-
}
608+
};
609+
610+
self.cache.insert(t, result.clone());
611+
return result;
602612
}
603613

604614
fn regions(

‎src/librustc_infer/infer/outlives/verify.rs

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::infer::{GenericKind, VerifyBound};
33
use rustc_data_structures::captures::Captures;
44
use rustc_hir::def_id::DefId;
55
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
6+
use rustc_middle::ty::walk::MiniSet;
67
use rustc_middle::ty::{self, Ty, TyCtxt};
78

89
/// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
@@ -31,16 +32,23 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
3132
/// Returns a "verify bound" that encodes what we know about
3233
/// `generic` and the regions it outlives.
3334
pub fn generic_bound(&self, generic: GenericKind<'tcx>) -> VerifyBound<'tcx> {
35+
let mut visited = MiniSet::new();
3436
match generic {
3537
GenericKind::Param(param_ty) => self.param_bound(param_ty),
36-
GenericKind::Projection(projection_ty) => self.projection_bound(projection_ty),
38+
GenericKind::Projection(projection_ty) => {
39+
self.projection_bound(projection_ty, &mut visited)
40+
}
3741
}
3842
}
3943

40-
fn type_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
44+
fn type_bound(
45+
&self,
46+
ty: Ty<'tcx>,
47+
visited: &mut MiniSet<GenericArg<'tcx>>,
48+
) -> VerifyBound<'tcx> {
4149
match ty.kind {
4250
ty::Param(p) => self.param_bound(p),
43-
ty::Projection(data) => self.projection_bound(data),
51+
ty::Projection(data) => self.projection_bound(data, visited),
4452
ty::FnDef(_, substs) => {
4553
// HACK(eddyb) ignore lifetimes found shallowly in `substs`.
4654
// This is inconsistent with `ty::Adt` (including all substs),
@@ -50,9 +58,9 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
5058
let mut bounds = substs
5159
.iter()
5260
.filter_map(|child| match child.unpack() {
53-
GenericArgKind::Type(ty) => Some(self.type_bound(ty)),
61+
GenericArgKind::Type(ty) => Some(self.type_bound(ty, visited)),
5462
GenericArgKind::Lifetime(_) => None,
55-
GenericArgKind::Const(_) => Some(self.recursive_bound(child)),
63+
GenericArgKind::Const(_) => Some(self.recursive_bound(child, visited)),
5664
})
5765
.filter(|bound| {
5866
// Remove bounds that must hold, since they are not interesting.
@@ -66,7 +74,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
6674
),
6775
}
6876
}
69-
_ => self.recursive_bound(ty.into()),
77+
_ => self.recursive_bound(ty.into(), visited),
7078
}
7179
}
7280

@@ -137,7 +145,11 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
137145
self.declared_projection_bounds_from_trait(projection_ty)
138146
}
139147

140-
pub fn projection_bound(&self, projection_ty: ty::ProjectionTy<'tcx>) -> VerifyBound<'tcx> {
148+
pub fn projection_bound(
149+
&self,
150+
projection_ty: ty::ProjectionTy<'tcx>,
151+
visited: &mut MiniSet<GenericArg<'tcx>>,
152+
) -> VerifyBound<'tcx> {
141153
debug!("projection_bound(projection_ty={:?})", projection_ty);
142154

143155
let projection_ty_as_ty =
@@ -166,21 +178,25 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
166178

167179
// see the extensive comment in projection_must_outlive
168180
let ty = self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs);
169-
let recursive_bound = self.recursive_bound(ty.into());
181+
let recursive_bound = self.recursive_bound(ty.into(), visited);
170182

171183
VerifyBound::AnyBound(env_bounds.chain(trait_bounds).collect()).or(recursive_bound)
172184
}
173185

174-
fn recursive_bound(&self, parent: GenericArg<'tcx>) -> VerifyBound<'tcx> {
186+
fn recursive_bound(
187+
&self,
188+
parent: GenericArg<'tcx>,
189+
visited: &mut MiniSet<GenericArg<'tcx>>,
190+
) -> VerifyBound<'tcx> {
175191
let mut bounds = parent
176-
.walk_shallow()
192+
.walk_shallow(visited)
177193
.filter_map(|child| match child.unpack() {
178-
GenericArgKind::Type(ty) => Some(self.type_bound(ty)),
194+
GenericArgKind::Type(ty) => Some(self.type_bound(ty, visited)),
179195
GenericArgKind::Lifetime(lt) => {
180196
// Ignore late-bound regions.
181197
if !lt.is_late_bound() { Some(VerifyBound::OutlivedBy(lt)) } else { None }
182198
}
183-
GenericArgKind::Const(_) => Some(self.recursive_bound(child)),
199+
GenericArgKind::Const(_) => Some(self.recursive_bound(child, visited)),
184200
})
185201
.filter(|bound| {
186202
// Remove bounds that must hold, since they are not interesting.

‎src/librustc_middle/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,6 @@ rustc_span = { path = "../librustc_span" }
3131
byteorder = { version = "1.3" }
3232
chalk-ir = "0.14.0"
3333
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
34+
arrayvec = { version = "0.5.1", default-features = false }
3435
measureme = "0.7.1"
3536
rustc_session = { path = "../librustc_session" }

‎src/librustc_middle/ty/outlives.rs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// RFC for reference.
44

55
use crate::ty::subst::{GenericArg, GenericArgKind};
6+
use crate::ty::walk::MiniSet;
67
use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
78
use smallvec::SmallVec;
89

@@ -50,12 +51,18 @@ impl<'tcx> TyCtxt<'tcx> {
5051
/// Push onto `out` all the things that must outlive `'a` for the condition
5152
/// `ty0: 'a` to hold. Note that `ty0` must be a **fully resolved type**.
5253
pub fn push_outlives_components(self, ty0: Ty<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>) {
53-
compute_components(self, ty0, out);
54+
let mut visited = MiniSet::new();
55+
compute_components(self, ty0, out, &mut visited);
5456
debug!("components({:?}) = {:?}", ty0, out);
5557
}
5658
}
5759

58-
fn compute_components(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>) {
60+
fn compute_components(
61+
tcx: TyCtxt<'tcx>,
62+
ty: Ty<'tcx>,
63+
out: &mut SmallVec<[Component<'tcx>; 4]>,
64+
visited: &mut MiniSet<GenericArg<'tcx>>,
65+
) {
5966
// Descend through the types, looking for the various "base"
6067
// components and collecting them into `out`. This is not written
6168
// with `collect()` because of the need to sometimes skip subtrees
@@ -73,31 +80,31 @@ fn compute_components(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, out: &mut SmallVec<[Compo
7380
for child in substs {
7481
match child.unpack() {
7582
GenericArgKind::Type(ty) => {
76-
compute_components(tcx, ty, out);
83+
compute_components(tcx, ty, out, visited);
7784
}
7885
GenericArgKind::Lifetime(_) => {}
7986
GenericArgKind::Const(_) => {
80-
compute_components_recursive(tcx, child, out);
87+
compute_components_recursive(tcx, child, out, visited);
8188
}
8289
}
8390
}
8491
}
8592

8693
ty::Array(element, _) => {
8794
// Don't look into the len const as it doesn't affect regions
88-
compute_components(tcx, element, out);
95+
compute_components(tcx, element, out, visited);
8996
}
9097

9198
ty::Closure(_, ref substs) => {
9299
for upvar_ty in substs.as_closure().upvar_tys() {
93-
compute_components(tcx, upvar_ty, out);
100+
compute_components(tcx, upvar_ty, out, visited);
94101
}
95102
}
96103

97104
ty::Generator(_, ref substs, _) => {
98105
// Same as the closure case
99106
for upvar_ty in substs.as_generator().upvar_tys() {
100-
compute_components(tcx, upvar_ty, out);
107+
compute_components(tcx, upvar_ty, out, visited);
101108
}
102109

103110
// We ignore regions in the generator interior as we don't
@@ -135,7 +142,8 @@ fn compute_components(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, out: &mut SmallVec<[Compo
135142
// OutlivesProjectionComponents. Continue walking
136143
// through and constrain Pi.
137144
let mut subcomponents = smallvec![];
138-
compute_components_recursive(tcx, ty.into(), &mut subcomponents);
145+
let mut subvisited = MiniSet::new();
146+
compute_components_recursive(tcx, ty.into(), &mut subcomponents, &mut subvisited);
139147
out.push(Component::EscapingProjection(subcomponents.into_iter().collect()));
140148
}
141149
}
@@ -177,7 +185,7 @@ fn compute_components(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, out: &mut SmallVec<[Compo
177185
// the "bound regions list". In our representation, no such
178186
// list is maintained explicitly, because bound regions
179187
// themselves can be readily identified.
180-
compute_components_recursive(tcx, ty.into(), out);
188+
compute_components_recursive(tcx, ty.into(), out, visited);
181189
}
182190
}
183191
}
@@ -186,11 +194,12 @@ fn compute_components_recursive(
186194
tcx: TyCtxt<'tcx>,
187195
parent: GenericArg<'tcx>,
188196
out: &mut SmallVec<[Component<'tcx>; 4]>,
197+
visited: &mut MiniSet<GenericArg<'tcx>>,
189198
) {
190-
for child in parent.walk_shallow() {
199+
for child in parent.walk_shallow(visited) {
191200
match child.unpack() {
192201
GenericArgKind::Type(ty) => {
193-
compute_components(tcx, ty, out);
202+
compute_components(tcx, ty, out, visited);
194203
}
195204
GenericArgKind::Lifetime(lt) => {
196205
// Ignore late-bound regions.
@@ -199,7 +208,7 @@ fn compute_components_recursive(
199208
}
200209
}
201210
GenericArgKind::Const(_) => {
202-
compute_components_recursive(tcx, child, out);
211+
compute_components_recursive(tcx, child, out, visited);
203212
}
204213
}
205214
}

‎src/librustc_middle/ty/print/mod.rs

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::ty::{self, DefIdTree, Ty, TyCtxt};
44
use rustc_data_structures::fx::FxHashSet;
55
use rustc_hir::def_id::{CrateNum, DefId};
66
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
7+
use rustc_middle::ty::walk::MiniSet;
78

89
// `pretty` is a separate module only for organization.
910
mod pretty;
@@ -265,21 +266,33 @@ pub trait Printer<'tcx>: Sized {
265266
/// function tries to find a "characteristic `DefId`" for a
266267
/// type. It's just a heuristic so it makes some questionable
267268
/// decisions and we may want to adjust it later.
268-
pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
269+
///
270+
/// Visited set is needed to avoid full iteration over
271+
/// deeply nested tuples that have no DefId.
272+
fn characteristic_def_id_of_type_cached<'a>(
273+
ty: Ty<'a>,
274+
visited: &mut MiniSet<Ty<'a>>,
275+
) -> Option<DefId> {
269276
match ty.kind {
270277
ty::Adt(adt_def, _) => Some(adt_def.did),
271278

272279
ty::Dynamic(data, ..) => data.principal_def_id(),
273280

274-
ty::Array(subty, _) | ty::Slice(subty) => characteristic_def_id_of_type(subty),
281+
ty::Array(subty, _) | ty::Slice(subty) => {
282+
characteristic_def_id_of_type_cached(subty, visited)
283+
}
275284

276-
ty::RawPtr(mt) => characteristic_def_id_of_type(mt.ty),
285+
ty::RawPtr(mt) => characteristic_def_id_of_type_cached(mt.ty, visited),
277286

278-
ty::Ref(_, ty, _) => characteristic_def_id_of_type(ty),
287+
ty::Ref(_, ty, _) => characteristic_def_id_of_type_cached(ty, visited),
279288

280-
ty::Tuple(ref tys) => {
281-
tys.iter().find_map(|ty| characteristic_def_id_of_type(ty.expect_ty()))
282-
}
289+
ty::Tuple(ref tys) => tys.iter().find_map(|ty| {
290+
let ty = ty.expect_ty();
291+
if visited.insert(ty) {
292+
return characteristic_def_id_of_type_cached(ty, visited);
293+
}
294+
return None;
295+
}),
283296

284297
ty::FnDef(def_id, _)
285298
| ty::Closure(def_id, _)
@@ -304,6 +317,9 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
304317
| ty::Float(_) => None,
305318
}
306319
}
320+
pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
321+
characteristic_def_id_of_type_cached(ty, &mut MiniSet::new())
322+
}
307323

308324
impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::RegionKind {
309325
type Output = P::Region;

‎src/librustc_middle/ty/print/pretty.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,6 +1226,7 @@ pub struct FmtPrinterData<'a, 'tcx, F> {
12261226
used_region_names: FxHashSet<Symbol>,
12271227
region_index: usize,
12281228
binder_depth: usize,
1229+
printed_type_count: usize,
12291230

12301231
pub region_highlight_mode: RegionHighlightMode,
12311232

@@ -1256,6 +1257,7 @@ impl<F> FmtPrinter<'a, 'tcx, F> {
12561257
used_region_names: Default::default(),
12571258
region_index: 0,
12581259
binder_depth: 0,
1260+
printed_type_count: 0,
12591261
region_highlight_mode: RegionHighlightMode::default(),
12601262
name_resolver: None,
12611263
}))
@@ -1368,8 +1370,14 @@ impl<F: fmt::Write> Printer<'tcx> for FmtPrinter<'_, 'tcx, F> {
13681370
self.pretty_print_region(region)
13691371
}
13701372

1371-
fn print_type(self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
1372-
self.pretty_print_type(ty)
1373+
fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
1374+
if self.tcx.sess.type_length_limit().value_within_limit(self.printed_type_count) {
1375+
self.printed_type_count += 1;
1376+
self.pretty_print_type(ty)
1377+
} else {
1378+
write!(self, "...")?;
1379+
Ok(self)
1380+
}
13731381
}
13741382

13751383
fn print_dyn_existential(

‎src/librustc_middle/ty/walk.rs

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,50 @@
33
44
use crate::ty;
55
use crate::ty::subst::{GenericArg, GenericArgKind};
6+
use arrayvec::ArrayVec;
7+
use rustc_data_structures::fx::FxHashSet;
68
use smallvec::{self, SmallVec};
9+
use std::hash::Hash;
10+
11+
/// Small-storage-optimized implementation of a set
12+
/// made specifically for walking type tree.
13+
///
14+
/// Stores elements in a small array up to a certain length
15+
/// and switches to `HashSet` when that length is exceeded.
16+
pub enum MiniSet<T> {
17+
Array(ArrayVec<[T; 8]>),
18+
Set(FxHashSet<T>),
19+
}
20+
21+
impl<T: Eq + Hash + Copy> MiniSet<T> {
22+
/// Creates an empty `MiniSet`.
23+
pub fn new() -> Self {
24+
MiniSet::Array(ArrayVec::new())
25+
}
26+
27+
/// Adds a value to the set.
28+
///
29+
/// If the set did not have this value present, true is returned.
30+
///
31+
/// If the set did have this value present, false is returned.
32+
pub fn insert(&mut self, elem: T) -> bool {
33+
match self {
34+
MiniSet::Array(array) => {
35+
if array.iter().any(|e| *e == elem) {
36+
false
37+
} else {
38+
if array.try_push(elem).is_err() {
39+
let mut set: FxHashSet<T> = array.iter().copied().collect();
40+
set.insert(elem);
41+
*self = MiniSet::Set(set);
42+
}
43+
true
44+
}
45+
}
46+
MiniSet::Set(set) => set.insert(elem),
47+
}
48+
}
49+
}
750

851
// The TypeWalker's stack is hot enough that it's worth going to some effort to
952
// avoid heap allocations.
@@ -12,11 +55,20 @@ type TypeWalkerStack<'tcx> = SmallVec<[GenericArg<'tcx>; 8]>;
1255
pub struct TypeWalker<'tcx> {
1356
stack: TypeWalkerStack<'tcx>,
1457
last_subtree: usize,
58+
visited: MiniSet<GenericArg<'tcx>>,
1559
}
1660

61+
/// An iterator for walking the type tree.
62+
///
63+
/// It's very easy to produce a deeply
64+
/// nested type tree with a lot of
65+
/// identical subtrees. In order to work efficiently
66+
/// in this situation walker only visits each type once.
67+
/// It maintains a set of visited types and
68+
/// skips any types that are already there.
1769
impl<'tcx> TypeWalker<'tcx> {
18-
pub fn new(root: GenericArg<'tcx>) -> TypeWalker<'tcx> {
19-
TypeWalker { stack: smallvec![root], last_subtree: 1 }
70+
pub fn new(root: GenericArg<'tcx>) -> Self {
71+
Self { stack: smallvec![root], last_subtree: 1, visited: MiniSet::new() }
2072
}
2173

2274
/// Skips the subtree corresponding to the last type
@@ -41,11 +93,15 @@ impl<'tcx> Iterator for TypeWalker<'tcx> {
4193

4294
fn next(&mut self) -> Option<GenericArg<'tcx>> {
4395
debug!("next(): stack={:?}", self.stack);
44-
let next = self.stack.pop()?;
45-
self.last_subtree = self.stack.len();
46-
push_inner(&mut self.stack, next);
47-
debug!("next: stack={:?}", self.stack);
48-
Some(next)
96+
loop {
97+
let next = self.stack.pop()?;
98+
self.last_subtree = self.stack.len();
99+
if self.visited.insert(next) {
100+
push_inner(&mut self.stack, next);
101+
debug!("next: stack={:?}", self.stack);
102+
return Some(next);
103+
}
104+
}
49105
}
50106
}
51107

@@ -67,9 +123,17 @@ impl GenericArg<'tcx> {
67123
/// Iterator that walks the immediate children of `self`. Hence
68124
/// `Foo<Bar<i32>, u32>` yields the sequence `[Bar<i32>, u32]`
69125
/// (but not `i32`, like `walk`).
70-
pub fn walk_shallow(self) -> impl Iterator<Item = GenericArg<'tcx>> {
126+
///
127+
/// Iterator only walks items once.
128+
/// It accepts visited set, updates it with all visited types
129+
/// and skips any types that are already there.
130+
pub fn walk_shallow(
131+
self,
132+
visited: &mut MiniSet<GenericArg<'tcx>>,
133+
) -> impl Iterator<Item = GenericArg<'tcx>> {
71134
let mut stack = SmallVec::new();
72135
push_inner(&mut stack, self);
136+
stack.retain(|a| visited.insert(*a));
73137
stack.into_iter()
74138
}
75139
}

‎src/librustc_mir/monomorphize/collector.rs

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,29 @@ fn record_accesses<'a, 'tcx: 'a>(
419419
inlining_map.lock_mut().record_accesses(caller, &accesses);
420420
}
421421

422+
// Shrinks string by keeping prefix and suffix of given sizes.
423+
fn shrink(s: String, before: usize, after: usize) -> String {
424+
// An iterator of all byte positions including the end of the string.
425+
let positions = || s.char_indices().map(|(i, _)| i).chain(iter::once(s.len()));
426+
427+
let shrunk = format!(
428+
"{before}...{after}",
429+
before = &s[..positions().nth(before).unwrap_or(s.len())],
430+
after = &s[positions().rev().nth(after).unwrap_or(0)..],
431+
);
432+
433+
// Only use the shrunk version if it's really shorter.
434+
// This also avoids the case where before and after slices overlap.
435+
if shrunk.len() < s.len() { shrunk } else { s }
436+
}
437+
438+
// Format instance name that is already known to be too long for rustc.
439+
// Show only the first and last 32 characters to avoid blasting
440+
// the user's terminal with thousands of lines of type-name.
441+
fn shrunk_instance_name(instance: &Instance<'tcx>) -> String {
442+
shrink(instance.to_string(), 32, 32)
443+
}
444+
422445
fn check_recursion_limit<'tcx>(
423446
tcx: TyCtxt<'tcx>,
424447
instance: Instance<'tcx>,
@@ -441,7 +464,10 @@ fn check_recursion_limit<'tcx>(
441464
// more than the recursion limit is assumed to be causing an
442465
// infinite expansion.
443466
if !tcx.sess.recursion_limit().value_within_limit(adjusted_recursion_depth) {
444-
let error = format!("reached the recursion limit while instantiating `{}`", instance);
467+
let error = format!(
468+
"reached the recursion limit while instantiating `{}`",
469+
shrunk_instance_name(&instance),
470+
);
445471
let mut err = tcx.sess.struct_span_fatal(span, &error);
446472
err.span_note(
447473
tcx.def_span(def_id),
@@ -475,26 +501,9 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
475501
//
476502
// Bail out in these cases to avoid that bad user experience.
477503
if !tcx.sess.type_length_limit().value_within_limit(type_length) {
478-
// The instance name is already known to be too long for rustc.
479-
// Show only the first and last 32 characters to avoid blasting
480-
// the user's terminal with thousands of lines of type-name.
481-
let shrink = |s: String, before: usize, after: usize| {
482-
// An iterator of all byte positions including the end of the string.
483-
let positions = || s.char_indices().map(|(i, _)| i).chain(iter::once(s.len()));
484-
485-
let shrunk = format!(
486-
"{before}...{after}",
487-
before = &s[..positions().nth(before).unwrap_or(s.len())],
488-
after = &s[positions().rev().nth(after).unwrap_or(0)..],
489-
);
490-
491-
// Only use the shrunk version if it's really shorter.
492-
// This also avoids the case where before and after slices overlap.
493-
if shrunk.len() < s.len() { shrunk } else { s }
494-
};
495504
let msg = format!(
496505
"reached the type-length limit while instantiating `{}`",
497-
shrink(instance.to_string(), 32, 32)
506+
shrunk_instance_name(&instance),
498507
);
499508
let mut diag = tcx.sess.struct_span_fatal(tcx.def_span(instance.def_id()), &msg);
500509
diag.note(&format!(

‎src/librustc_parse/parser/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -694,9 +694,13 @@ impl<'a> Parser<'a> {
694694
Ok(t) => {
695695
// Parsed successfully, therefore most probably the code only
696696
// misses a separator.
697+
let mut exp_span = self.sess.source_map().next_point(sp);
698+
if self.sess.source_map().is_multiline(exp_span) {
699+
exp_span = sp;
700+
}
697701
expect_err
698702
.span_suggestion_short(
699-
self.sess.source_map().next_point(sp),
703+
exp_span,
700704
&format!("missing `{}`", token_str),
701705
token_str,
702706
Applicability::MaybeIncorrect,

‎src/librustc_trait_selection/traits/query/normalize.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::infer::canonical::OriginalQueryValues;
77
use crate::infer::{InferCtxt, InferOk};
88
use crate::traits::error_reporting::InferCtxtExt;
99
use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
10+
use rustc_data_structures::mini_map::MiniMap;
1011
use rustc_data_structures::stack::ensure_sufficient_stack;
1112
use rustc_infer::traits::Normalized;
1213
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
@@ -57,6 +58,7 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
5758
param_env: self.param_env,
5859
obligations: vec![],
5960
error: false,
61+
cache: MiniMap::new(),
6062
anon_depth: 0,
6163
};
6264

@@ -85,6 +87,7 @@ struct QueryNormalizer<'cx, 'tcx> {
8587
cause: &'cx ObligationCause<'tcx>,
8688
param_env: ty::ParamEnv<'tcx>,
8789
obligations: Vec<PredicateObligation<'tcx>>,
90+
cache: MiniMap<Ty<'tcx>, Ty<'tcx>>,
8891
error: bool,
8992
anon_depth: usize,
9093
}
@@ -99,8 +102,12 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
99102
return ty;
100103
}
101104

105+
if let Some(ty) = self.cache.get(&ty) {
106+
return ty;
107+
}
108+
102109
let ty = ty.super_fold_with(self);
103-
match ty.kind {
110+
let res = (|| match ty.kind {
104111
ty::Opaque(def_id, substs) => {
105112
// Only normalize `impl Trait` after type-checking, usually in codegen.
106113
match self.param_env.reveal() {
@@ -197,7 +204,9 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
197204
}
198205

199206
_ => ty,
200-
}
207+
})();
208+
self.cache.insert(ty, res);
209+
res
201210
}
202211

203212
fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// build-pass
2+
3+
// Closures include captured types twice in a type tree.
4+
//
5+
// Wrapping one closure with another leads to doubling
6+
// the amount of types in the type tree.
7+
//
8+
// This test ensures that rust can handle
9+
// deeply nested type trees with a lot
10+
// of duplicated subtrees.
11+
12+
fn dup(f: impl Fn(i32) -> i32) -> impl Fn(i32) -> i32 {
13+
move |a| f(a * 2)
14+
}
15+
16+
fn main() {
17+
let f = |a| a;
18+
19+
let f = dup(f);
20+
let f = dup(f);
21+
let f = dup(f);
22+
let f = dup(f);
23+
let f = dup(f);
24+
25+
let f = dup(f);
26+
let f = dup(f);
27+
let f = dup(f);
28+
let f = dup(f);
29+
let f = dup(f);
30+
31+
let f = dup(f);
32+
let f = dup(f);
33+
let f = dup(f);
34+
let f = dup(f);
35+
let f = dup(f);
36+
37+
let f = dup(f);
38+
let f = dup(f);
39+
let f = dup(f);
40+
let f = dup(f);
41+
let f = dup(f);
42+
43+
// Compiler dies around here if it tries
44+
// to walk the tree exhaustively.
45+
46+
let f = dup(f);
47+
let f = dup(f);
48+
let f = dup(f);
49+
let f = dup(f);
50+
let f = dup(f);
51+
52+
let f = dup(f);
53+
let f = dup(f);
54+
let f = dup(f);
55+
let f = dup(f);
56+
let f = dup(f);
57+
58+
println!("Type size was at least {}", f(1));
59+
}

‎src/test/ui/infinite/infinite-instantiation.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
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>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
1+
error: reached the recursion limit while instantiating `function::<std::option::Option<s...>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
22
--> $DIR/infinite-instantiation.rs:21:9
33
|
44
LL | function(counter - 1, t.to_option());

‎src/test/ui/issue-76597.fixed

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// run-rustfix
2+
3+
#![allow(dead_code)]
4+
#![allow(unused_variables)]
5+
fn f(
6+
x: u8,
7+
y: u8,
8+
) {}
9+
//~^^ ERROR: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `y`
10+
11+
fn main() {}

‎src/test/ui/issue-76597.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// run-rustfix
2+
3+
#![allow(dead_code)]
4+
#![allow(unused_variables)]
5+
fn f(
6+
x: u8
7+
y: u8,
8+
) {}
9+
//~^^ ERROR: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `y`
10+
11+
fn main() {}

‎src/test/ui/issue-76597.stderr

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `y`
2+
--> $DIR/issue-76597.rs:7:38
3+
|
4+
LL | ... x: u8
5+
| -
6+
| |
7+
| expected one of 7 possible tokens
8+
| help: missing `,`
9+
LL | ... y: u8,
10+
| ^ unexpected token
11+
12+
error: aborting due to previous error
13+

‎src/test/ui/issues/issue-22638.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ struct D (Box<A>);
5151

5252
impl D {
5353
pub fn matches<F: Fn()>(&self, f: &F) {
54-
//~^ ERROR reached the type-length limit while instantiating `D::matches::<[closure
5554
let &D(ref a) = self;
5655
a.matches(f)
56+
//~^ ERROR reached the recursion limit while instantiating `A::matches::<[closure
5757
}
5858
}
5959

‎src/test/ui/issues/issue-22638.stderr

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
error: reached the type-length limit while instantiating `D::matches::$CLOSURE`
2-
--> $DIR/issue-22638.rs:53:5
1+
error: reached the recursion limit while instantiating `A::matches::$CLOSURE`
2+
--> $DIR/issue-22638.rs:55:9
3+
|
4+
LL | a.matches(f)
5+
| ^^^^^^^^^^^^
6+
|
7+
note: `A::matches` defined here
8+
--> $DIR/issue-22638.rs:14:5
39
|
410
LL | pub fn matches<F: Fn()>(&self, f: &F) {
511
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6-
|
7-
= note: consider adding a `#![type_length_limit="30408681"]` attribute to your crate
812

913
error: aborting due to previous error
1014

‎src/test/ui/issues/issue-37311-type-length-limit/issue-37311.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ trait Foo {
1212

1313
impl<T> Foo for T {
1414
#[allow(unconditional_recursion)]
15-
fn recurse(&self) { //~ ERROR reached the type-length limit
16-
(self, self).recurse();
15+
fn recurse(&self) {
16+
(self, self).recurse(); //~ ERROR reached the recursion limit
1717
}
1818
}
1919

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
error: reached the type-length limit while instantiating `<(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(...))))))))))))))) as Foo>::recurse`
1+
error: reached the recursion limit while instantiating `<(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(.....), ...), ...) as Foo>::recurse`
2+
--> $DIR/issue-37311.rs:16:9
3+
|
4+
LL | (self, self).recurse();
5+
| ^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
note: `<T as Foo>::recurse` defined here
28
--> $DIR/issue-37311.rs:15:5
39
|
410
LL | fn recurse(&self) {
511
| ^^^^^^^^^^^^^^^^^
6-
|
7-
= note: consider adding a `#![type_length_limit="2097149"]` attribute to your crate
812

913
error: aborting due to previous error
1014

‎src/test/ui/issues/issue-67552.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
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>`
1+
error: reached the recursion limit while instantiating `rec::<&mut &mut &mut &mut &mut &... &mut &mut &mut &mut &mut Empty>`
22
--> $DIR/issue-67552.rs:27:9
33
|
44
LL | rec(identity(&mut it))

‎src/test/ui/issues/issue-8727.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LL | generic::<Option<T>>();
99
= note: `#[warn(unconditional_recursion)]` on by default
1010
= help: a `loop` may express intention better if this is on purpose
1111

12-
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>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
12+
error: reached the recursion limit while instantiating `generic::<std::option::Option<st...>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
1313
--> $DIR/issue-8727.rs:7:5
1414
|
1515
LL | generic::<Option<T>>();

‎src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
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))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))>))`
1+
error: reached the recursion limit while instantiating `std::intrinsics::drop_in_place::...)))))))))))))))))))))))))))))>))`
22
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
33
|
44
LL | / pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {

‎src/test/ui/recursion/recursion.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
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>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
1+
error: reached the recursion limit while instantiating `test::<Cons<Cons<Cons<Cons<Cons<...>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
22
--> $DIR/recursion.rs:17:11
33
|
44
LL | _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})}

‎src/test/ui/type_length_limit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// Test that the type length limit can be changed.
55

66
#![allow(dead_code)]
7-
#![type_length_limit="256"]
7+
#![type_length_limit="4"]
88

99
macro_rules! link {
1010
($id:ident, $t:ty) => {

‎src/test/ui/type_length_limit.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error: reached the type-length limit while instantiating `std::mem::drop::<std::option::Op... G), (G, G, G), (G, G, G))))))>>`
1+
error: reached the type-length limit while instantiating `std::mem::drop::<std::option::Op....., ...), ..., ...), ..., ...)>>`
22
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
33
|
44
LL | pub fn drop<T>(_x: T) {}
55
| ^^^^^^^^^^^^^^^^^^^^^^^^
66
|
7-
= note: consider adding a `#![type_length_limit="1094"]` attribute to your crate
7+
= note: consider adding a `#![type_length_limit="8"]` attribute to your crate
88

99
error: aborting due to previous error
1010

0 commit comments

Comments
 (0)
Please sign in to comment.