Skip to content

Commit 96027d9

Browse files
committedOct 20, 2023
Auto merge of #116951 - compiler-errors:ir-file-structure, r=jackh726
Restructure `rustc_type_ir` a bit 1. Split `sty` into new `ty_kind`/`region_kind`/`const_kind` modules, so that when we uplift more kinds (e.g. `PredicateKind`, `ClauseKind`, and `ExistentialPredicate`), they can live in their own simple-to-understand files. 2. Split up the `structural_impls` module, which is a kitchen sink of random impls -- move `TypeFoldable` and `TypeVisitable` impls into existing `fold` and `visit` modules, respectively. 3. Move the `DebugWithInfcx` trait and blanket impls into a new `debug` module, and `TypeFlags` definition into a new `flags` module. 5. Move `Interner` trait into a new `interner` module. I expect this file to get a lot larger as we make the interner more powerful for the trait solver refactor. r? `@ghost` for now, will assign once #116946 lands
2 parents 7db4a89 + c3fd438 commit 96027d9

File tree

22 files changed

+1560
-1532
lines changed

22 files changed

+1560
-1532
lines changed
 

Diff for: ‎compiler/rustc_const_eval/src/interpret/cast.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_middle::ty::adjustment::PointerCoercion;
88
use rustc_middle::ty::layout::{IntegerExt, LayoutOf, TyAndLayout};
99
use rustc_middle::ty::{self, FloatTy, Ty, TypeAndMut};
1010
use rustc_target::abi::Integer;
11-
use rustc_type_ir::sty::TyKind::*;
11+
use rustc_type_ir::TyKind::*;
1212

1313
use super::{
1414
util::ensure_monomorphic_enough, FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy, PlaceTy,
@@ -185,7 +185,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
185185
src: &ImmTy<'tcx, M::Provenance>,
186186
cast_to: TyAndLayout<'tcx>,
187187
) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
188-
use rustc_type_ir::sty::TyKind::*;
188+
use rustc_type_ir::TyKind::*;
189189

