@@ -43,6 +43,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
4343 TestKind :: Len { len : len as u64 , op }
4444 }
4545
46+ TestCase :: Deref { temp } => TestKind :: Deref { temp } ,
47+
4648 TestCase :: Or { .. } => bug ! ( "or-patterns should have already been handled" ) ,
4749
4850 TestCase :: Irrefutable { .. } => span_bug ! (
@@ -145,35 +147,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
145147 ) ;
146148 }
147149 let re_erased = tcx. lifetimes . re_erased ;
148- let ref_string = self . temp ( Ty :: new_imm_ref ( tcx, re_erased, ty) , test. span ) ;
149150 let ref_str_ty = Ty :: new_imm_ref ( tcx, re_erased, tcx. types . str_ ) ;
150151 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] ) ;
153152 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 ) ;
177155 self . non_scalar_compare (
178156 eq_block,
179157 success_block,
@@ -272,9 +250,57 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
272250 Operand :: Move ( expected) ,
273251 ) ;
274252 }
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+ }
275259 }
276260 }
277261
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+
278304 /// Compare using the provided built-in comparison operator
279305 fn compare (
280306 & mut self ,
@@ -657,13 +683,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
657683 Some ( TestBranch :: Success )
658684 }
659685
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+
660693 (
661694 TestKind :: Switch { .. }
662695 | TestKind :: SwitchInt { .. }
663696 | TestKind :: If
664697 | TestKind :: Len { .. }
665698 | TestKind :: Range { .. }
666- | TestKind :: Eq { .. } ,
699+ | TestKind :: Eq { .. }
700+ | TestKind :: Deref { .. } ,
667701 _,
668702 ) => {
669703 fully_matched = false ;
0 commit comments