@@ -89,6 +89,7 @@ use std::borrow::Cow;
89
89
use either:: Either ;
90
90
use itertools:: Itertools as _;
91
91
use rustc_abi:: { self as abi, BackendRepr , FIRST_VARIANT , FieldIdx , Primitive , Size , VariantIdx } ;
92
+ use rustc_arena:: DroplessArena ;
92
93
use rustc_const_eval:: const_eval:: DummyMachine ;
93
94
use rustc_const_eval:: interpret:: {
94
95
ImmTy , Immediate , InterpCx , MemPlaceMeta , MemoryKind , OpTy , Projectable , Scalar ,
@@ -127,7 +128,9 @@ impl<'tcx> crate::MirPass<'tcx> for GVN {
127
128
// Clone dominators because we need them while mutating the body.
128
129
let dominators = body. basic_blocks . dominators ( ) . clone ( ) ;
129
130
130
- let mut state = VnState :: new ( tcx, body, typing_env, & ssa, dominators, & body. local_decls ) ;
131
+ let arena = DroplessArena :: default ( ) ;
132
+ let mut state =
133
+ VnState :: new ( tcx, body, typing_env, & ssa, dominators, & body. local_decls , & arena) ;
131
134
132
135
for local in body. args_iter ( ) . filter ( |& local| ssa. is_ssa ( local) ) {
133
136
let opaque = state. new_opaque ( body. local_decls [ local] . ty ) ;
@@ -161,8 +164,8 @@ enum AddressKind {
161
164
Address ( RawPtrKind ) ,
162
165
}
163
166
164
- #[ derive( Debug , PartialEq , Eq , Hash ) ]
165
- enum Value < ' tcx > {
167
+ #[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
168
+ enum Value < ' a , ' tcx > {
166
169
// Root values.
167
170
/// Used to represent values we know nothing about.
168
171
/// The `usize` is a counter incremented by `new_opaque`.
@@ -177,7 +180,7 @@ enum Value<'tcx> {
177
180
} ,
178
181
/// An aggregate value, either tuple/closure/struct/enum.
179
182
/// This does not contain unions, as we cannot reason with the value.
180
- Aggregate ( VariantIdx , Vec < VnIndex > ) ,
183
+ Aggregate ( VariantIdx , & ' a [ VnIndex ] ) ,
181
184
/// A raw pointer aggregate built from a thin pointer and metadata.
182
185
RawPtr {
183
186
/// Thin pointer component. This is field 0 in MIR.
@@ -213,7 +216,7 @@ enum Value<'tcx> {
213
216
} ,
214
217
}
215
218
216
- struct VnState < ' body , ' tcx > {
219
+ struct VnState < ' body , ' a , ' tcx > {
217
220
tcx : TyCtxt < ' tcx > ,
218
221
ecx : InterpCx < ' tcx , DummyMachine > ,
219
222
local_decls : & ' body LocalDecls < ' tcx > ,
@@ -223,7 +226,7 @@ struct VnState<'body, 'tcx> {
223
226
/// Locals that are assigned that value.
224
227
// This vector does not hold all the values of `VnIndex` that we create.
225
228
rev_locals : IndexVec < VnIndex , SmallVec < [ Local ; 1 ] > > ,
226
- values : FxIndexSet < ( Value < ' tcx > , Ty < ' tcx > ) > ,
229
+ values : FxIndexSet < ( Value < ' a , ' tcx > , Ty < ' tcx > ) > ,
227
230
/// Values evaluated as constants if possible.
228
231
evaluated : IndexVec < VnIndex , Option < OpTy < ' tcx > > > ,
229
232
/// Counter to generate different values.
@@ -233,16 +236,18 @@ struct VnState<'body, 'tcx> {
233
236
ssa : & ' body SsaLocals ,
234
237
dominators : Dominators < BasicBlock > ,
235
238
reused_locals : DenseBitSet < Local > ,
239
+ arena : & ' a DroplessArena ,
236
240
}
237
241
238
- impl < ' body , ' tcx > VnState < ' body , ' tcx > {
242
+ impl < ' body , ' a , ' tcx > VnState < ' body , ' a , ' tcx > {
239
243
fn new (
240
244
tcx : TyCtxt < ' tcx > ,
241
245
body : & Body < ' tcx > ,
242
246
typing_env : ty:: TypingEnv < ' tcx > ,
243
247
ssa : & ' body SsaLocals ,
244
248
dominators : Dominators < BasicBlock > ,
245
249
local_decls : & ' body LocalDecls < ' tcx > ,
250
+ arena : & ' a DroplessArena ,
246
251
) -> Self {
247
252
// Compute a rough estimate of the number of values in the body from the number of
248
253
// statements. This is meant to reduce the number of allocations, but it's all right if
@@ -265,6 +270,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
265
270
ssa,
266
271
dominators,
267
272
reused_locals : DenseBitSet :: new_empty ( local_decls. len ( ) ) ,
273
+ arena,
268
274
}
269
275
}
270
276
@@ -273,7 +279,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
273
279
}
274
280
275
281
#[ instrument( level = "trace" , skip( self ) , ret) ]
276
- fn insert ( & mut self , ty : Ty < ' tcx > , value : Value < ' tcx > ) -> VnIndex {
282
+ fn insert ( & mut self , ty : Ty < ' tcx > , value : Value < ' a , ' tcx > ) -> VnIndex {
277
283
let ( index, new) = self . values . insert_full ( ( value, ty) ) ;
278
284
let index = VnIndex :: from_usize ( index) ;
279
285
if new {
@@ -316,8 +322,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
316
322
}
317
323
318
324
#[ inline]
319
- fn get ( & self , index : VnIndex ) -> & Value < ' tcx > {
320
- & self . values . get_index ( index. as_usize ( ) ) . unwrap ( ) . 0
325
+ fn get ( & self , index : VnIndex ) -> Value < ' a , ' tcx > {
326
+ self . values . get_index ( index. as_usize ( ) ) . unwrap ( ) . 0
321
327
}
322
328
323
329
#[ inline]
@@ -362,8 +368,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
362
368
self . insert ( ty, Value :: Constant { value, disambiguator : 0 } )
363
369
}
364
370
365
- fn insert_tuple ( & mut self , ty : Ty < ' tcx > , values : Vec < VnIndex > ) -> VnIndex {
366
- self . insert ( ty, Value :: Aggregate ( VariantIdx :: ZERO , values) )
371
+ fn insert_tuple ( & mut self , ty : Ty < ' tcx > , values : & [ VnIndex ] ) -> VnIndex {
372
+ self . insert ( ty, Value :: Aggregate ( VariantIdx :: ZERO , self . arena . alloc_slice ( values) ) )
367
373
}
368
374
369
375
fn insert_deref ( & mut self , ty : Ty < ' tcx > , value : VnIndex ) -> VnIndex {
@@ -389,7 +395,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
389
395
} else {
390
396
return None ;
391
397
} ;
392
- let op = match * self . get ( value) {
398
+ let op = match self . get ( value) {
393
399
_ if ty. is_zst ( ) => ImmTy :: uninit ( ty) . into ( ) ,
394
400
395
401
Opaque ( _) => return None ,
@@ -609,7 +615,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
609
615
if let Value :: Aggregate ( _, fields) = self . get ( value) {
610
616
return Some ( ( projection_ty, fields[ f. as_usize ( ) ] ) ) ;
611
617
} else if let Value :: Projection ( outer_value, ProjectionElem :: Downcast ( _, read_variant) ) = self . get ( value)
612
- && let Value :: Aggregate ( written_variant, fields) = self . get ( * outer_value)
618
+ && let Value :: Aggregate ( written_variant, fields) = self . get ( outer_value)
613
619
// This pass is not aware of control-flow, so we do not know whether the
614
620
// replacement we are doing is actually reachable. We could be in any arm of
615
621
// ```
@@ -634,15 +640,15 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
634
640
ProjectionElem :: Index ( idx) => {
635
641
if let Value :: Repeat ( inner, _) = self . get ( value) {
636
642
* from_non_ssa_index |= self . locals [ idx] . is_none ( ) ;
637
- return Some ( ( projection_ty, * inner) ) ;
643
+ return Some ( ( projection_ty, inner) ) ;
638
644
}
639
645
let idx = self . locals [ idx] ?;
640
646
ProjectionElem :: Index ( idx)
641
647
}
642
648
ProjectionElem :: ConstantIndex { offset, min_length, from_end } => {
643
649
match self . get ( value) {
644
650
Value :: Repeat ( inner, _) => {
645
- return Some ( ( projection_ty, * inner) ) ;
651
+ return Some ( ( projection_ty, inner) ) ;
646
652
}
647
653
Value :: Aggregate ( _, operands) => {
648
654
let offset = if from_end {
@@ -732,8 +738,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
732
738
let mut place_ty = PlaceTy :: from_ty ( self . local_decls [ place. local ] . ty ) ;
733
739
let mut from_non_ssa_index = false ;
734
740
for ( index, proj) in place. projection . iter ( ) . enumerate ( ) {
735
- if let Value :: Projection ( pointer, ProjectionElem :: Deref ) = * self . get ( value)
736
- && let Value :: Address { place : mut pointee, kind, .. } = * self . get ( pointer)
741
+ if let Value :: Projection ( pointer, ProjectionElem :: Deref ) = self . get ( value)
742
+ && let Value :: Address { place : mut pointee, kind, .. } = self . get ( pointer)
737
743
&& let AddressKind :: Ref ( BorrowKind :: Shared ) = kind
738
744
&& let Some ( v) = self . simplify_place_value ( & mut pointee, location)
739
745
{
@@ -756,8 +762,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
756
762
( place_ty, value) = self . project ( place_ty, value, proj, & mut from_non_ssa_index) ?;
757
763
}
758
764
759
- if let Value :: Projection ( pointer, ProjectionElem :: Deref ) = * self . get ( value)
760
- && let Value :: Address { place : mut pointee, kind, .. } = * self . get ( pointer)
765
+ if let Value :: Projection ( pointer, ProjectionElem :: Deref ) = self . get ( value)
766
+ && let Value :: Address { place : mut pointee, kind, .. } = self . get ( pointer)
761
767
&& let AddressKind :: Ref ( BorrowKind :: Shared ) = kind
762
768
&& let Some ( v) = self . simplify_place_value ( & mut pointee, location)
763
769
{
@@ -869,7 +875,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
869
875
fn simplify_discriminant ( & mut self , place : VnIndex ) -> Option < VnIndex > {
870
876
let enum_ty = self . ty ( place) ;
871
877
if enum_ty. is_enum ( )
872
- && let Value :: Aggregate ( variant, _) = * self . get ( place)
878
+ && let Value :: Aggregate ( variant, _) = self . get ( place)
873
879
{
874
880
let discr = self . ecx . discriminant_for_variant ( enum_ty, variant) . discard_err ( ) ?;
875
881
return Some ( self . insert_scalar ( discr. layout . ty , discr. to_scalar ( ) ) ) ;
@@ -901,11 +907,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
901
907
fields : & [ VnIndex ] ,
902
908
) -> Option < VnIndex > {
903
909
let Some ( & first_field) = fields. first ( ) else { return None } ;
904
- let Value :: Projection ( copy_from_value, _) = * self . get ( first_field) else { return None } ;
910
+ let Value :: Projection ( copy_from_value, _) = self . get ( first_field) else { return None } ;
905
911
906
912
// All fields must correspond one-to-one and come from the same aggregate value.
907
913
if fields. iter ( ) . enumerate ( ) . any ( |( index, & v) | {
908
- if let Value :: Projection ( pointer, ProjectionElem :: Field ( from_index, _) ) = * self . get ( v)
914
+ if let Value :: Projection ( pointer, ProjectionElem :: Field ( from_index, _) ) = self . get ( v)
909
915
&& copy_from_value == pointer
910
916
&& from_index. index ( ) == index
911
917
{
@@ -917,7 +923,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
917
923
}
918
924
919
925
let mut copy_from_local_value = copy_from_value;
920
- if let Value :: Projection ( pointer, proj) = * self . get ( copy_from_value)
926
+ if let Value :: Projection ( pointer, proj) = self . get ( copy_from_value)
921
927
&& let ProjectionElem :: Downcast ( _, read_variant) = proj
922
928
{
923
929
if variant_index == read_variant {
@@ -962,13 +968,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
962
968
}
963
969
}
964
970
965
- let fields: Vec < _ > = field_ops
966
- . iter_mut ( )
967
- . map ( |op| {
968
- self . simplify_operand ( op, location)
969
- . unwrap_or_else ( || self . new_opaque ( op. ty ( self . local_decls , self . tcx ) ) )
970
- } )
971
- . collect ( ) ;
971
+ let fields = self . arena . alloc_from_iter ( field_ops. iter_mut ( ) . map ( |op| {
972
+ self . simplify_operand ( op, location)
973
+ . unwrap_or_else ( || self . new_opaque ( op. ty ( self . local_decls , self . tcx ) ) )
974
+ } ) ) ;
972
975
973
976
let variant_index = match * kind {
974
977
AggregateKind :: Array ( ..) | AggregateKind :: Tuple => {
@@ -989,12 +992,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
989
992
let mut was_updated = false ;
990
993
while let Value :: Cast { kind : CastKind :: PtrToPtr , value : cast_value } =
991
994
self . get ( pointer)
992
- && let ty:: RawPtr ( from_pointee_ty, from_mtbl) = self . ty ( * cast_value) . kind ( )
995
+ && let ty:: RawPtr ( from_pointee_ty, from_mtbl) = self . ty ( cast_value) . kind ( )
993
996
&& let ty:: RawPtr ( _, output_mtbl) = ty. kind ( )
994
997
&& from_mtbl == output_mtbl
995
998
&& from_pointee_ty. is_sized ( self . tcx , self . typing_env ( ) )
996
999
{
997
- pointer = * cast_value;
1000
+ pointer = cast_value;
998
1001
was_updated = true ;
999
1002
}
1000
1003
@@ -1059,9 +1062,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
1059
1062
// To allow things like `*mut (?A, ?T)` <-> `*mut (?B, ?T)`,
1060
1063
// it's fine to get a projection as the type.
1061
1064
Value :: Cast { kind : CastKind :: PtrToPtr , value : inner }
1062
- if self . pointers_have_same_metadata ( self . ty ( * inner) , arg_ty) =>
1065
+ if self . pointers_have_same_metadata ( self . ty ( inner) , arg_ty) =>
1063
1066
{
1064
- arg_index = * inner;
1067
+ arg_index = inner;
1065
1068
was_updated = true ;
1066
1069
continue ;
1067
1070
}
@@ -1088,15 +1091,15 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
1088
1091
}
1089
1092
1090
1093
let value = match ( op, self . get ( arg_index) ) {
1091
- ( UnOp :: Not , Value :: UnaryOp ( UnOp :: Not , inner) ) => return Some ( * inner) ,
1092
- ( UnOp :: Neg , Value :: UnaryOp ( UnOp :: Neg , inner) ) => return Some ( * inner) ,
1094
+ ( UnOp :: Not , Value :: UnaryOp ( UnOp :: Not , inner) ) => return Some ( inner) ,
1095
+ ( UnOp :: Neg , Value :: UnaryOp ( UnOp :: Neg , inner) ) => return Some ( inner) ,
1093
1096
( UnOp :: Not , Value :: BinaryOp ( BinOp :: Eq , lhs, rhs) ) => {
1094
- Value :: BinaryOp ( BinOp :: Ne , * lhs, * rhs)
1097
+ Value :: BinaryOp ( BinOp :: Ne , lhs, rhs)
1095
1098
}
1096
1099
( UnOp :: Not , Value :: BinaryOp ( BinOp :: Ne , lhs, rhs) ) => {
1097
- Value :: BinaryOp ( BinOp :: Eq , * lhs, * rhs)
1100
+ Value :: BinaryOp ( BinOp :: Eq , lhs, rhs)
1098
1101
}
1099
- ( UnOp :: PtrMetadata , Value :: RawPtr { metadata, .. } ) => return Some ( * metadata) ,
1102
+ ( UnOp :: PtrMetadata , Value :: RawPtr { metadata, .. } ) => return Some ( metadata) ,
1100
1103
// We have an unsizing cast, which assigns the length to wide pointer metadata.
1101
1104
(
1102
1105
UnOp :: PtrMetadata ,
@@ -1105,7 +1108,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
1105
1108
value : inner,
1106
1109
} ,
1107
1110
) if let ty:: Slice ( ..) = arg_ty. builtin_deref ( true ) . unwrap ( ) . kind ( )
1108
- && let ty:: Array ( _, len) = self . ty ( * inner) . builtin_deref ( true ) . unwrap ( ) . kind ( ) =>
1111
+ && let ty:: Array ( _, len) = self . ty ( inner) . builtin_deref ( true ) . unwrap ( ) . kind ( ) =>
1109
1112
{
1110
1113
return Some ( self . insert_constant ( Const :: Ty ( self . tcx . types . usize , * len) ) ) ;
1111
1114
}
@@ -1138,12 +1141,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
1138
1141
&& lhs_ty. is_any_ptr ( )
1139
1142
&& let Value :: Cast { kind : CastKind :: PtrToPtr , value : lhs_value } = self . get ( lhs)
1140
1143
&& let Value :: Cast { kind : CastKind :: PtrToPtr , value : rhs_value } = self . get ( rhs)
1141
- && let lhs_from = self . ty ( * lhs_value)
1142
- && lhs_from == self . ty ( * rhs_value)
1144
+ && let lhs_from = self . ty ( lhs_value)
1145
+ && lhs_from == self . ty ( rhs_value)
1143
1146
&& self . pointers_have_same_metadata ( lhs_from, lhs_ty)
1144
1147
{
1145
- lhs = * lhs_value;
1146
- rhs = * rhs_value;
1148
+ lhs = lhs_value;
1149
+ rhs = rhs_value;
1147
1150
if let Some ( lhs_op) = self . try_as_operand ( lhs, location)
1148
1151
&& let Some ( rhs_op) = self . try_as_operand ( rhs, location)
1149
1152
{
@@ -1277,7 +1280,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
1277
1280
if op. is_overflowing ( ) {
1278
1281
let ty = Ty :: new_tup ( self . tcx , & [ self . ty ( result) , self . tcx . types . bool ] ) ;
1279
1282
let false_val = self . insert_bool ( false ) ;
1280
- Some ( self . insert_tuple ( ty, vec ! [ result, false_val] ) )
1283
+ Some ( self . insert_tuple ( ty, & [ result, false_val] ) )
1281
1284
} else {
1282
1285
Some ( result)
1283
1286
}
@@ -1330,11 +1333,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
1330
1333
&& let ty:: RawPtr ( to_pointee, _) = to. kind ( )
1331
1334
&& to_pointee. is_sized ( self . tcx , self . typing_env ( ) )
1332
1335
{
1333
- from = self . ty ( * pointer) ;
1334
- value = * pointer;
1336
+ from = self . ty ( pointer) ;
1337
+ value = pointer;
1335
1338
was_updated_this_iteration = true ;
1336
1339
if from == to {
1337
- return Some ( * pointer) ;
1340
+ return Some ( pointer) ;
1338
1341
}
1339
1342
}
1340
1343
@@ -1343,7 +1346,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
1343
1346
if let Transmute = kind
1344
1347
&& let Value :: Aggregate ( variant_idx, field_values) = self . get ( value)
1345
1348
&& let Some ( ( field_idx, field_ty) ) =
1346
- self . value_is_all_in_one_field ( from, * variant_idx)
1349
+ self . value_is_all_in_one_field ( from, variant_idx)
1347
1350
{
1348
1351
from = field_ty;
1349
1352
value = field_values[ field_idx. as_usize ( ) ] ;
@@ -1354,7 +1357,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
1354
1357
}
1355
1358
1356
1359
// Various cast-then-cast cases can be simplified.
1357
- if let Value :: Cast { kind : inner_kind, value : inner_value } = * self . get ( value) {
1360
+ if let Value :: Cast { kind : inner_kind, value : inner_value } = self . get ( value) {
1358
1361
let inner_from = self . ty ( inner_value) ;
1359
1362
let new_kind = match ( inner_kind, kind) {
1360
1363
// Even if there's a narrowing cast in here that's fine, because
@@ -1428,7 +1431,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
1428
1431
// We have an unsizing cast, which assigns the length to wide pointer metadata.
1429
1432
if let Value :: Cast { kind, value : from } = self . get ( inner)
1430
1433
&& let CastKind :: PointerCoercion ( ty:: adjustment:: PointerCoercion :: Unsize , _) = kind
1431
- && let Some ( from) = self . ty ( * from) . builtin_deref ( true )
1434
+ && let Some ( from) = self . ty ( from) . builtin_deref ( true )
1432
1435
&& let ty:: Array ( _, len) = from. kind ( )
1433
1436
&& let Some ( to) = self . ty ( inner) . builtin_deref ( true )
1434
1437
&& let ty:: Slice ( ..) = to. kind ( )
@@ -1586,7 +1589,7 @@ fn op_to_prop_const<'tcx>(
1586
1589
None
1587
1590
}
1588
1591
1589
- impl < ' tcx > VnState < ' _ , ' tcx > {
1592
+ impl < ' tcx > VnState < ' _ , ' _ , ' tcx > {
1590
1593
/// If either [`Self::try_as_constant`] as [`Self::try_as_place`] succeeds,
1591
1594
/// returns that result as an [`Operand`].
1592
1595
fn try_as_operand ( & mut self , index : VnIndex , location : Location ) -> Option < Operand < ' tcx > > {
@@ -1605,7 +1608,7 @@ impl<'tcx> VnState<'_, 'tcx> {
1605
1608
// This was already constant in MIR, do not change it. If the constant is not
1606
1609
// deterministic, adding an additional mention of it in MIR will not give the same value as
1607
1610
// the former mention.
1608
- if let Value :: Constant { value, disambiguator : 0 } = * self . get ( index) {
1611
+ if let Value :: Constant { value, disambiguator : 0 } = self . get ( index) {
1609
1612
debug_assert ! ( value. is_deterministic( ) ) ;
1610
1613
return Some ( ConstOperand { span : DUMMY_SP , user_ty : None , const_ : value } ) ;
1611
1614
}
@@ -1649,7 +1652,7 @@ impl<'tcx> VnState<'_, 'tcx> {
1649
1652
// If we are here, we failed to find a local, and we already have a `Deref`.
1650
1653
// Trying to add projections will only result in an ill-formed place.
1651
1654
return None ;
1652
- } else if let Value :: Projection ( pointer, proj) = * self . get ( index)
1655
+ } else if let Value :: Projection ( pointer, proj) = self . get ( index)
1653
1656
&& ( allow_complex_projection || proj. is_stable_offset ( ) )
1654
1657
&& let Some ( proj) = self . try_as_place_elem ( self . ty ( index) , proj, loc)
1655
1658
{
@@ -1672,7 +1675,7 @@ impl<'tcx> VnState<'_, 'tcx> {
1672
1675
}
1673
1676
}
1674
1677
1675
- impl < ' tcx > MutVisitor < ' tcx > for VnState < ' _ , ' tcx > {
1678
+ impl < ' tcx > MutVisitor < ' tcx > for VnState < ' _ , ' _ , ' tcx > {
1676
1679
fn tcx ( & self ) -> TyCtxt < ' tcx > {
1677
1680
self . tcx
1678
1681
}
0 commit comments