190190
let val = match src.layout.ty.kind() {
191191
// Floating point
@@ -310,7 +310,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
310310
where
311311
F: Float + Into<Scalar<M::Provenance>> + FloatConvert<Single> + FloatConvert<Double>,
312312
{
313-
use rustc_type_ir::sty::TyKind::*;
313+
use rustc_type_ir::TyKind::*;
314314

315315
fn adjust_nan<
316316
'mir,

Diff for: ‎compiler/rustc_hir_analysis/src/coherence/builtin.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
162162
// trait, they *do* satisfy the repr(transparent) rules, and then we assume that everything else
163163
// in the compiler (in particular, all the call ABI logic) will treat them as repr(transparent)
164164
// even if they do not carry that attribute.
165-
use rustc_type_ir::sty::TyKind::*;
165+
use rustc_type_ir::TyKind::*;
166166
match (source.kind(), target.kind()) {
167167
(&Ref(r_a, _, mutbl_a), Ref(r_b, _, mutbl_b))
168168
if infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, r_a, *r_b).is_ok()

Diff for: ‎compiler/rustc_hir_typeck/src/op.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use rustc_span::Span;
2020
use rustc_trait_selection::infer::InferCtxtExt;
2121
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _;
2222
use rustc_trait_selection::traits::{self, FulfillmentError, ObligationCtxt};
23-
use rustc_type_ir::sty::TyKind::*;
23+
use rustc_type_ir::TyKind::*;
2424

2525
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2626
/// Checks a `a <op>= b`

Diff for: ‎compiler/rustc_lint/src/builtin.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2475,7 +2475,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
24752475
ty: Ty<'tcx>,
24762476
init: InitKind,
24772477
) -> Option<InitError> {
2478-
use rustc_type_ir::sty::TyKind::*;
2478+
use rustc_type_ir::TyKind::*;
24792479
match ty.kind() {
24802480
// Primitive types that don't like 0 as a value.
24812481
Ref(..) => Some("references must be non-null".into()),

Diff for: ‎compiler/rustc_lint/src/foreign_modules.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ fn structurally_same_type_impl<'tcx>(
262262
true
263263
} else {
264264
// Do a full, depth-first comparison between the two.
265-
use rustc_type_ir::sty::TyKind::*;
265+
use rustc_type_ir::TyKind::*;
266266
let a_kind = a.kind();
267267
let b_kind = b.kind();
268268

Diff for: ‎compiler/rustc_middle/src/ty/context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
6565
use rustc_span::{Span, DUMMY_SP};
6666
use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx};
6767
use rustc_target::spec::abi;
68-
use rustc_type_ir::sty::TyKind::*;
68+
use rustc_type_ir::TyKind::*;
6969
use rustc_type_ir::WithCachedTypeInfo;
7070
use rustc_type_ir::{CollectAndApply, Interner, TypeFlags};
7171

Diff for: ‎compiler/rustc_middle/src/ty/diagnostics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc_hir::def::DefKind;
1717
use rustc_hir::def_id::DefId;
1818
use rustc_hir::{PredicateOrigin, WherePredicate};
1919
use rustc_span::{BytePos, Span};
20-
use rustc_type_ir::sty::TyKind::*;
20+
use rustc_type_ir::TyKind::*;
2121

2222
impl<'tcx> IntoDiagnosticArg for Ty<'tcx> {
2323
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {

Diff for: ‎compiler/rustc_middle/src/ty/inhabitedness/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ use crate::query::Providers;
4747
use crate::ty::context::TyCtxt;
4848
use crate::ty::{self, DefId, Ty, VariantDef, Visibility};
4949

50-
use rustc_type_ir::sty::TyKind::*;
50+
use rustc_type_ir::TyKind::*;
5151

5252
pub mod inhabited_predicate;
5353

Diff for: ‎compiler/rustc_middle/src/ty/sty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,13 @@ use std::marker::PhantomData;
3333
use std::ops::{ControlFlow, Deref, Range};
3434
use ty::util::IntTypeExt;
3535

36-
use rustc_type_ir::sty::TyKind::*;
3736
use rustc_type_ir::CollectAndApply;
3837
use rustc_type_ir::ConstKind as IrConstKind;
3938
use rustc_type_ir::DebugWithInfcx;
4039
use rustc_type_ir::DynKind;
4140
use rustc_type_ir::RegionKind as IrRegionKind;
4241
use rustc_type_ir::TyKind as IrTyKind;
42+
use rustc_type_ir::TyKind::*;
4343

4444
use super::GenericParamDefKind;
4545

Diff for: ‎compiler/rustc_ty_utils/src/ty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ fn sized_constraint_for_ty<'tcx>(
1414
adtdef: ty::AdtDef<'tcx>,
1515
ty: Ty<'tcx>,
1616
) -> Vec<Ty<'tcx>> {
17-
use rustc_type_ir::sty::TyKind::*;
17+
use rustc_type_ir::TyKind::*;
1818

1919
let result = match ty.kind() {
2020
Bool | Char | Int(..) | Uint(..) | Float(..) | RawPtr(..) | Ref(..) | FnDef(..)

Diff for: ‎compiler/rustc_type_ir/src/const_kind.rs

+258
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
use rustc_data_structures::stable_hasher::HashStable;
2+
use rustc_serialize::{Decodable, Decoder, Encodable};
3+
use std::cmp::Ordering;
4+
use std::fmt;
5+
use std::hash;
6+
7+
use crate::{
8+
DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, OptWithInfcx,
9+
TyDecoder, TyEncoder,
10+
};
11+
12+
use self::ConstKind::*;
13+
14+
/// Represents a constant in Rust.
15+
// #[derive(derive_more::From)]
16+
pub enum ConstKind<I: Interner> {
17+
/// A const generic parameter.
18+
Param(I::ParamConst),
19+
20+
/// Infer the value of the const.
21+
Infer(I::InferConst),
22+
23+
/// Bound const variable, used only when preparing a trait query.
24+
Bound(DebruijnIndex, I::BoundConst),
25+
26+
/// A placeholder const - universally quantified higher-ranked const.
27+
Placeholder(I::PlaceholderConst),
28+
29+
/// An unnormalized const item such as an anon const or assoc const or free const item.
30+
/// Right now anything other than anon consts does not actually work properly but this
31+
/// should
32+
Unevaluated(I::AliasConst),
33+
34+
/// Used to hold computed value.
35+
Value(I::ValueConst),
36+
37+
/// A placeholder for a const which could not be computed; this is
38+
/// propagated to avoid useless error messages.
39+
Error(I::ErrorGuaranteed),
40+
41+
/// Unevaluated non-const-item, used by `feature(generic_const_exprs)` to represent
42+
/// const arguments such as `N + 1` or `foo(N)`
43+
Expr(I::ExprConst),
44+
}
45+
46+
const fn const_kind_discriminant<I: Interner>(value: &ConstKind<I>) -> usize {
47+
match value {
48+
Param(_) => 0,
49+
Infer(_) => 1,
50+
Bound(_, _) => 2,
51+
Placeholder(_) => 3,
52+
Unevaluated(_) => 4,
53+
Value(_) => 5,
54+
Error(_) => 6,
55+
Expr(_) => 7,
56+
}
57+
}
58+
59+
impl<I: Interner> hash::Hash for ConstKind<I> {
60+
fn hash<H: hash::Hasher>(&self, state: &mut H) {
61+
const_kind_discriminant(self).hash(state);
62+
match self {
63+
Param(p) => p.hash(state),
64+
Infer(i) => i.hash(state),
65+
Bound(d, b) => {
66+
d.hash(state);
67+
b.hash(state);
68+
}
69+
Placeholder(p) => p.hash(state),
70+
Unevaluated(u) => u.hash(state),
71+
Value(v) => v.hash(state),
72+
Error(e) => e.hash(state),
73+
Expr(e) => e.hash(state),
74+
}
75+
}
76+
}
77+
78+
impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for ConstKind<I>
79+
where
80+
I::ParamConst: HashStable<CTX>,
81+
I::InferConst: HashStable<CTX>,
82+
I::BoundConst: HashStable<CTX>,
83+
I::PlaceholderConst: HashStable<CTX>,
84+
I::AliasConst: HashStable<CTX>,
85+
I::ValueConst: HashStable<CTX>,
86+
I::ErrorGuaranteed: HashStable<CTX>,
87+
I::ExprConst: HashStable<CTX>,
88+
{
89+
fn hash_stable(
90+
&self,
91+
hcx: &mut CTX,
92+
hasher: &mut rustc_data_structures::stable_hasher::StableHasher,
93+
) {
94+
const_kind_discriminant(self).hash_stable(hcx, hasher);
95+
match self {
96+
Param(p) => p.hash_stable(hcx, hasher),
97+
Infer(i) => i.hash_stable(hcx, hasher),
98+
Bound(d, b) => {
99+
d.hash_stable(hcx, hasher);
100+
b.hash_stable(hcx, hasher);
101+
}
102+
Placeholder(p) => p.hash_stable(hcx, hasher),
103+
Unevaluated(u) => u.hash_stable(hcx, hasher),
104+
Value(v) => v.hash_stable(hcx, hasher),
105+
Error(e) => e.hash_stable(hcx, hasher),
106+
Expr(e) => e.hash_stable(hcx, hasher),
107+
}
108+
}
109+
}
110+
111+
impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for ConstKind<I>
112+
where
113+
I::ParamConst: Decodable<D>,
114+
I::InferConst: Decodable<D>,
115+
I::BoundConst: Decodable<D>,
116+
I::PlaceholderConst: Decodable<D>,
117+
I::AliasConst: Decodable<D>,
118+
I::ValueConst: Decodable<D>,
119+
I::ErrorGuaranteed: Decodable<D>,
120+
I::ExprConst: Decodable<D>,
121+
{
122+
fn decode(d: &mut D) -> Self {
123+
match Decoder::read_usize(d) {
124+
0 => Param(Decodable::decode(d)),
125+
1 => Infer(Decodable::decode(d)),
126+
2 => Bound(Decodable::decode(d), Decodable::decode(d)),
127+
3 => Placeholder(Decodable::decode(d)),
128+
4 => Unevaluated(Decodable::decode(d)),
129+
5 => Value(Decodable::decode(d)),
130+
6 => Error(Decodable::decode(d)),
131+
7 => Expr(Decodable::decode(d)),
132+
_ => panic!(
133+
"{}",
134+
format!(
135+
"invalid enum variant tag while decoding `{}`, expected 0..{}",
136+
"ConstKind", 8,
137+
)
138+
),
139+
}
140+
}
141+
}
142+
143+
impl<I: Interner, E: TyEncoder<I = I>> Encodable<E> for ConstKind<I>
144+
where
145+
I::ParamConst: Encodable<E>,
146+
I::InferConst: Encodable<E>,
147+
I::BoundConst: Encodable<E>,
148+
I::PlaceholderConst: Encodable<E>,
149+
I::AliasConst: Encodable<E>,
150+
I::ValueConst: Encodable<E>,
151+
I::ErrorGuaranteed: Encodable<E>,
152+
I::ExprConst: Encodable<E>,
153+
{
154+
fn encode(&self, e: &mut E) {
155+
let disc = const_kind_discriminant(self);
156+
match self {
157+
Param(p) => e.emit_enum_variant(disc, |e| p.encode(e)),
158+
Infer(i) => e.emit_enum_variant(disc, |e| i.encode(e)),
159+
Bound(d, b) => e.emit_enum_variant(disc, |e| {
160+
d.encode(e);
161+
b.encode(e);
162+
}),
163+
Placeholder(p) => e.emit_enum_variant(disc, |e| p.encode(e)),
164+
Unevaluated(u) => e.emit_enum_variant(disc, |e| u.encode(e)),
165+
Value(v) => e.emit_enum_variant(disc, |e| v.encode(e)),
166+
Error(er) => e.emit_enum_variant(disc, |e| er.encode(e)),
167+
Expr(ex) => e.emit_enum_variant(disc, |e| ex.encode(e)),
168+
}
169+
}
170+
}
171+
172+
impl<I: Interner> PartialOrd for ConstKind<I> {
173+
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
174+
Some(self.cmp(other))
175+
}
176+
}
177+
178+
impl<I: Interner> Ord for ConstKind<I> {
179+
fn cmp(&self, other: &Self) -> Ordering {
180+
const_kind_discriminant(self)
181+
.cmp(&const_kind_discriminant(other))
182+
.then_with(|| match (self, other) {
183+
(Param(p1), Param(p2)) => p1.cmp(p2),
184+
(Infer(i1), Infer(i2)) => i1.cmp(i2),
185+
(Bound(d1, b1), Bound(d2, b2)) => d1.cmp(d2).then_with(|| b1.cmp(b2)),
186+
(Placeholder(p1), Placeholder(p2)) => p1.cmp(p2),
187+
(Unevaluated(u1), Unevaluated(u2)) => u1.cmp(u2),
188+
(Value(v1), Value(v2)) => v1.cmp(v2),
189+
(Error(e1), Error(e2)) => e1.cmp(e2),
190+
(Expr(e1), Expr(e2)) => e1.cmp(e2),
191+
_ => {
192+
debug_assert!(false, "This branch must be unreachable, maybe the match is missing an arm? self = {self:?}, other = {other:?}");
193+
Ordering::Equal
194+
}
195+
})
196+
}
197+
}
198+
199+
impl<I: Interner> PartialEq for ConstKind<I> {
200+
fn eq(&self, other: &Self) -> bool {
201+
match (self, other) {
202+
(Param(l0), Param(r0)) => l0 == r0,
203+
(Infer(l0), Infer(r0)) => l0 == r0,
204+
(Bound(l0, l1), Bound(r0, r1)) => l0 == r0 && l1 == r1,
205+
(Placeholder(l0), Placeholder(r0)) => l0 == r0,
206+
(Unevaluated(l0), Unevaluated(r0)) => l0 == r0,
207+
(Value(l0), Value(r0)) => l0 == r0,
208+
(Error(l0), Error(r0)) => l0 == r0,
209+
(Expr(l0), Expr(r0)) => l0 == r0,
210+
_ => false,
211+
}
212+
}
213+
}
214+
215+
impl<I: Interner> Eq for ConstKind<I> {}
216+
217+
impl<I: Interner> Clone for ConstKind<I> {
218+
fn clone(&self) -> Self {
219+
match self {
220+
Param(arg0) => Param(arg0.clone()),
221+
Infer(arg0) => Infer(arg0.clone()),
222+
Bound(arg0, arg1) => Bound(arg0.clone(), arg1.clone()),
223+
Placeholder(arg0) => Placeholder(arg0.clone()),
224+
Unevaluated(arg0) => Unevaluated(arg0.clone()),
225+
Value(arg0) => Value(arg0.clone()),
226+
Error(arg0) => Error(arg0.clone()),
227+
Expr(arg0) => Expr(arg0.clone()),
228+
}
229+
}
230+
}
231+
232+
impl<I: Interner> fmt::Debug for ConstKind<I> {
233+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
234+
OptWithInfcx::new_no_ctx(self).fmt(f)
235+
}
236+
}
237+
238+
impl<I: Interner> DebugWithInfcx<I> for ConstKind<I> {
239+
fn fmt<InfCtx: InferCtxtLike<I>>(
240+
this: OptWithInfcx<'_, I, InfCtx, &Self>,
241+
f: &mut core::fmt::Formatter<'_>,
242+
) -> core::fmt::Result {
243+
use ConstKind::*;
244+
245+
match this.data {
246+
Param(param) => write!(f, "{param:?}"),
247+
Infer(var) => write!(f, "{:?}", &this.wrap(var)),
248+
Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var.clone()),
249+
Placeholder(placeholder) => write!(f, "{placeholder:?}"),
250+
Unevaluated(uv) => {
251+
write!(f, "{:?}", &this.wrap(uv))
252+
}
253+
Value(valtree) => write!(f, "{valtree:?}"),
254+
Error(_) => write!(f, "{{const error}}"),
255+
Expr(expr) => write!(f, "{:?}", &this.wrap(expr)),
256+
}
257+
}
258+
}

Diff for: ‎compiler/rustc_type_ir/src/debug.rs

+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
use crate::{Interner, UniverseIndex};
2+
3+
use core::fmt;
4+
use std::marker::PhantomData;
5+
6+
pub trait InferCtxtLike<I: Interner> {
7+
fn universe_of_ty(&self, ty: I::InferTy) -> Option<UniverseIndex>;
8+
9+
fn universe_of_lt(&self, lt: I::InferRegion) -> Option<UniverseIndex>;
10+
11+
fn universe_of_ct(&self, ct: I::InferConst) -> Option<UniverseIndex>;
12+
}
13+
14+
impl<I: Interner> InferCtxtLike<I> for core::convert::Infallible {
15+
fn universe_of_ty(&self, _ty: <I as Interner>::InferTy) -> Option<UniverseIndex> {
16+
match *self {}
17+
}
18+
19+
fn universe_of_ct(&self, _ct: <I as Interner>::InferConst) -> Option<UniverseIndex> {
20+
match *self {}
21+
}
22+
23+
fn universe_of_lt(&self, _lt: <I as Interner>::InferRegion) -> Option<UniverseIndex> {
24+
match *self {}
25+
}
26+
}
27+
28+
pub trait DebugWithInfcx<I: Interner>: fmt::Debug {
29+
fn fmt<InfCtx: InferCtxtLike<I>>(
30+
this: OptWithInfcx<'_, I, InfCtx, &Self>,
31+
f: &mut fmt::Formatter<'_>,
32+
) -> fmt::Result;
33+
}
34+
35+
impl<I: Interner, T: DebugWithInfcx<I> + ?Sized> DebugWithInfcx<I> for &'_ T {
36+
fn fmt<InfCtx: InferCtxtLike<I>>(
37+
this: OptWithInfcx<'_, I, InfCtx, &Self>,
38+
f: &mut fmt::Formatter<'_>,
39+
) -> fmt::Result {
40+
<T as DebugWithInfcx<I>>::fmt(this.map(|&data| data), f)
41+
}
42+
}
43+
44+
impl<I: Interner, T: DebugWithInfcx<I>> DebugWithInfcx<I> for [T] {
45+
fn fmt<InfCtx: InferCtxtLike<I>>(
46+
this: OptWithInfcx<'_, I, InfCtx, &Self>,
47+
f: &mut fmt::Formatter<'_>,
48+
) -> fmt::Result {
49+
match f.alternate() {
50+
true => {
51+
write!(f, "[\n")?;
52+
for element in this.data.iter() {
53+
write!(f, "{:?},\n", &this.wrap(element))?;
54+
}
55+
write!(f, "]")
56+
}
57+
false => {
58+
write!(f, "[")?;
59+
if this.data.len() > 0 {
60+
for element in &this.data[..(this.data.len() - 1)] {
61+
write!(f, "{:?}, ", &this.wrap(element))?;
62+
}
63+
if let Some(element) = this.data.last() {
64+
write!(f, "{:?}", &this.wrap(element))?;
65+
}
66+
}
67+
write!(f, "]")
68+
}
69+
}
70+
}
71+
}
72+
73+
pub struct OptWithInfcx<'a, I: Interner, InfCtx: InferCtxtLike<I>, T> {
74+
pub data: T,
75+
pub infcx: Option<&'a InfCtx>,
76+
_interner: PhantomData<I>,
77+
}
78+
79+
impl<I: Interner, InfCtx: InferCtxtLike<I>, T: Copy> Copy for OptWithInfcx<'_, I, InfCtx, T> {}
80+
81+
impl<I: Interner, InfCtx: InferCtxtLike<I>, T: Clone> Clone for OptWithInfcx<'_, I, InfCtx, T> {
82+
fn clone(&self) -> Self {
83+
Self { data: self.data.clone(), infcx: self.infcx, _interner: self._interner }
84+
}
85+
}
86+
87+
impl<'a, I: Interner, T> OptWithInfcx<'a, I, core::convert::Infallible, T> {
88+
pub fn new_no_ctx(data: T) -> Self {
89+
Self { data, infcx: None, _interner: PhantomData }
90+
}
91+
}
92+
93+
impl<'a, I: Interner, InfCtx: InferCtxtLike<I>, T> OptWithInfcx<'a, I, InfCtx, T> {
94+
pub fn new(data: T, infcx: &'a InfCtx) -> Self {
95+
Self { data, infcx: Some(infcx), _interner: PhantomData }
96+
}
97+
98+
pub fn wrap<U>(self, u: U) -> OptWithInfcx<'a, I, InfCtx, U> {
99+
OptWithInfcx { data: u, infcx: self.infcx, _interner: PhantomData }
100+
}
101+
102+
pub fn map<U>(self, f: impl FnOnce(T) -> U) -> OptWithInfcx<'a, I, InfCtx, U> {
103+
OptWithInfcx { data: f(self.data), infcx: self.infcx, _interner: PhantomData }
104+
}
105+
106+
pub fn as_ref(&self) -> OptWithInfcx<'a, I, InfCtx, &T> {
107+
OptWithInfcx { data: &self.data, infcx: self.infcx, _interner: PhantomData }
108+
}
109+
}
110+
111+
impl<I: Interner, InfCtx: InferCtxtLike<I>, T: DebugWithInfcx<I>> fmt::Debug
112+
for OptWithInfcx<'_, I, InfCtx, T>
113+
{
114+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115+
DebugWithInfcx::fmt(self.as_ref(), f)
116+
}
117+
}

