diff options
Diffstat (limited to 'compiler/rustc_mir_build/src/build/matches/test.rs')
-rw-r--r-- | compiler/rustc_mir_build/src/build/matches/test.rs | 52 |
1 files changed, 42 insertions, 10 deletions
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index b597ecfaa..58513bde2 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -150,11 +150,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match_start_span: Span, scrutinee_span: Span, block: BasicBlock, - place_builder: PlaceBuilder<'tcx>, + place_builder: &PlaceBuilder<'tcx>, test: &Test<'tcx>, make_target_blocks: impl FnOnce(&mut Self) -> Vec<BasicBlock>, ) { - let place = place_builder.into_place(self); + let place = place_builder.to_place(self); let place_ty = place.ty(&self.local_decls, self.tcx); debug!(?place, ?place_ty,); @@ -240,6 +240,39 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } TestKind::Eq { value, ty } => { + let tcx = self.tcx; + if let ty::Adt(def, _) = ty.kind() && Some(def.did()) == tcx.lang_items().string() { + if !tcx.features().string_deref_patterns { + bug!("matching on `String` went through without enabling string_deref_patterns"); + } + let re_erased = tcx.lifetimes.re_erased; + let ref_string = self.temp(tcx.mk_imm_ref(re_erased, ty), test.span); + let ref_str_ty = tcx.mk_imm_ref(re_erased, tcx.types.str_); + let ref_str = self.temp(ref_str_ty, test.span); + let deref = tcx.require_lang_item(LangItem::Deref, None); + let method = trait_method(tcx, deref, sym::deref, [ty]); + let eq_block = self.cfg.start_new_block(); + self.cfg.push_assign(block, source_info, ref_string, Rvalue::Ref(re_erased, BorrowKind::Shared, place)); + self.cfg.terminate( + block, + source_info, + TerminatorKind::Call { + func: Operand::Constant(Box::new(Constant { + span: test.span, + user_ty: None, + literal: method, + })), + args: vec![Operand::Move(ref_string)], + destination: ref_str, + target: Some(eq_block), + cleanup: None, + from_hir_call: false, + fn_span: source_info.span + } + ); + self.non_scalar_compare(eq_block, make_target_blocks, source_info, value, ref_str, ref_str_ty); + return; + } if !ty.is_scalar() { // Use `PartialEq::eq` instead of `BinOp::Eq` // (the binop can only handle primitives) @@ -411,8 +444,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { bug!("non_scalar_compare called on non-reference type: {}", ty); }; - let eq_def_id = self.tcx.require_lang_item(LangItem::PartialEq, None); - let method = trait_method(self.tcx, eq_def_id, sym::eq, deref_ty, &[deref_ty.into()]); + let eq_def_id = self.tcx.require_lang_item(LangItem::PartialEq, Some(source_info.span)); + let method = trait_method(self.tcx, eq_def_id, sym::eq, [deref_ty, deref_ty]); let bool_ty = self.tcx.types.bool; let eq_result = self.temp(bool_ty, source_info.span); @@ -727,7 +760,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let downcast_place = match_pair.place.downcast(adt_def, variant_index); // `(x as Variant)` let consequent_match_pairs = subpatterns.iter().map(|subpattern| { // e.g., `(x as Variant).0` - let place = downcast_place.clone().field(subpattern.field, subpattern.pattern.ty); + let place = downcast_place + .clone_project(PlaceElem::Field(subpattern.field, subpattern.pattern.ty)); // e.g., `(x as Variant).0 @ P1` MatchPair::new(place, &subpattern.pattern, self) }); @@ -804,10 +838,9 @@ fn trait_method<'tcx>( tcx: TyCtxt<'tcx>, trait_def_id: DefId, method_name: Symbol, - self_ty: Ty<'tcx>, - params: &[GenericArg<'tcx>], + substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>, ) -> ConstantKind<'tcx> { - let substs = tcx.mk_substs_trait(self_ty, params); + let substs = tcx.mk_substs(substs.into_iter().map(Into::into)); // The unhygienic comparison here is acceptable because this is only // used on known traits. @@ -817,8 +850,7 @@ fn trait_method<'tcx>( .find(|item| item.kind == ty::AssocKind::Fn) .expect("trait method not found"); - let method_ty = tcx.bound_type_of(item.def_id); - let method_ty = method_ty.subst(tcx, substs); + let method_ty = tcx.mk_fn_def(item.def_id, substs); ConstantKind::zero_sized(method_ty) } |