Skip to content

Commit d6646f6

Browse files
committed
Auto merge of rust-lang#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 rust-lang#77418 * cache types during normalization rust-lang#76928 * Fixing memory exhaustion when formatting short code suggestion rust-lang#76598 * Issue 72408 nested closures exponential rust-lang#72412 r? `@Mark-Simulacrum`
2 parents 6d3dc31 + bf38fa5 commit d6646f6

33 files changed

+410
-94
lines changed

Cargo.lock

+3
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

+2-2
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

+1
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

+7-5
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> {
+61
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

+3-3
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

+1-1
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

+1
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

+12-2
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

+28-12
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

+1
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" }

0 commit comments

Comments
 (0)