Diff for: ‎compiler/rustc_type_ir/src/flags.rs

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
bitflags! {
2+
/// Flags that we track on types. These flags are propagated upwards
3+
/// through the type during type construction, so that we can quickly check
4+
/// whether the type has various kinds of types in it without recursing
5+
/// over the type itself.
6+
pub struct TypeFlags: u32 {
7+
// Does this have parameters? Used to determine whether substitution is
8+
// required.
9+
/// Does this have `Param`?
10+
const HAS_TY_PARAM = 1 << 0;
11+
/// Does this have `ReEarlyBound`?
12+
const HAS_RE_PARAM = 1 << 1;
13+
/// Does this have `ConstKind::Param`?
14+
const HAS_CT_PARAM = 1 << 2;
15+
16+
const HAS_PARAM = TypeFlags::HAS_TY_PARAM.bits
17+
| TypeFlags::HAS_RE_PARAM.bits
18+
| TypeFlags::HAS_CT_PARAM.bits;
19+
20+
/// Does this have `Infer`?
21+
const HAS_TY_INFER = 1 << 3;
22+
/// Does this have `ReVar`?
23+
const HAS_RE_INFER = 1 << 4;
24+
/// Does this have `ConstKind::Infer`?
25+
const HAS_CT_INFER = 1 << 5;
26+
27+
/// Does this have inference variables? Used to determine whether
28+
/// inference is required.
29+
const HAS_INFER = TypeFlags::HAS_TY_INFER.bits
30+
| TypeFlags::HAS_RE_INFER.bits
31+
| TypeFlags::HAS_CT_INFER.bits;
32+
33+
/// Does this have `Placeholder`?
34+
const HAS_TY_PLACEHOLDER = 1 << 6;
35+
/// Does this have `RePlaceholder`?
36+
const HAS_RE_PLACEHOLDER = 1 << 7;
37+
/// Does this have `ConstKind::Placeholder`?
38+
const HAS_CT_PLACEHOLDER = 1 << 8;
39+
40+
/// Does this have placeholders?
41+
const HAS_PLACEHOLDER = TypeFlags::HAS_TY_PLACEHOLDER.bits
42+
| TypeFlags::HAS_RE_PLACEHOLDER.bits
43+
| TypeFlags::HAS_CT_PLACEHOLDER.bits;
44+
45+
/// `true` if there are "names" of regions and so forth
46+
/// that are local to a particular fn/inferctxt
47+
const HAS_FREE_LOCAL_REGIONS = 1 << 9;
48+
49+
/// `true` if there are "names" of types and regions and so forth
50+
/// that are local to a particular fn
51+
const HAS_FREE_LOCAL_NAMES = TypeFlags::HAS_TY_PARAM.bits
52+
| TypeFlags::HAS_CT_PARAM.bits
53+
| TypeFlags::HAS_TY_INFER.bits
54+
| TypeFlags::HAS_CT_INFER.bits
55+
| TypeFlags::HAS_TY_PLACEHOLDER.bits
56+
| TypeFlags::HAS_CT_PLACEHOLDER.bits
57+
// We consider 'freshened' types and constants
58+
// to depend on a particular fn.
59+
// The freshening process throws away information,
60+
// which can make things unsuitable for use in a global
61+
// cache. Note that there is no 'fresh lifetime' flag -
62+
// freshening replaces all lifetimes with `ReErased`,
63+
// which is different from how types/const are freshened.
64+
| TypeFlags::HAS_TY_FRESH.bits
65+
| TypeFlags::HAS_CT_FRESH.bits
66+
| TypeFlags::HAS_FREE_LOCAL_REGIONS.bits
67+
| TypeFlags::HAS_RE_ERASED.bits;
68+
69+
/// Does this have `Projection`?
70+
const HAS_TY_PROJECTION = 1 << 10;
71+
/// Does this have `Inherent`?
72+
const HAS_TY_INHERENT = 1 << 11;
73+
/// Does this have `Opaque`?
74+
const HAS_TY_OPAQUE = 1 << 12;
75+
/// Does this have `ConstKind::Unevaluated`?
76+
const HAS_CT_PROJECTION = 1 << 13;
77+
78+
/// Could this type be normalized further?
79+
const HAS_PROJECTION = TypeFlags::HAS_TY_PROJECTION.bits
80+
| TypeFlags::HAS_TY_OPAQUE.bits
81+
| TypeFlags::HAS_TY_INHERENT.bits
82+
| TypeFlags::HAS_CT_PROJECTION.bits;
83+
84+
/// Is an error type/const reachable?
85+
const HAS_ERROR = 1 << 14;
86+
87+
/// Does this have any region that "appears free" in the type?
88+
/// Basically anything but `ReLateBound` and `ReErased`.
89+
const HAS_FREE_REGIONS = 1 << 15;
90+
91+
/// Does this have any `ReLateBound` regions?
92+
const HAS_RE_LATE_BOUND = 1 << 16;
93+
/// Does this have any `Bound` types?
94+
const HAS_TY_LATE_BOUND = 1 << 17;
95+
/// Does this have any `ConstKind::Bound` consts?
96+
const HAS_CT_LATE_BOUND = 1 << 18;
97+
/// Does this have any bound variables?
98+
/// Used to check if a global bound is safe to evaluate.
99+
const HAS_LATE_BOUND = TypeFlags::HAS_RE_LATE_BOUND.bits
100+
| TypeFlags::HAS_TY_LATE_BOUND.bits
101+
| TypeFlags::HAS_CT_LATE_BOUND.bits;
102+
103+
/// Does this have any `ReErased` regions?
104+
const HAS_RE_ERASED = 1 << 19;
105+
106+
/// Does this value have parameters/placeholders/inference variables which could be
107+
/// replaced later, in a way that would change the results of `impl` specialization?
108+
const STILL_FURTHER_SPECIALIZABLE = 1 << 20;
109+
110+
/// Does this value have `InferTy::FreshTy/FreshIntTy/FreshFloatTy`?
111+
const HAS_TY_FRESH = 1 << 21;
112+
113+
/// Does this value have `InferConst::Fresh`?
114+
const HAS_CT_FRESH = 1 << 22;
115+
116+
/// Does this have `Generator` or `GeneratorWitness`?
117+
const HAS_TY_GENERATOR = 1 << 23;
118+
}
119+
}

