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