summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_mir_build/src/build/matches
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:18:25 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:18:25 +0000
commit5363f350887b1e5b5dd21a86f88c8af9d7fea6da (patch)
tree35ca005eb6e0e9a1ba3bb5dbc033209ad445dc17 /compiler/rustc_mir_build/src/build/matches
parentAdding debian version 1.66.0+dfsg1-1. (diff)
downloadrustc-5363f350887b1e5b5dd21a86f88c8af9d7fea6da.tar.xz
rustc-5363f350887b1e5b5dd21a86f88c8af9d7fea6da.zip
Merging upstream version 1.67.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_mir_build/src/build/matches')
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs123
-rw-r--r--compiler/rustc_mir_build/src/build/matches/simplify.rs19
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs52
-rw-r--r--compiler/rustc_mir_build/src/build/matches/util.rs35
4 files changed, 113 insertions, 116 deletions
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 3f813e0af..691cbee2c 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -84,6 +84,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
break_scope,
Some(variable_source_info.scope),
variable_source_info.span,
+ true,
),
_ => {
let temp_scope = temp_scope_override.unwrap_or_else(|| this.local_scope());
@@ -168,7 +169,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let scrutinee_place =
unpack!(block = self.lower_scrutinee(block, scrutinee, scrutinee_span,));
- let mut arm_candidates = self.create_match_candidates(scrutinee_place.clone(), &arms);
+ let mut arm_candidates = self.create_match_candidates(&scrutinee_place, &arms);
let match_has_guard = arm_candidates.iter().any(|(_, candidate)| candidate.has_guard);
let mut candidates =
@@ -220,8 +221,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let cause_matched_place = FakeReadCause::ForMatchedPlace(None);
let source_info = self.source_info(scrutinee_span);
- if let Ok(scrutinee_builder) = scrutinee_place_builder.clone().try_upvars_resolved(self) {
- let scrutinee_place = scrutinee_builder.into_place(self);
+ if let Some(scrutinee_place) = scrutinee_place_builder.try_to_place(self) {
self.cfg.push_fake_read(block, source_info, cause_matched_place, scrutinee_place);
}
@@ -231,7 +231,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Create the initial `Candidate`s for a `match` expression.
fn create_match_candidates<'pat>(
&mut self,
- scrutinee: PlaceBuilder<'tcx>,
+ scrutinee: &PlaceBuilder<'tcx>,
arms: &'pat [ArmId],
) -> Vec<(&'pat Arm<'tcx>, Candidate<'pat, 'tcx>)>
where
@@ -334,7 +334,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let arm_scope = (arm.scope, arm_source_info);
let match_scope = self.local_scope();
self.in_scope(arm_scope, arm.lint_level, |this| {
- // `try_upvars_resolved` may fail if it is unable to resolve the given
+ // `try_to_place` may fail if it is unable to resolve the given
// `PlaceBuilder` inside a closure. In this case, we don't want to include
// a scrutinee place. `scrutinee_place_builder` will fail to be resolved
// if the only match arm is a wildcard (`_`).
@@ -345,31 +345,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// match foo { _ => () };
// };
// ```
- let mut opt_scrutinee_place: Option<(Option<&Place<'tcx>>, Span)> = None;
- let scrutinee_place: Place<'tcx>;
- if let Ok(scrutinee_builder) =
- scrutinee_place_builder.clone().try_upvars_resolved(this)
- {
- scrutinee_place = scrutinee_builder.into_place(this);
- opt_scrutinee_place = Some((Some(&scrutinee_place), scrutinee_span));
- }
+ let scrutinee_place = scrutinee_place_builder.try_to_place(this);
+ let opt_scrutinee_place =
+ scrutinee_place.as_ref().map(|place| (Some(place), scrutinee_span));
let scope = this.declare_bindings(
None,
arm.span,
&arm.pattern,
- ArmHasGuard(arm.guard.is_some()),
+ arm.guard.as_ref(),
opt_scrutinee_place,
);
let arm_block = this.bind_pattern(
outer_source_info,
candidate,
- arm.guard.as_ref(),
&fake_borrow_temps,
scrutinee_span,
- Some(arm.span),
- Some(arm.scope),
- Some(match_scope),
+ Some((arm, match_scope)),
false,
);
@@ -410,12 +402,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
&mut self,
outer_source_info: SourceInfo,
candidate: Candidate<'_, 'tcx>,
- guard: Option<&Guard<'tcx>>,
fake_borrow_temps: &[(Place<'tcx>, Local)],
scrutinee_span: Span,
- arm_span: Option<Span>,
- arm_scope: Option<region::Scope>,
- match_scope: Option<region::Scope>,
+ arm_match_scope: Option<(&Arm<'tcx>, region::Scope)>,
storages_alive: bool,
) -> BasicBlock {
if candidate.subcandidates.is_empty() {
@@ -424,11 +413,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.bind_and_guard_matched_candidate(
candidate,
&[],
- guard,
fake_borrow_temps,
scrutinee_span,
- arm_span,
- match_scope,
+ arm_match_scope,
true,
storages_alive,
)
@@ -449,6 +436,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// we lower the guard.
let target_block = self.cfg.start_new_block();
let mut schedule_drops = true;
+ let arm = arm_match_scope.unzip().0;
// We keep a stack of all of the bindings and type ascriptions
// from the parent candidates that we visit, that also need to
// be bound for each candidate.
@@ -456,21 +444,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
candidate,
&mut Vec::new(),
&mut |leaf_candidate, parent_bindings| {
- if let Some(arm_scope) = arm_scope {
- self.clear_top_scope(arm_scope);
+ if let Some(arm) = arm {
+ self.clear_top_scope(arm.scope);
}
let binding_end = self.bind_and_guard_matched_candidate(
leaf_candidate,
parent_bindings,
- guard,
&fake_borrow_temps,
scrutinee_span,
- arm_span,
- match_scope,
+ arm_match_scope,
schedule_drops,
storages_alive,
);
- if arm_scope.is_none() {
+ if arm.is_none() {
schedule_drops = false;
}
self.cfg.goto(binding_end, outer_source_info, target_block);
@@ -600,7 +586,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
while let Some(next) = {
for binding in &candidate_ref.bindings {
let local = self.var_local_id(binding.var_id, OutsideGuard);
- // `try_upvars_resolved` may fail if it is unable to resolve the given
+ // `try_to_place` may fail if it is unable to resolve the given
// `PlaceBuilder` inside a closure. In this case, we don't want to include
// a scrutinee place. `scrutinee_place_builder` will fail for destructured
// assignments. This is because a closure only captures the precise places
@@ -614,9 +600,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// let (v1, v2) = foo;
// };
// ```
- if let Ok(match_pair_resolved) = initializer.clone().try_upvars_resolved(self) {
- let place = match_pair_resolved.into_place(self);
-
+ if let Some(place) = initializer.try_to_place(self) {
let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. },
)))) = self.local_decls[local].local_info else {
@@ -636,12 +620,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.bind_pattern(
self.source_info(irrefutable_pat.span),
candidate,
- None,
&fake_borrow_temps,
irrefutable_pat.span,
None,
- None,
- None,
false,
)
.unit()
@@ -657,7 +638,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
mut visibility_scope: Option<SourceScope>,
scope_span: Span,
pattern: &Pat<'tcx>,
- has_guard: ArmHasGuard,
+ guard: Option<&Guard<'tcx>>,
opt_match_place: Option<(Option<&Place<'tcx>>, Span)>,
) -> Option<SourceScope> {
self.visit_primary_bindings(
@@ -679,12 +660,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
var,
ty,
user_ty,
- has_guard,
+ ArmHasGuard(guard.is_some()),
opt_match_place.map(|(x, y)| (x.cloned(), y)),
pattern.span,
);
},
);
+ if let Some(Guard::IfLet(guard_pat, _)) = guard {
+ // FIXME: pass a proper `opt_match_place`
+ self.declare_bindings(visibility_scope, scope_span, guard_pat, None, None);
+ }
visibility_scope
}
@@ -1352,7 +1337,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
bug!("Or-patterns should have been sorted to the end");
};
let or_span = match_pair.pattern.span;
- let place = match_pair.place;
first_candidate.visit_leaves(|leaf_candidate| {
self.test_or_pattern(
@@ -1360,7 +1344,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
&mut otherwise,
pats,
or_span,
- place.clone(),
+ &match_pair.place,
fake_borrows,
);
});
@@ -1388,7 +1372,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
otherwise: &mut Option<BasicBlock>,
pats: &'pat [Box<Pat<'tcx>>],
or_span: Span,
- place: PlaceBuilder<'tcx>,
+ place: &PlaceBuilder<'tcx>,
fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
) {
debug!("candidate={:#?}\npats={:#?}", candidate, pats);
@@ -1606,10 +1590,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
// Insert a Shallow borrow of any places that is switched on.
- if let Some(fb) = fake_borrows && let Ok(match_place_resolved) =
- match_place.clone().try_upvars_resolved(self)
+ if let Some(fb) = fake_borrows
+ && let Some(resolved_place) = match_place.try_to_place(self)
{
- let resolved_place = match_place_resolved.into_place(self);
fb.insert(resolved_place);
}
@@ -1628,7 +1611,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// encounter a candidate where the test is not relevant; at
// that point, we stop sorting.
while let Some(candidate) = candidates.first_mut() {
- let Some(idx) = self.sort_candidate(&match_place.clone(), &test, candidate) else {
+ let Some(idx) = self.sort_candidate(&match_place, &test, candidate) else {
break;
};
let (candidate, rest) = candidates.split_first_mut().unwrap();
@@ -1697,7 +1680,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
target_blocks
};
- self.perform_test(span, scrutinee_span, block, match_place, &test, make_target_blocks);
+ self.perform_test(span, scrutinee_span, block, &match_place, &test, make_target_blocks);
}
/// Determine the fake borrows that are needed from a set of places that
@@ -1778,6 +1761,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// Pat binding - used for `let` and function parameters as well.
impl<'a, 'tcx> Builder<'a, 'tcx> {
+ /// If the bindings have already been declared, set `declare_bindings` to
+ /// `false` to avoid duplicated bindings declaration. Used for if-let guards.
pub(crate) fn lower_let_expr(
&mut self,
mut block: BasicBlock,
@@ -1786,6 +1771,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
else_target: region::Scope,
source_scope: Option<SourceScope>,
span: Span,
+ declare_bindings: bool,
) -> BlockAnd<()> {
let expr_span = expr.span;
let expr_place_builder = unpack!(block = self.lower_scrutinee(block, expr, expr_span));
@@ -1800,32 +1786,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
false,
&mut [&mut guard_candidate, &mut otherwise_candidate],
);
- let mut opt_expr_place: Option<(Option<&Place<'tcx>>, Span)> = None;
- let expr_place: Place<'tcx>;
- if let Ok(expr_builder) = expr_place_builder.try_upvars_resolved(self) {
- expr_place = expr_builder.into_place(self);
- opt_expr_place = Some((Some(&expr_place), expr_span));
- }
+ let expr_place = expr_place_builder.try_to_place(self);
+ let opt_expr_place = expr_place.as_ref().map(|place| (Some(place), expr_span));
let otherwise_post_guard_block = otherwise_candidate.pre_binding_block.unwrap();
self.break_for_else(otherwise_post_guard_block, else_target, self.source_info(expr_span));
- self.declare_bindings(
- source_scope,
- pat.span.to(span),
- pat,
- ArmHasGuard(false),
- opt_expr_place,
- );
+ if declare_bindings {
+ self.declare_bindings(source_scope, pat.span.to(span), pat, None, opt_expr_place);
+ }
let post_guard_block = self.bind_pattern(
self.source_info(pat.span),
guard_candidate,
- None,
&fake_borrow_temps,
expr.span,
None,
- None,
- None,
false,
);
@@ -1844,11 +1819,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
&mut self,
candidate: Candidate<'pat, 'tcx>,
parent_bindings: &[(Vec<Binding<'tcx>>, Vec<Ascription<'tcx>>)],
- guard: Option<&Guard<'tcx>>,
fake_borrows: &[(Place<'tcx>, Local)],
scrutinee_span: Span,
- arm_span: Option<Span>,
- match_scope: Option<region::Scope>,
+ arm_match_scope: Option<(&Arm<'tcx>, region::Scope)>,
schedule_drops: bool,
storages_alive: bool,
) -> BasicBlock {
@@ -1960,7 +1933,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// the reference that we create for the arm.
// * So we eagerly create the reference for the arm and then take a
// reference to that.
- if let Some(guard) = guard {
+ if let Some((arm, match_scope)) = arm_match_scope
+ && let Some(guard) = &arm.guard
+ {
let tcx = self.tcx;
let bindings = parent_bindings
.iter()
@@ -1981,8 +1956,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.cfg.push_assign(block, scrutinee_source_info, Place::from(temp), borrow);
}
- let arm_span = arm_span.unwrap();
- let match_scope = match_scope.unwrap();
let mut guard_span = rustc_span::DUMMY_SP;
let (post_guard_block, otherwise_post_guard_block) =
@@ -1995,13 +1968,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
e,
None,
match_scope,
- this.source_info(arm_span),
+ this.source_info(arm.span),
)
}
Guard::IfLet(ref pat, scrutinee) => {
let s = &this.thir[scrutinee];
guard_span = s.span;
- this.lower_let_expr(block, s, pat, match_scope, None, arm_span)
+ this.lower_let_expr(block, s, pat, match_scope, None, arm.span, false)
}
});
@@ -2317,24 +2290,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let matching = this.bind_pattern(
this.source_info(pattern.span),
candidate,
- None,
&fake_borrow_temps,
initializer_span,
None,
- None,
- None,
true,
);
// This block is for the failure case
let failure = this.bind_pattern(
this.source_info(else_block_span),
wildcard,
- None,
&fake_borrow_temps,
initializer_span,
None,
- None,
- None,
true,
);
this.break_for_else(failure, *let_else_scope, this.source_info(initializer_span));
diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs
index 924d2f555..f6b1955fd 100644
--- a/compiler/rustc_mir_build/src/build/matches/simplify.rs
+++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs
@@ -73,8 +73,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
{
existing_bindings.extend_from_slice(&new_bindings);
mem::swap(&mut candidate.bindings, &mut existing_bindings);
- candidate.subcandidates =
- self.create_or_subcandidates(candidate, place.clone(), pats);
+ candidate.subcandidates = self.create_or_subcandidates(candidate, &place, pats);
return true;
}
@@ -127,7 +126,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
fn create_or_subcandidates<'pat>(
&mut self,
candidate: &Candidate<'pat, 'tcx>,
- place: PlaceBuilder<'tcx>,
+ place: &PlaceBuilder<'tcx>,
pats: &'pat [Box<Pat<'tcx>>],
) -> Vec<Candidate<'pat, 'tcx>> {
pats.iter()
@@ -156,10 +155,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
ascription: thir::Ascription { ref annotation, variance },
} => {
// Apply the type ascription to the value at `match_pair.place`, which is the
- if let Ok(place_resolved) = match_pair.place.clone().try_upvars_resolved(self) {
+ if let Some(source) = match_pair.place.try_to_place(self) {
candidate.ascriptions.push(Ascription {
annotation: annotation.clone(),
- source: place_resolved.into_place(self),
+ source,
variance,
});
}
@@ -183,10 +182,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
ref subpattern,
is_primary: _,
} => {
- if let Ok(place_resolved) = match_pair.place.clone().try_upvars_resolved(self) {
+ if let Some(source) = match_pair.place.try_to_place(self) {
candidate.bindings.push(Binding {
span: match_pair.pattern.span,
- source: place_resolved.into_place(self),
+ source,
var_id: var,
binding_mode: mode,
});
@@ -264,10 +263,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| {
i == variant_index || {
self.tcx.features().exhaustive_patterns
- && v.inhabited_predicate(self.tcx, adt_def)
+ && !v
+ .inhabited_predicate(self.tcx, adt_def)
.subst(self.tcx, substs)
- .apply_any_module(self.tcx, self.param_env)
- != Some(true)
+ .apply_ignore_module(self.tcx, self.param_env)
}
}) && (adt_def.did().is_local()
|| !adt_def.is_variant_list_non_exhaustive());
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)
}
diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs
index b854ba47f..bd435f9ab 100644
--- a/compiler/rustc_mir_build/src/build/matches/util.rs
+++ b/compiler/rustc_mir_build/src/build/matches/util.rs
@@ -18,7 +18,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
subpatterns
.iter()
.map(|fieldpat| {
- let place = place.clone().field(fieldpat.field, fieldpat.pattern.ty);
+ let place =
+ place.clone_project(PlaceElem::Field(fieldpat.field, fieldpat.pattern.ty));
MatchPair::new(place, &fieldpat.pattern, self)
})
.collect()
@@ -33,26 +34,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
suffix: &'pat [Box<Pat<'tcx>>],
) {
let tcx = self.tcx;
- let (min_length, exact_size) =
- if let Ok(place_resolved) = place.clone().try_upvars_resolved(self) {
- match place_resolved.into_place(self).ty(&self.local_decls, tcx).ty.kind() {
- ty::Array(_, length) => (length.eval_usize(tcx, self.param_env), true),
- _ => ((prefix.len() + suffix.len()).try_into().unwrap(), false),
- }
- } else {
- ((prefix.len() + suffix.len()).try_into().unwrap(), false)
- };
+ let (min_length, exact_size) = if let Some(place_resolved) = place.try_to_place(self) {
+ match place_resolved.ty(&self.local_decls, tcx).ty.kind() {
+ ty::Array(_, length) => (length.eval_usize(tcx, self.param_env), true),
+ _ => ((prefix.len() + suffix.len()).try_into().unwrap(), false),
+ }
+ } else {
+ ((prefix.len() + suffix.len()).try_into().unwrap(), false)
+ };
match_pairs.extend(prefix.iter().enumerate().map(|(idx, subpattern)| {
let elem =
ProjectionElem::ConstantIndex { offset: idx as u64, min_length, from_end: false };
- let place = place.clone().project(elem);
- MatchPair::new(place, subpattern, self)
+ MatchPair::new(place.clone_project(elem), subpattern, self)
}));
if let Some(subslice_pat) = opt_slice {
let suffix_len = suffix.len() as u64;
- let subslice = place.clone().project(ProjectionElem::Subslice {
+ let subslice = place.clone_project(PlaceElem::Subslice {
from: prefix.len() as u64,
to: if exact_size { min_length - suffix_len } else { suffix_len },
from_end: !exact_size,
@@ -67,7 +66,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
min_length,
from_end: !exact_size,
};
- let place = place.clone().project(elem);
+ let place = place.clone_project(elem);
MatchPair::new(place, subpattern, self)
}));
}
@@ -97,15 +96,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
pub(in crate::build) fn new(
- place: PlaceBuilder<'tcx>,
+ mut place: PlaceBuilder<'tcx>,
pattern: &'pat Pat<'tcx>,
cx: &Builder<'_, 'tcx>,
) -> MatchPair<'pat, 'tcx> {
// Force the place type to the pattern's type.
// FIXME(oli-obk): can we use this to simplify slice/array pattern hacks?
- let mut place = match place.try_upvars_resolved(cx) {
- Ok(val) | Err(val) => val,
- };
+ if let Some(resolved) = place.resolve_upvar(cx) {
+ place = resolved;
+ }
// Only add the OpaqueCast projection if the given place is an opaque type and the
// expected type from the pattern is not.