@@ -43,6 +43,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
43
43
TestKind :: Len { len : len as u64 , op }
44
44
}
45
45
46
+ TestCase :: Deref { temp } => TestKind :: Deref { temp } ,
47
+
46
48
TestCase :: Or { .. } => bug ! ( "or-patterns should have already been handled" ) ,
47
49
48
50
TestCase :: Irrefutable { .. } => span_bug ! (
@@ -145,35 +147,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
145
147
) ;
146
148
}
147
149
let re_erased = tcx. lifetimes . re_erased ;
148
- let ref_string = self . temp ( Ty :: new_imm_ref ( tcx, re_erased, ty) , test. span ) ;
149
150
let ref_str_ty = Ty :: new_imm_ref ( tcx, re_erased, tcx. types . str_ ) ;
150
151
let ref_str = self . temp ( ref_str_ty, test. span ) ;
151
- let deref = tcx. require_lang_item ( LangItem :: Deref , None ) ;
152
- let method = trait_method ( tcx, deref, sym:: deref, [ ty] ) ;
153
152
let eq_block = self . cfg . start_new_block ( ) ;
154
- self . cfg . push_assign (
155
- block,
156
- source_info,
157
- ref_string,
158
- Rvalue :: Ref ( re_erased, BorrowKind :: Shared , place) ,
159
- ) ;
160
- self . cfg . terminate (
161
- block,
162
- source_info,
163
- TerminatorKind :: Call {
164
- func : Operand :: Constant ( Box :: new ( ConstOperand {
165
- span : test. span ,
166
- user_ty : None ,
167
- const_ : method,
168
- } ) ) ,
169
- args : vec ! [ Spanned { node: Operand :: Move ( ref_string) , span: DUMMY_SP } ] ,
170
- destination : ref_str,
171
- target : Some ( eq_block) ,
172
- unwind : UnwindAction :: Continue ,
173
- call_source : CallSource :: Misc ,
174
- fn_span : source_info. span ,
175
- } ,
176
- ) ;
153
+ // `let ref_str: &str = <String as Deref>::deref(&place);`
154
+ self . call_deref ( block, eq_block, place, ty, ref_str, test. span ) ;
177
155
self . non_scalar_compare (
178
156
eq_block,
179
157
success_block,
@@ -272,9 +250,57 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
272
250
Operand :: Move ( expected) ,
273
251
) ;
274
252
}
253
+
254
+ TestKind :: Deref { temp } => {
255
+ let ty = place_ty. ty ;
256
+ let target = target_block ( TestBranch :: Success ) ;
257
+ self . call_deref ( block, target, place, ty, temp, test. span ) ;
258
+ }
275
259
}
276
260
}
277
261
262
+ /// Perform `let temp = Deref::deref(&place)`.
263
+ pub ( super ) fn call_deref (
264
+ & mut self ,
265
+ block : BasicBlock ,
266
+ target_block : BasicBlock ,
267
+ place : Place < ' tcx > ,
268
+ ty : Ty < ' tcx > ,
269
+ temp : Place < ' tcx > ,
270
+ span : Span ,
271
+ ) {
272
+ let source_info = self . source_info ( span) ;
273
+ let re_erased = self . tcx . lifetimes . re_erased ;
274
+ let deref = self . tcx . require_lang_item ( LangItem :: Deref , None ) ;
275
+ let method = trait_method ( self . tcx , deref, sym:: deref, [ ty] ) ;
276
+ let ref_src = self . temp ( Ty :: new_imm_ref ( self . tcx , re_erased, ty) , span) ;
277
+ // `let ref_src = &src_place;`
278
+ self . cfg . push_assign (
279
+ block,
280
+ source_info,
281
+ ref_src,
282
+ Rvalue :: Ref ( re_erased, BorrowKind :: Shared , place) ,
283
+ ) ;
284
+ // `let temp = <Ty as Deref>::deref(ref_src);`
285
+ self . cfg . terminate (
286
+ block,
287
+ source_info,
288
+ TerminatorKind :: Call {
289
+ func : Operand :: Constant ( Box :: new ( ConstOperand {
290
+ span,
291
+ user_ty : None ,
292
+ const_ : method,
293
+ } ) ) ,
294
+ args : vec ! [ Spanned { node: Operand :: Move ( ref_src) , span } ] ,
295
+ destination : temp,
296
+ target : Some ( target_block) ,
297
+ unwind : UnwindAction :: Continue ,
298
+ call_source : CallSource :: Misc ,
299
+ fn_span : source_info. span ,
300
+ } ,
301
+ ) ;
302
+ }
303
+
278
304
/// Compare using the provided built-in comparison operator
279
305
fn compare (
280
306
& mut self ,
@@ -657,13 +683,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
657
683
Some ( TestBranch :: Success )
658
684
}
659
685
686
+ ( TestKind :: Deref { temp : test_temp } , TestCase :: Deref { temp } )
687
+ if test_temp == temp =>
688
+ {
689
+ fully_matched = true ;
690
+ Some ( TestBranch :: Success )
691
+ }
692
+
660
693
(
661
694
TestKind :: Switch { .. }
662
695
| TestKind :: SwitchInt { .. }
663
696
| TestKind :: If
664
697
| TestKind :: Len { .. }
665
698
| TestKind :: Range { .. }
666
- | TestKind :: Eq { .. } ,
699
+ | TestKind :: Eq { .. }
700
+ | TestKind :: Deref { .. } ,
667
701
_,
668
702
) => {
669
703
fully_matched = false ;
0 commit comments