1 //! `TypeFoldable` implementations for MIR types
5 use rustc_data_structures
::functor
::IdFunctor
;
7 TrivialTypeFoldableAndLiftImpls
! {
15 UserTypeAnnotationIndex
,
18 impl<'tcx
> TypeFoldable
<'tcx
> for Terminator
<'tcx
> {
19 fn try_fold_with
<F
: FallibleTypeFolder
<'tcx
>>(self, folder
: &mut F
) -> Result
<Self, F
::Error
> {
20 use crate::mir
::TerminatorKind
::*;
22 let kind
= match self.kind
{
23 Goto { target }
=> Goto { target }
,
24 SwitchInt { discr, switch_ty, targets }
=> SwitchInt
{
25 discr
: discr
.try_fold_with(folder
)?
,
26 switch_ty
: switch_ty
.try_fold_with(folder
)?
,
29 Drop { place, target, unwind }
=> {
30 Drop { place: place.try_fold_with(folder)?, target, unwind }
32 DropAndReplace { place, value, target, unwind }
=> DropAndReplace
{
33 place
: place
.try_fold_with(folder
)?
,
34 value
: value
.try_fold_with(folder
)?
,
38 Yield { value, resume, resume_arg, drop }
=> Yield
{
39 value
: value
.try_fold_with(folder
)?
,
41 resume_arg
: resume_arg
.try_fold_with(folder
)?
,
44 Call { func, args, destination, target, cleanup, from_hir_call, fn_span }
=> Call
{
45 func
: func
.try_fold_with(folder
)?
,
46 args
: args
.try_fold_with(folder
)?
,
47 destination
: destination
.try_fold_with(folder
)?
,
53 Assert { cond, expected, msg, target, cleanup }
=> {
56 BoundsCheck { len, index }
=> BoundsCheck
{
57 len
: len
.try_fold_with(folder
)?
,
58 index
: index
.try_fold_with(folder
)?
,
60 Overflow(op
, l
, r
) => {
61 Overflow(op
, l
.try_fold_with(folder
)?
, r
.try_fold_with(folder
)?
)
63 OverflowNeg(op
) => OverflowNeg(op
.try_fold_with(folder
)?
),
64 DivisionByZero(op
) => DivisionByZero(op
.try_fold_with(folder
)?
),
65 RemainderByZero(op
) => RemainderByZero(op
.try_fold_with(folder
)?
),
66 ResumedAfterReturn(_
) | ResumedAfterPanic(_
) => msg
,
68 Assert { cond: cond.try_fold_with(folder)?, expected, msg, target, cleanup }
70 GeneratorDrop
=> GeneratorDrop
,
74 Unreachable
=> Unreachable
,
75 FalseEdge { real_target, imaginary_target }
=> {
76 FalseEdge { real_target, imaginary_target }
78 FalseUnwind { real_target, unwind }
=> FalseUnwind { real_target, unwind }
,
79 InlineAsm { template, operands, options, line_spans, destination, cleanup }
=> {
82 operands
: operands
.try_fold_with(folder
)?
,
90 Ok(Terminator { source_info: self.source_info, kind }
)
93 fn visit_with
<V
: TypeVisitor
<'tcx
>>(&self, visitor
: &mut V
) -> ControlFlow
<V
::BreakTy
> {
94 use crate::mir
::TerminatorKind
::*;
97 SwitchInt { ref discr, switch_ty, .. }
=> {
98 discr
.visit_with(visitor
)?
;
99 switch_ty
.visit_with(visitor
)
101 Drop { ref place, .. }
=> place
.visit_with(visitor
),
102 DropAndReplace { ref place, ref value, .. }
=> {
103 place
.visit_with(visitor
)?
;
104 value
.visit_with(visitor
)
106 Yield { ref value, .. }
=> value
.visit_with(visitor
),
107 Call { ref func, ref args, ref destination, .. }
=> {
108 destination
.visit_with(visitor
)?
;
109 func
.visit_with(visitor
)?
;
110 args
.visit_with(visitor
)
112 Assert { ref cond, ref msg, .. }
=> {
113 cond
.visit_with(visitor
)?
;
116 BoundsCheck { ref len, ref index }
=> {
117 len
.visit_with(visitor
)?
;
118 index
.visit_with(visitor
)
120 Overflow(_
, l
, r
) => {
121 l
.visit_with(visitor
)?
;
122 r
.visit_with(visitor
)
124 OverflowNeg(op
) | DivisionByZero(op
) | RemainderByZero(op
) => {
125 op
.visit_with(visitor
)
127 ResumedAfterReturn(_
) | ResumedAfterPanic(_
) => ControlFlow
::CONTINUE
,
130 InlineAsm { ref operands, .. }
=> operands
.visit_with(visitor
),
138 | FalseUnwind { .. }
=> ControlFlow
::CONTINUE
,
143 impl<'tcx
> TypeFoldable
<'tcx
> for GeneratorKind
{
144 fn try_fold_with
<F
: FallibleTypeFolder
<'tcx
>>(self, _
: &mut F
) -> Result
<Self, F
::Error
> {
148 fn visit_with
<V
: TypeVisitor
<'tcx
>>(&self, _
: &mut V
) -> ControlFlow
<V
::BreakTy
> {
149 ControlFlow
::CONTINUE
153 impl<'tcx
> TypeFoldable
<'tcx
> for Place
<'tcx
> {
154 fn try_fold_with
<F
: FallibleTypeFolder
<'tcx
>>(self, folder
: &mut F
) -> Result
<Self, F
::Error
> {
156 local
: self.local
.try_fold_with(folder
)?
,
157 projection
: self.projection
.try_fold_with(folder
)?
,
161 fn visit_with
<V
: TypeVisitor
<'tcx
>>(&self, visitor
: &mut V
) -> ControlFlow
<V
::BreakTy
> {
162 self.local
.visit_with(visitor
)?
;
163 self.projection
.visit_with(visitor
)
167 impl<'tcx
> TypeFoldable
<'tcx
> for &'tcx ty
::List
<PlaceElem
<'tcx
>> {
168 fn try_fold_with
<F
: FallibleTypeFolder
<'tcx
>>(self, folder
: &mut F
) -> Result
<Self, F
::Error
> {
169 ty
::util
::fold_list(self, folder
, |tcx
, v
| tcx
.intern_place_elems(v
))
172 fn visit_with
<V
: TypeVisitor
<'tcx
>>(&self, visitor
: &mut V
) -> ControlFlow
<V
::BreakTy
> {
173 self.iter().try_for_each(|t
| t
.visit_with(visitor
))
177 impl<'tcx
> TypeFoldable
<'tcx
> for Rvalue
<'tcx
> {
178 fn try_fold_with
<F
: FallibleTypeFolder
<'tcx
>>(self, folder
: &mut F
) -> Result
<Self, F
::Error
> {
179 use crate::mir
::Rvalue
::*;
181 Use(op
) => Use(op
.try_fold_with(folder
)?
),
182 Repeat(op
, len
) => Repeat(op
.try_fold_with(folder
)?
, len
.try_fold_with(folder
)?
),
183 ThreadLocalRef(did
) => ThreadLocalRef(did
.try_fold_with(folder
)?
),
184 Ref(region
, bk
, place
) => {
185 Ref(region
.try_fold_with(folder
)?
, bk
, place
.try_fold_with(folder
)?
)
187 AddressOf(mutability
, place
) => AddressOf(mutability
, place
.try_fold_with(folder
)?
),
188 Len(place
) => Len(place
.try_fold_with(folder
)?
),
189 Cast(kind
, op
, ty
) => Cast(kind
, op
.try_fold_with(folder
)?
, ty
.try_fold_with(folder
)?
),
190 BinaryOp(op
, box (rhs
, lhs
)) => {
191 BinaryOp(op
, Box
::new((rhs
.try_fold_with(folder
)?
, lhs
.try_fold_with(folder
)?
)))
193 CheckedBinaryOp(op
, box (rhs
, lhs
)) => CheckedBinaryOp(
195 Box
::new((rhs
.try_fold_with(folder
)?
, lhs
.try_fold_with(folder
)?
)),
197 UnaryOp(op
, val
) => UnaryOp(op
, val
.try_fold_with(folder
)?
),
198 Discriminant(place
) => Discriminant(place
.try_fold_with(folder
)?
),
199 NullaryOp(op
, ty
) => NullaryOp(op
, ty
.try_fold_with(folder
)?
),
200 Aggregate(kind
, fields
) => {
201 let kind
= kind
.try_map_id(|kind
| {
203 AggregateKind
::Array(ty
) => AggregateKind
::Array(ty
.try_fold_with(folder
)?
),
204 AggregateKind
::Tuple
=> AggregateKind
::Tuple
,
205 AggregateKind
::Adt(def
, v
, substs
, user_ty
, n
) => AggregateKind
::Adt(
208 substs
.try_fold_with(folder
)?
,
209 user_ty
.try_fold_with(folder
)?
,
212 AggregateKind
::Closure(id
, substs
) => {
213 AggregateKind
::Closure(id
, substs
.try_fold_with(folder
)?
)
215 AggregateKind
::Generator(id
, substs
, movablity
) => {
216 AggregateKind
::Generator(id
, substs
.try_fold_with(folder
)?
, movablity
)
220 Aggregate(kind
, fields
.try_fold_with(folder
)?
)
222 ShallowInitBox(op
, ty
) => {
223 ShallowInitBox(op
.try_fold_with(folder
)?
, ty
.try_fold_with(folder
)?
)
228 fn visit_with
<V
: TypeVisitor
<'tcx
>>(&self, visitor
: &mut V
) -> ControlFlow
<V
::BreakTy
> {
229 use crate::mir
::Rvalue
::*;
231 Use(ref op
) => op
.visit_with(visitor
),
232 Repeat(ref op
, _
) => op
.visit_with(visitor
),
233 ThreadLocalRef(did
) => did
.visit_with(visitor
),
234 Ref(region
, _
, ref place
) => {
235 region
.visit_with(visitor
)?
;
236 place
.visit_with(visitor
)
238 AddressOf(_
, ref place
) => place
.visit_with(visitor
),
239 Len(ref place
) => place
.visit_with(visitor
),
240 Cast(_
, ref op
, ty
) => {
241 op
.visit_with(visitor
)?
;
242 ty
.visit_with(visitor
)
244 BinaryOp(_
, box (ref rhs
, ref lhs
)) | CheckedBinaryOp(_
, box (ref rhs
, ref lhs
)) => {
245 rhs
.visit_with(visitor
)?
;
246 lhs
.visit_with(visitor
)
248 UnaryOp(_
, ref val
) => val
.visit_with(visitor
),
249 Discriminant(ref place
) => place
.visit_with(visitor
),
250 NullaryOp(_
, ty
) => ty
.visit_with(visitor
),
251 Aggregate(ref kind
, ref fields
) => {
253 AggregateKind
::Array(ty
) => {
254 ty
.visit_with(visitor
)?
;
256 AggregateKind
::Tuple
=> {}
257 AggregateKind
::Adt(_
, _
, substs
, user_ty
, _
) => {
258 substs
.visit_with(visitor
)?
;
259 user_ty
.visit_with(visitor
)?
;
261 AggregateKind
::Closure(_
, substs
) => {
262 substs
.visit_with(visitor
)?
;
264 AggregateKind
::Generator(_
, substs
, _
) => {
265 substs
.visit_with(visitor
)?
;
268 fields
.visit_with(visitor
)
270 ShallowInitBox(ref op
, ty
) => {
271 op
.visit_with(visitor
)?
;
272 ty
.visit_with(visitor
)
278 impl<'tcx
> TypeFoldable
<'tcx
> for Operand
<'tcx
> {
279 fn try_fold_with
<F
: FallibleTypeFolder
<'tcx
>>(self, folder
: &mut F
) -> Result
<Self, F
::Error
> {
281 Operand
::Copy(place
) => Operand
::Copy(place
.try_fold_with(folder
)?
),
282 Operand
::Move(place
) => Operand
::Move(place
.try_fold_with(folder
)?
),
283 Operand
::Constant(c
) => Operand
::Constant(c
.try_fold_with(folder
)?
),
287 fn visit_with
<V
: TypeVisitor
<'tcx
>>(&self, visitor
: &mut V
) -> ControlFlow
<V
::BreakTy
> {
289 Operand
::Copy(ref place
) | Operand
::Move(ref place
) => place
.visit_with(visitor
),
290 Operand
::Constant(ref c
) => c
.visit_with(visitor
),
295 impl<'tcx
> TypeFoldable
<'tcx
> for PlaceElem
<'tcx
> {
296 fn try_fold_with
<F
: FallibleTypeFolder
<'tcx
>>(self, folder
: &mut F
) -> Result
<Self, F
::Error
> {
297 use crate::mir
::ProjectionElem
::*;
301 Field(f
, ty
) => Field(f
, ty
.try_fold_with(folder
)?
),
302 Index(v
) => Index(v
.try_fold_with(folder
)?
),
303 Downcast(symbol
, variantidx
) => Downcast(symbol
, variantidx
),
304 ConstantIndex { offset, min_length, from_end }
=> {
305 ConstantIndex { offset, min_length, from_end }
307 Subslice { from, to, from_end }
=> Subslice { from, to, from_end }
,
311 fn visit_with
<Vs
: TypeVisitor
<'tcx
>>(&self, visitor
: &mut Vs
) -> ControlFlow
<Vs
::BreakTy
> {
312 use crate::mir
::ProjectionElem
::*;
315 Field(_
, ty
) => ty
.visit_with(visitor
),
316 Index(v
) => v
.visit_with(visitor
),
317 _
=> ControlFlow
::CONTINUE
,
322 impl<'tcx
> TypeFoldable
<'tcx
> for Field
{
323 fn try_fold_with
<F
: FallibleTypeFolder
<'tcx
>>(self, _
: &mut F
) -> Result
<Self, F
::Error
> {
326 fn visit_with
<V
: TypeVisitor
<'tcx
>>(&self, _
: &mut V
) -> ControlFlow
<V
::BreakTy
> {
327 ControlFlow
::CONTINUE
331 impl<'tcx
> TypeFoldable
<'tcx
> for GeneratorSavedLocal
{
332 fn try_fold_with
<F
: FallibleTypeFolder
<'tcx
>>(self, _
: &mut F
) -> Result
<Self, F
::Error
> {
335 fn visit_with
<V
: TypeVisitor
<'tcx
>>(&self, _
: &mut V
) -> ControlFlow
<V
::BreakTy
> {
336 ControlFlow
::CONTINUE
340 impl<'tcx
, R
: Idx
, C
: Idx
> TypeFoldable
<'tcx
> for BitMatrix
<R
, C
> {
341 fn try_fold_with
<F
: FallibleTypeFolder
<'tcx
>>(self, _
: &mut F
) -> Result
<Self, F
::Error
> {
344 fn visit_with
<V
: TypeVisitor
<'tcx
>>(&self, _
: &mut V
) -> ControlFlow
<V
::BreakTy
> {
345 ControlFlow
::CONTINUE
349 impl<'tcx
> TypeFoldable
<'tcx
> for Constant
<'tcx
> {
350 fn try_fold_with
<F
: FallibleTypeFolder
<'tcx
>>(self, folder
: &mut F
) -> Result
<Self, F
::Error
> {
353 user_ty
: self.user_ty
.try_fold_with(folder
)?
,
354 literal
: self.literal
.try_fold_with(folder
)?
,
357 fn visit_with
<V
: TypeVisitor
<'tcx
>>(&self, visitor
: &mut V
) -> ControlFlow
<V
::BreakTy
> {
358 self.literal
.visit_with(visitor
)?
;
359 self.user_ty
.visit_with(visitor
)
363 impl<'tcx
> TypeFoldable
<'tcx
> for ConstantKind
<'tcx
> {
365 fn try_fold_with
<F
: FallibleTypeFolder
<'tcx
>>(self, folder
: &mut F
) -> Result
<Self, F
::Error
> {
366 folder
.try_fold_mir_const(self)
369 fn visit_with
<V
: TypeVisitor
<'tcx
>>(&self, visitor
: &mut V
) -> ControlFlow
<V
::BreakTy
> {
370 visitor
.visit_mir_const(*self)
374 impl<'tcx
> TypeSuperFoldable
<'tcx
> for ConstantKind
<'tcx
> {
375 fn try_super_fold_with
<F
: FallibleTypeFolder
<'tcx
>>(
378 ) -> Result
<Self, F
::Error
> {
380 ConstantKind
::Ty(c
) => Ok(ConstantKind
::Ty(c
.try_fold_with(folder
)?
)),
381 ConstantKind
::Val(v
, t
) => Ok(ConstantKind
::Val(v
, t
.try_fold_with(folder
)?
)),
385 fn super_visit_with
<V
: TypeVisitor
<'tcx
>>(&self, visitor
: &mut V
) -> ControlFlow
<V
::BreakTy
> {
387 ConstantKind
::Ty(c
) => c
.visit_with(visitor
),
388 ConstantKind
::Val(_
, t
) => t
.visit_with(visitor
),