Diff for: ‎compiler/rustc_type_ir/src/fold.rs

+103
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@
4444
//! - ty.super_fold_with(folder)
4545
//! - u.fold_with(folder)
4646
//! ```
47+
48+
use rustc_data_structures::sync::Lrc;
49+
use rustc_index::{Idx, IndexVec};
50+
use std::mem;
51+
4752
use crate::{visit::TypeVisitable, Interner};
4853

4954
/// This trait is implemented for every type that can be folded,
@@ -242,3 +247,101 @@ where
242247
Ok(self.fold_predicate(p))
243248
}
244249
}
250+
251+
///////////////////////////////////////////////////////////////////////////
252+
// Traversal implementations.
253+
254+
impl<I: Interner, T: TypeFoldable<I>, U: TypeFoldable<I>> TypeFoldable<I> for (T, U) {
255+
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<(T, U), F::Error> {
256+
Ok((self.0.try_fold_with(folder)?, self.1.try_fold_with(folder)?))
257+
}
258+
}
259+
260+
impl<I: Interner, A: TypeFoldable<I>, B: TypeFoldable<I>, C: TypeFoldable<I>> TypeFoldable<I>
261+
for (A, B, C)
262+
{
263+
fn try_fold_with<F: FallibleTypeFolder<I>>(
264+
self,
265+
folder: &mut F,
266+
) -> Result<(A, B, C), F::Error> {
267+
Ok((
268+
self.0.try_fold_with(folder)?,
269+
self.1.try_fold_with(folder)?,
270+
self.2.try_fold_with(folder)?,
271+
))
272+
}
273+
}
274+
275+
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Option<T> {
276+
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
277+
Ok(match self {
278+
Some(v) => Some(v.try_fold_with(folder)?),
279+
None => None,
280+
})
281+
}
282+
}
283+
284+
impl<I: Interner, T: TypeFoldable<I>, E: TypeFoldable<I>> TypeFoldable<I> for Result<T, E> {
285+
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
286+
Ok(match self {
287+
Ok(v) => Ok(v.try_fold_with(folder)?),
288+
Err(e) => Err(e.try_fold_with(folder)?),
289+
})
290+
}
291+
}
292+
293+
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Lrc<T> {
294+
fn try_fold_with<F: FallibleTypeFolder<I>>(mut self, folder: &mut F) -> Result<Self, F::Error> {
295+
// We merely want to replace the contained `T`, if at all possible,
296+
// so that we don't needlessly allocate a new `Lrc` or indeed clone
297+
// the contained type.
298+
unsafe {
299+
// First step is to ensure that we have a unique reference to
300+
// the contained type, which `Lrc::make_mut` will accomplish (by
301+
// allocating a new `Lrc` and cloning the `T` only if required).
302+
// This is done *before* casting to `Lrc<ManuallyDrop<T>>` so that
303+
// panicking during `make_mut` does not leak the `T`.
304+
Lrc::make_mut(&mut self);
305+
306+
// Casting to `Lrc<ManuallyDrop<T>>` is safe because `ManuallyDrop`
307+
// is `repr(transparent)`.
308+
let ptr = Lrc::into_raw(self).cast::<mem::ManuallyDrop<T>>();
309+
let mut unique = Lrc::from_raw(ptr);
310+
311+
// Call to `Lrc::make_mut` above guarantees that `unique` is the
312+
// sole reference to the contained value, so we can avoid doing
313+
// a checked `get_mut` here.
314+
let slot = Lrc::get_mut_unchecked(&mut unique);
315+
316+
// Semantically move the contained type out from `unique`, fold
317+
// it, then move the folded value back into `unique`. Should
318+
// folding fail, `ManuallyDrop` ensures that the "moved-out"
319+
// value is not re-dropped.
320+
let owned = mem::ManuallyDrop::take(slot);
321+
let folded = owned.try_fold_with(folder)?;
322+
*slot = mem::ManuallyDrop::new(folded);
323+
324+
// Cast back to `Lrc<T>`.
325+
Ok(Lrc::from_raw(Lrc::into_raw(unique).cast()))
326+
}
327+
}
328+
}
329+
330+
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Box<T> {
331+
fn try_fold_with<F: FallibleTypeFolder<I>>(mut self, folder: &mut F) -> Result<Self, F::Error> {
332+
*self = (*self).try_fold_with(folder)?;
333+
Ok(self)
334+
}
335+
}
336+
337+
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Vec<T> {
338+
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
339+
self.into_iter().map(|t| t.try_fold_with(folder)).collect()
340+
}
341+
}
342+
343+
impl<I: Interner, T: TypeFoldable<I>, Ix: Idx> TypeFoldable<I> for IndexVec<Ix, T> {
344+
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
345+
self.raw.try_fold_with(folder).map(IndexVec::from_raw)
346+
}
347+
}

