From b1a0607e10e8eeb8c4d55523f8491511a4cf32e2 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 20 Feb 2024 22:36:48 +0100 Subject: [PATCH] Process bindings and ascriptions in `MatchPair::new()` --- .../rustc_mir_build/src/build/matches/mod.rs | 2 +- .../src/build/matches/simplify.rs | 80 ++---------------- .../rustc_mir_build/src/build/matches/test.rs | 2 +- .../rustc_mir_build/src/build/matches/util.rs | 83 +++++++++++++++---- 4 files changed, 77 insertions(+), 90 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 20f74a2569c9..f9a8795f5d6e 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -1054,7 +1054,7 @@ struct Ascription<'tcx> { #[derive(Debug, Clone)] enum TestCase<'pat, 'tcx> { - Irrefutable, + Irrefutable { binding: Option>, ascription: Option> }, Variant { adt_def: ty::AdtDef<'tcx>, variant_index: VariantIdx }, Constant { value: mir::Const<'tcx> }, Range(&'pat PatRange<'tcx>), diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index 28971d4de44b..a78dda39e888 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -15,9 +15,7 @@ use crate::build::expr::as_place::PlaceBuilder; use crate::build::matches::{Ascription, Binding, Candidate, MatchPair, TestCase}; use crate::build::Builder; -use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_middle::thir::{self, *}; -use rustc_middle::ty; +use rustc_middle::thir::{Pat, PatKind}; use std::mem; @@ -128,79 +126,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ascriptions: &mut Vec>, match_pairs: &mut Vec>, ) -> Result<(), MatchPair<'pat, 'tcx>> { - // Collect bindings and ascriptions. - match match_pair.pattern.kind { - PatKind::AscribeUserType { - ascription: thir::Ascription { ref annotation, variance }, - .. - } => { - // Apply the type ascription to the value at `match_pair.place` - if let Some(source) = match_pair.place.try_to_place(self) { - ascriptions.push(Ascription { - annotation: annotation.clone(), - source, - variance, - }); - } + if let TestCase::Irrefutable { binding, ascription } = match_pair.test_case { + if let Some(binding) = binding { + bindings.push(binding); } - - PatKind::Binding { - name: _, - mutability: _, - mode, - var, - ty: _, - subpattern: _, - is_primary: _, - } => { - if let Some(source) = match_pair.place.try_to_place(self) { - bindings.push(Binding { - span: match_pair.pattern.span, - source, - var_id: var, - binding_mode: mode, - }); - } + if let Some(ascription) = ascription { + ascriptions.push(ascription); } - - PatKind::InlineConstant { subpattern: ref pattern, def } => { - // Apply a type ascription for the inline constant to the value at `match_pair.place` - if let Some(source) = match_pair.place.try_to_place(self) { - let span = match_pair.pattern.span; - let parent_id = self.tcx.typeck_root_def_id(self.def_id.to_def_id()); - let args = ty::InlineConstArgs::new( - self.tcx, - ty::InlineConstArgsParts { - parent_args: ty::GenericArgs::identity_for_item(self.tcx, parent_id), - ty: self.infcx.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::MiscVariable, - span, - }), - }, - ) - .args; - let user_ty = - self.infcx.canonicalize_user_type_annotation(ty::UserType::TypeOf( - def.to_def_id(), - ty::UserArgs { args, user_self_ty: None }, - )); - let annotation = ty::CanonicalUserTypeAnnotation { - inferred_ty: pattern.ty, - span, - user_ty: Box::new(user_ty), - }; - ascriptions.push(Ascription { - annotation, - source, - variance: ty::Contravariant, - }); - } - } - - _ => {} - } - - if let TestCase::Irrefutable = match_pair.test_case { // Simplifiable pattern; we replace it with its subpairs. match_pairs.append(&mut match_pair.subpairs); Ok(()) diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 41cfa0cfb278..1c97de58863b 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -60,7 +60,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { TestCase::Or { .. } => bug!("or-patterns should have already been handled"), - TestCase::Irrefutable => span_bug!( + TestCase::Irrefutable { .. } => span_bug!( match_pair.pattern.span, "simplifiable pattern found: {:?}", match_pair.pattern diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs index cf5a051f4434..3f7e7a348ed6 100644 --- a/compiler/rustc_mir_build/src/build/matches/util.rs +++ b/compiler/rustc_mir_build/src/build/matches/util.rs @@ -1,8 +1,9 @@ use crate::build::expr::as_place::{PlaceBase, PlaceBuilder}; use crate::build::matches::{MatchPair, TestCase}; use crate::build::Builder; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_middle::mir::*; -use rustc_middle::thir::*; +use rustc_middle::thir::{self, *}; use rustc_middle::ty; use rustc_middle::ty::TypeVisitableExt; @@ -116,14 +117,15 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { place = place.project(ProjectionElem::OpaqueCast(pattern.ty)); } + let default_irrefutable = || TestCase::Irrefutable { binding: None, ascription: None }; let mut subpairs = Vec::new(); let test_case = match pattern.kind { - PatKind::Never | PatKind::Wild | PatKind::Error(_) => TestCase::Irrefutable, + PatKind::Never | PatKind::Wild | PatKind::Error(_) => default_irrefutable(), PatKind::Or { .. } => TestCase::Or, PatKind::Range(ref range) => { if range.is_full_range(cx.tcx) == Some(true) { - TestCase::Irrefutable + default_irrefutable() } else { TestCase::Range(range) } @@ -131,33 +133,86 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { PatKind::Constant { value } => TestCase::Constant { value }, - PatKind::AscribeUserType { ref subpattern, .. } => { + PatKind::AscribeUserType { + ascription: thir::Ascription { ref annotation, variance }, + ref subpattern, + .. + } => { + // Apply the type ascription to the value at `match_pair.place` + let ascription = place.try_to_place(cx).map(|source| super::Ascription { + annotation: annotation.clone(), + source, + variance, + }); + subpairs.push(MatchPair::new(place.clone(), subpattern, cx)); - TestCase::Irrefutable + TestCase::Irrefutable { ascription, binding: None } } - PatKind::Binding { ref subpattern, .. } => { + PatKind::Binding { + name: _, + mutability: _, + mode, + var, + ty: _, + ref subpattern, + is_primary: _, + } => { + let binding = place.try_to_place(cx).map(|source| super::Binding { + span: pattern.span, + source, + var_id: var, + binding_mode: mode, + }); + if let Some(subpattern) = subpattern.as_ref() { // this is the `x @ P` case; have to keep matching against `P` now subpairs.push(MatchPair::new(place.clone(), subpattern, cx)); } - TestCase::Irrefutable + TestCase::Irrefutable { ascription: None, binding } } - PatKind::InlineConstant { subpattern: ref pattern, .. } => { + PatKind::InlineConstant { subpattern: ref pattern, def, .. } => { + // Apply a type ascription for the inline constant to the value at `match_pair.place` + let ascription = place.try_to_place(cx).map(|source| { + let span = pattern.span; + let parent_id = cx.tcx.typeck_root_def_id(cx.def_id.to_def_id()); + let args = ty::InlineConstArgs::new( + cx.tcx, + ty::InlineConstArgsParts { + parent_args: ty::GenericArgs::identity_for_item(cx.tcx, parent_id), + ty: cx.infcx.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::MiscVariable, + span, + }), + }, + ) + .args; + let user_ty = cx.infcx.canonicalize_user_type_annotation(ty::UserType::TypeOf( + def.to_def_id(), + ty::UserArgs { args, user_self_ty: None }, + )); + let annotation = ty::CanonicalUserTypeAnnotation { + inferred_ty: pattern.ty, + span, + user_ty: Box::new(user_ty), + }; + super::Ascription { annotation, source, variance: ty::Contravariant } + }); + subpairs.push(MatchPair::new(place.clone(), pattern, cx)); - TestCase::Irrefutable + TestCase::Irrefutable { ascription, binding: None } } PatKind::Array { ref prefix, ref slice, ref suffix } => { cx.prefix_slice_suffix(&mut subpairs, &place, prefix, slice, suffix); - TestCase::Irrefutable + default_irrefutable() } PatKind::Slice { ref prefix, ref slice, ref suffix } => { cx.prefix_slice_suffix(&mut subpairs, &place, prefix, slice, suffix); if prefix.is_empty() && slice.is_some() && suffix.is_empty() { - TestCase::Irrefutable + default_irrefutable() } else { TestCase::Slice { len: prefix.len() + suffix.len(), @@ -182,7 +237,7 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { }) && (adt_def.did().is_local() || !adt_def.is_variant_list_non_exhaustive()); if irrefutable { - TestCase::Irrefutable + default_irrefutable() } else { TestCase::Variant { adt_def, variant_index } } @@ -190,13 +245,13 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { PatKind::Leaf { ref subpatterns } => { subpairs = cx.field_match_pairs(place.clone(), subpatterns); - TestCase::Irrefutable + default_irrefutable() } PatKind::Deref { ref subpattern } => { let place_builder = place.clone().deref(); subpairs.push(MatchPair::new(place_builder, subpattern, cx)); - TestCase::Irrefutable + default_irrefutable() } };