summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_mir_build/src/build/matches/test.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_build/src/build/matches/test.rs')
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs52
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)
}