Diff for: ‎compiler/rustc_type_ir/src/interner.rs

+155
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
use smallvec::SmallVec;
2+
use std::fmt::Debug;
3+
use std::hash::Hash;
4+
5+
use crate::{DebugWithInfcx, Mutability};
6+
7+
pub trait Interner: Sized {
8+
type DefId: Clone + Debug + Hash + Ord;
9+
type AdtDef: Clone + Debug + Hash + Ord;
10+
11+
type GenericArgs: Clone
12+
+ DebugWithInfcx<Self>
13+
+ Hash
14+
+ Ord
15+
+ IntoIterator<Item = Self::GenericArg>;
16+
type GenericArg: Clone + DebugWithInfcx<Self> + Hash + Ord;
17+
18+
type Binder<T>;
19+
20+
// Predicates
21+
type Predicate;
22+
type PredicateKind: Clone + Debug + Hash + PartialEq + Eq;
23+
24+
type TypeAndMut: Clone + Debug + Hash + Ord;
25+
26+
// Kinds of tys
27+
type Ty: Clone + DebugWithInfcx<Self> + Hash + Ord;
28+
type Tys: Clone + Debug + Hash + Ord + IntoIterator<Item = Self::Ty>;
29+
type AliasTy: Clone + DebugWithInfcx<Self> + Hash + Ord;
30+
type ParamTy: Clone + Debug + Hash + Ord;
31+
type BoundTy: Clone + Debug + Hash + Ord;
32+
type PlaceholderTy: Clone + Debug + Hash + Ord;
33+
type InferTy: Clone + DebugWithInfcx<Self> + Hash + Ord;
34+
35+
// Things stored inside of tys
36+
type ErrorGuaranteed: Clone + Debug + Hash + Ord;
37+
type BoundExistentialPredicates: Clone + DebugWithInfcx<Self> + Hash + Ord;
38+
type PolyFnSig: Clone + DebugWithInfcx<Self> + Hash + Ord;
39+
type AllocId: Clone + Debug + Hash + Ord;
40+
41+
// Kinds of consts
42+
type Const: Clone + DebugWithInfcx<Self> + Hash + Ord;
43+
type InferConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
44+
type AliasConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
45+
type PlaceholderConst: Clone + Debug + Hash + Ord;
46+
type ParamConst: Clone + Debug + Hash + Ord;
47+
type BoundConst: Clone + Debug + Hash + Ord;
48+
type ValueConst: Clone + Debug + Hash + Ord;
49+
type ExprConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
50+
51+
// Kinds of regions
52+
type Region: Clone + DebugWithInfcx<Self> + Hash + Ord;
53+
type EarlyBoundRegion: Clone + Debug + Hash + Ord;
54+
type BoundRegion: Clone + Debug + Hash + Ord;
55+
type FreeRegion: Clone + Debug + Hash + Ord;
56+
type InferRegion: Clone + DebugWithInfcx<Self> + Hash + Ord;
57+
type PlaceholderRegion: Clone + Debug + Hash + Ord;
58+
59+
fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Mutability);
60+
}
61+
62+
/// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
63+
/// that produces `T` items. You could combine them with
64+
/// `f(&iter.collect::<Vec<_>>())`, but this requires allocating memory for the
65+
/// `Vec`.
66+
///
67+
/// This trait allows for faster implementations, intended for cases where the
68+
/// number of items produced by the iterator is small. There is a blanket impl
69+
/// for `T` items, but there is also a fallible impl for `Result<T, E>` items.
70+
pub trait CollectAndApply<T, R>: Sized {
71+
type Output;
72+
73+
/// Produce a result of type `Self::Output` from `iter`. The result will
74+
/// typically be produced by applying `f` on the elements produced by
75+
/// `iter`, though this may not happen in some impls, e.g. if an error
76+
/// occurred during iteration.
77+
fn collect_and_apply<I, F>(iter: I, f: F) -> Self::Output
78+
where
79+
I: Iterator<Item = Self>,
80+
F: FnOnce(&[T]) -> R;
81+
}
82+
83+
/// The blanket impl that always collects all elements and applies `f`.
84+
impl<T, R> CollectAndApply<T, R> for T {
85+
type Output = R;
86+
87+
/// Equivalent to `f(&iter.collect::<Vec<_>>())`.
88+
fn collect_and_apply<I, F>(mut iter: I, f: F) -> R
89+
where
90+
I: Iterator<Item = T>,
91+
F: FnOnce(&[T]) -> R,
92+
{
93+
// This code is hot enough that it's worth specializing for the most
94+
// common length lists, to avoid the overhead of `SmallVec` creation.
95+
// Lengths 0, 1, and 2 typically account for ~95% of cases. If
96+
// `size_hint` is incorrect a panic will occur via an `unwrap` or an
97+
// `assert`.
98+
match iter.size_hint() {
99+
(0, Some(0)) => {
100+
assert!(iter.next().is_none());
101+
f(&[])
102+
}
103+
(1, Some(1)) => {
104+
let t0 = iter.next().unwrap();
105+
assert!(iter.next().is_none());
106+
f(&[t0])
107+
}
108+
(2, Some(2)) => {
109+
let t0 = iter.next().unwrap();
110+
let t1 = iter.next().unwrap();
111+
assert!(iter.next().is_none());
112+
f(&[t0, t1])
113+
}
114+
_ => f(&iter.collect::<SmallVec<[_; 8]>>()),
115+
}
116+
}
117+
}
118+
119+
/// A fallible impl that will fail, without calling `f`, if there are any
120+
/// errors during collection.
121+
impl<T, R, E> CollectAndApply<T, R> for Result<T, E> {
122+
type Output = Result<R, E>;
123+
124+
/// Equivalent to `Ok(f(&iter.collect::<Result<Vec<_>>>()?))`.
125+
fn collect_and_apply<I, F>(mut iter: I, f: F) -> Result<R, E>
126+
where
127+
I: Iterator<Item = Result<T, E>>,
128+
F: FnOnce(&[T]) -> R,
129+
{
130+
// This code is hot enough that it's worth specializing for the most
131+
// common length lists, to avoid the overhead of `SmallVec` creation.
132+
// Lengths 0, 1, and 2 typically account for ~95% of cases. If
133+
// `size_hint` is incorrect a panic will occur via an `unwrap` or an
134+
// `assert`, unless a failure happens first, in which case the result
135+
// will be an error anyway.
136+
Ok(match iter.size_hint() {
137+
(0, Some(0)) => {
138+
assert!(iter.next().is_none());
139+
f(&[])
140+
}
141+
(1, Some(1)) => {
142+
let t0 = iter.next().unwrap()?;
143+
assert!(iter.next().is_none());
144+
f(&[t0])
145+
}
146+
(2, Some(2)) => {
147+
let t0 = iter.next().unwrap()?;
148+
let t1 = iter.next().unwrap()?;
149+
assert!(iter.next().is_none());
150+
f(&[t0, t1])
151+
}
152+
_ => f(&iter.collect::<Result<SmallVec<[_; 8]>, _>>()?),
153+
})
154+
}
155+
}

