diff options
6 files changed, 47 insertions, 23 deletions
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index e2b41516bf6..4d9e9b7c473 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -293,6 +293,10 @@ impl<'tcx> PlaceBuilder<'tcx> { self.base } + pub(crate) fn projection(&self) -> &[PlaceElem<'tcx>] { + &self.projection + } + pub(crate) fn field(self, f: Field, ty: Ty<'tcx>) -> Self { self.project(PlaceElem::Field(f, ty)) } diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index d283c33a005..34a310539f0 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -244,7 +244,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .map(|arm| { let arm = &self.thir[arm]; let arm_has_guard = arm.guard.is_some(); - let arm_candidate = Candidate::new(scrutinee.clone(), &arm.pattern, arm_has_guard); + let arm_candidate = + Candidate::new(scrutinee.clone(), &arm.pattern, arm_has_guard, self); (arm, arm_candidate) }) .collect() @@ -578,7 +579,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { initializer: PlaceBuilder<'tcx>, set_match_place: bool, ) -> BlockAnd<()> { - let mut candidate = Candidate::new(initializer.clone(), &irrefutable_pat, false); + let mut candidate = Candidate::new(initializer.clone(), &irrefutable_pat, false, self); let fake_borrow_temps = self.lower_match_tree( block, irrefutable_pat.span, @@ -859,11 +860,16 @@ struct Candidate<'pat, 'tcx> { } impl<'tcx, 'pat> Candidate<'pat, 'tcx> { - fn new(place: PlaceBuilder<'tcx>, pattern: &'pat Pat<'tcx>, has_guard: bool) -> Self { + fn new( + place: PlaceBuilder<'tcx>, + pattern: &'pat Pat<'tcx>, + has_guard: bool, + cx: &Builder<'_, 'tcx>, + ) -> Self { Candidate { span: pattern.span, has_guard, - match_pairs: smallvec![MatchPair::new(place, pattern)], + match_pairs: smallvec![MatchPair::new(place, pattern, cx)], bindings: Vec::new(), ascriptions: Vec::new(), subcandidates: Vec::new(), @@ -1383,7 +1389,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { debug!("candidate={:#?}\npats={:#?}", candidate, pats); let mut or_candidates: Vec<_> = pats .iter() - .map(|pat| Candidate::new(place.clone(), pat, candidate.has_guard)) + .map(|pat| Candidate::new(place.clone(), pat, candidate.has_guard, self)) .collect(); let mut or_candidate_refs: Vec<_> = or_candidates.iter_mut().collect(); let otherwise = if candidate.otherwise_block.is_some() { @@ -1779,8 +1785,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let expr_span = expr.span; let expr_place_builder = unpack!(block = self.lower_scrutinee(block, expr, expr_span)); let wildcard = Pat::wildcard_from_ty(pat.ty); - let mut guard_candidate = Candidate::new(expr_place_builder.clone(), &pat, false); - let mut otherwise_candidate = Candidate::new(expr_place_builder.clone(), &wildcard, false); + let mut guard_candidate = Candidate::new(expr_place_builder.clone(), &pat, false, self); + let mut otherwise_candidate = + Candidate::new(expr_place_builder.clone(), &wildcard, false, self); let fake_borrow_temps = self.lower_match_tree( block, pat.span, @@ -2276,8 +2283,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let (matching, failure) = self.in_if_then_scope(*let_else_scope, |this| { let scrutinee = unpack!(block = this.lower_scrutinee(block, init, initializer_span)); let pat = Pat { ty: init.ty, span: else_block_span, kind: PatKind::Wild }; - let mut wildcard = Candidate::new(scrutinee.clone(), &pat, false); - let mut candidate = Candidate::new(scrutinee.clone(), pattern, false); + let mut wildcard = Candidate::new(scrutinee.clone(), &pat, false, this); + let mut candidate = Candidate::new(scrutinee.clone(), pattern, false, this); let fake_borrow_temps = this.lower_match_tree( block, 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 7117554933d..828f32db361 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -132,7 +132,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ) -> Vec<Candidate<'pat, 'tcx>> { pats.iter() .map(|box pat| { - let mut candidate = Candidate::new(place.clone(), pat, candidate.has_guard); + let mut candidate = Candidate::new(place.clone(), pat, candidate.has_guard, self); self.simplify_candidate(&mut candidate); candidate }) @@ -164,7 +164,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }); } - candidate.match_pairs.push(MatchPair::new(match_pair.place, subpattern)); + candidate.match_pairs.push(MatchPair::new(match_pair.place, subpattern, self)); Ok(()) } @@ -194,7 +194,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if let Some(subpattern) = subpattern.as_ref() { // this is the `x @ P` case; have to keep matching against `P` now - candidate.match_pairs.push(MatchPair::new(match_pair.place, subpattern)); + candidate.match_pairs.push(MatchPair::new(match_pair.place, subpattern, self)); } Ok(()) @@ -305,7 +305,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { PatKind::Deref { ref subpattern } => { let place_builder = match_pair.place.deref(); - candidate.match_pairs.push(MatchPair::new(place_builder, subpattern)); + candidate.match_pairs.push(MatchPair::new(place_builder, subpattern, self)); Ok(()) } diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index a8adf490db8..9f9987edbfd 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -729,7 +729,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // e.g., `(x as Variant).0` let place = downcast_place.clone().field(subpattern.field, subpattern.pattern.ty); // e.g., `(x as Variant).0 @ P1` - MatchPair::new(place, &subpattern.pattern) + MatchPair::new(place, &subpattern.pattern, self) }); candidate.match_pairs.extend(consequent_match_pairs); diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs index 0b20300293b..d77d296f206 100644 --- a/compiler/rustc_mir_build/src/build/matches/util.rs +++ b/compiler/rustc_mir_build/src/build/matches/util.rs @@ -1,9 +1,11 @@ +use crate::build::expr::as_place::PlaceBase; use crate::build::expr::as_place::PlaceBuilder; use crate::build::matches::MatchPair; use crate::build::Builder; use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty; +use rustc_middle::ty::TypeVisitable; use smallvec::SmallVec; use std::convert::TryInto; @@ -17,7 +19,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .iter() .map(|fieldpat| { let place = place.clone().field(fieldpat.field, fieldpat.pattern.ty); - MatchPair::new(place, &fieldpat.pattern) + MatchPair::new(place, &fieldpat.pattern, self) }) .collect() } @@ -45,7 +47,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let elem = ProjectionElem::ConstantIndex { offset: idx as u64, min_length, from_end: false }; let place = place.clone().project(elem); - MatchPair::new(place, subpattern) + MatchPair::new(place, subpattern, self) })); if let Some(subslice_pat) = opt_slice { @@ -55,7 +57,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { to: if exact_size { min_length - suffix_len } else { suffix_len }, from_end: !exact_size, }); - match_pairs.push(MatchPair::new(subslice, subslice_pat)); + match_pairs.push(MatchPair::new(subslice, subslice_pat, self)); } match_pairs.extend(suffix.iter().rev().enumerate().map(|(idx, subpattern)| { @@ -66,7 +68,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { from_end: !exact_size, }; let place = place.clone().project(elem); - MatchPair::new(place, subpattern) + MatchPair::new(place, subpattern, self) })); } @@ -95,14 +97,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { pub(in crate::build) fn new( - mut place: PlaceBuilder<'tcx>, + 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? - // FIXME(oli-obk): only add this projection if `place` actually had an opaque - // type before the projection. - place = place.project(ProjectionElem::OpaqueCast(pattern.ty)); + let mut place = match place.try_upvars_resolved(cx) { + Ok(val) | Err(val) => val, + }; + let may_need_cast = match place.base() { + PlaceBase::Local(local) => { + let ty = Place::ty_from(local, place.projection(), &cx.local_decls, cx.tcx).ty; + ty != pattern.ty && ty.has_opaque_types() + } + _ => true, + }; + if may_need_cast { + place = place.project(ProjectionElem::OpaqueCast(pattern.ty)); + } MatchPair { place, pattern } } } diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index c0b0cc3c591..702ca2eaf5c 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -893,7 +893,7 @@ where } ty::Slice(ety) => self.open_drop_for_array(*ety, None), - _ => bug!("open drop from non-ADT `{:?}`", ty), + _ => span_bug!(self.source_info.span, "open drop from non-ADT `{:?}`", ty), } } |