Diff for: ‎compiler/rustc_type_ir/src/lib.rs

+12-574
Large diffs are not rendered by default.

Diff for: ‎compiler/rustc_type_ir/src/macros.rs

+17
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,20 @@ macro_rules! TrivialTypeTraversalImpls {
3333
)+
3434
};
3535
}
36+
37+
///////////////////////////////////////////////////////////////////////////
38+
// Atomic structs
39+
//
40+
// For things that don't carry any arena-allocated data (and are
41+
// copy...), just add them to this list.
42+
43+
TrivialTypeTraversalImpls! {
44+
(),
45+
bool,
46+
usize,
47+
u16,
48+
u32,
49+
u64,
50+
String,
51+
crate::DebruijnIndex,
52+
}

Diff for: ‎compiler/rustc_type_ir/src/region_kind.rs

+412
Large diffs are not rendered by default.

Diff for: ‎compiler/rustc_type_ir/src/structural_impls.rs

-390
This file was deleted.

Diff for: ‎compiler/rustc_type_ir/src/ty_info.rs

+5-10
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
1-
use std::{
2-
cmp::Ordering,
3-
hash::{Hash, Hasher},
4-
ops::Deref,
5-
};
6-
7-
use rustc_data_structures::{
8-
fingerprint::Fingerprint,
9-
stable_hasher::{HashStable, StableHasher},
10-
};
1+
use rustc_data_structures::fingerprint::Fingerprint;
2+
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
3+
use std::cmp::Ordering;
4+
use std::hash::{Hash, Hasher};
5+
use std::ops::Deref;
116

127
use crate::{DebruijnIndex, TypeFlags};
138

Diff for: ‎compiler/rustc_type_ir/src/sty.rs renamed to ‎compiler/rustc_type_ir/src/ty_kind.rs

+269-545
Large diffs are not rendered by default.

Diff for: ‎compiler/rustc_type_ir/src/visit.rs

+81-1
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,14 @@
4040
//! - ty.super_visit_with(visitor)
4141
//! - u.visit_with(visitor)
4242
//! ```
43-
use crate::Interner;
4443
44+
use rustc_data_structures::sync::Lrc;
45+
use rustc_index::{Idx, IndexVec};
4546
use std::fmt;
4647
use std::ops::ControlFlow;
4748

49+
use crate::Interner;
50+
4851
/// This trait is implemented for every type that can be visited,
4952
/// providing the skeleton of the traversal.
5053
///
@@ -116,3 +119,80 @@ pub trait TypeVisitor<I: Interner>: Sized {
116119
p.super_visit_with(self)
117120
}
118121
}
122+
123+
///////////////////////////////////////////////////////////////////////////
124+
// Traversal implementations.
125+
126+
impl<I: Interner, T: TypeVisitable<I>, U: TypeVisitable<I>> TypeVisitable<I> for (T, U) {
127+
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
128+
self.0.visit_with(visitor)?;
129+
self.1.visit_with(visitor)
130+
}
131+
}
132+
133+
impl<I: Interner, A: TypeVisitable<I>, B: TypeVisitable<I>, C: TypeVisitable<I>> TypeVisitable<I>
134+
for (A, B, C)
135+
{
136+
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
137+
self.0.visit_with(visitor)?;
138+
self.1.visit_with(visitor)?;
139+
self.2.visit_with(visitor)
140+
}
141+
}
142+
143+
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Option<T> {
144+
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
145+
match self {
146+
Some(v) => v.visit_with(visitor),
147+
None => ControlFlow::Continue(()),
148+
}
149+
}
150+
}
151+
152+
impl<I: Interner, T: TypeVisitable<I>, E: TypeVisitable<I>> TypeVisitable<I> for Result<T, E> {
153+
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
154+
match self {
155+
Ok(v) => v.visit_with(visitor),
156+
Err(e) => e.visit_with(visitor),
157+
}
158+
}
159+
}
160+
161+
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Lrc<T> {
162+
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
163+
(**self).visit_with(visitor)
164+
}
165+
}
166+
167+
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Box<T> {
168+
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
169+
(**self).visit_with(visitor)
170+
}
171+
}
172+
173+
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Vec<T> {
174+
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
175+
self.iter().try_for_each(|t| t.visit_with(visitor))
176+
}
177+
}
178+
179+
// `TypeFoldable` isn't impl'd for `&[T]`. It doesn't make sense in the general
180+
// case, because we can't return a new slice. But note that there are a couple
181+
// of trivial impls of `TypeFoldable` for specific slice types elsewhere.
182+
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for &[T] {
183+
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
184+
self.iter().try_for_each(|t| t.visit_with(visitor))
185+
}
186+
}
187+
188+
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Box<[T]> {
189+
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
190+
self.iter().try_for_each(|t| t.visit_with(visitor))
191+
}
192+
}
193+
194+
impl<I: Interner, T: TypeVisitable<I>, Ix: Idx> TypeVisitable<I> for IndexVec<Ix, T> {
195+
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
196+
self.iter().try_for_each(|t| t.visit_with(visitor))
197+
}
198+
}

0 commit comments

Comments
 (0)
Please sign in to comment.