Remove 'pat
lifetime from some match-lowering data structures
By storing `PatRange` in an Arc, and copying a few fields out of `Pat`, we can greatly simplify the lifetimes involved in match lowering.
This commit is contained in:
parent
ee17c3bc4d
commit
849e0364c1
8 changed files with 107 additions and 99 deletions
|
@ -11,6 +11,7 @@
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::Index;
|
use std::ops::Index;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use rustc_abi::{FieldIdx, Integer, Size, VariantIdx};
|
use rustc_abi::{FieldIdx, Integer, Size, VariantIdx};
|
||||||
use rustc_ast::{AsmMacro, InlineAsmOptions, InlineAsmTemplatePiece};
|
use rustc_ast::{AsmMacro, InlineAsmOptions, InlineAsmTemplatePiece};
|
||||||
|
@ -846,7 +847,7 @@ pub enum PatKind<'tcx> {
|
||||||
subpattern: Box<Pat<'tcx>>,
|
subpattern: Box<Pat<'tcx>>,
|
||||||
},
|
},
|
||||||
|
|
||||||
Range(Box<PatRange<'tcx>>),
|
Range(Arc<PatRange<'tcx>>),
|
||||||
|
|
||||||
/// Matches against a slice, checking the length and extracting elements.
|
/// Matches against a slice, checking the length and extracting elements.
|
||||||
/// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
|
/// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::thir::{self, *};
|
use rustc_middle::thir::{self, *};
|
||||||
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
||||||
|
@ -12,11 +14,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
/// [`PatKind::Leaf`].
|
/// [`PatKind::Leaf`].
|
||||||
///
|
///
|
||||||
/// Used internally by [`MatchPairTree::for_pattern`].
|
/// Used internally by [`MatchPairTree::for_pattern`].
|
||||||
fn field_match_pairs<'pat>(
|
fn field_match_pairs(
|
||||||
&mut self,
|
&mut self,
|
||||||
place: PlaceBuilder<'tcx>,
|
place: PlaceBuilder<'tcx>,
|
||||||
subpatterns: &'pat [FieldPat<'tcx>],
|
subpatterns: &[FieldPat<'tcx>],
|
||||||
) -> Vec<MatchPairTree<'pat, 'tcx>> {
|
) -> Vec<MatchPairTree<'tcx>> {
|
||||||
subpatterns
|
subpatterns
|
||||||
.iter()
|
.iter()
|
||||||
.map(|fieldpat| {
|
.map(|fieldpat| {
|
||||||
|
@ -31,13 +33,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
/// array pattern or slice pattern, and adds those trees to `match_pairs`.
|
/// array pattern or slice pattern, and adds those trees to `match_pairs`.
|
||||||
///
|
///
|
||||||
/// Used internally by [`MatchPairTree::for_pattern`].
|
/// Used internally by [`MatchPairTree::for_pattern`].
|
||||||
fn prefix_slice_suffix<'pat>(
|
fn prefix_slice_suffix(
|
||||||
&mut self,
|
&mut self,
|
||||||
match_pairs: &mut Vec<MatchPairTree<'pat, 'tcx>>,
|
match_pairs: &mut Vec<MatchPairTree<'tcx>>,
|
||||||
place: &PlaceBuilder<'tcx>,
|
place: &PlaceBuilder<'tcx>,
|
||||||
prefix: &'pat [Box<Pat<'tcx>>],
|
prefix: &[Box<Pat<'tcx>>],
|
||||||
opt_slice: &'pat Option<Box<Pat<'tcx>>>,
|
opt_slice: &Option<Box<Pat<'tcx>>>,
|
||||||
suffix: &'pat [Box<Pat<'tcx>>],
|
suffix: &[Box<Pat<'tcx>>],
|
||||||
) {
|
) {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let (min_length, exact_size) = if let Some(place_resolved) = place.try_to_place(self) {
|
let (min_length, exact_size) = if let Some(place_resolved) = place.try_to_place(self) {
|
||||||
|
@ -83,14 +85,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> {
|
impl<'tcx> MatchPairTree<'tcx> {
|
||||||
/// Recursively builds a match pair tree for the given pattern and its
|
/// Recursively builds a match pair tree for the given pattern and its
|
||||||
/// subpatterns.
|
/// subpatterns.
|
||||||
pub(in crate::builder) fn for_pattern(
|
pub(in crate::builder) fn for_pattern(
|
||||||
mut place_builder: PlaceBuilder<'tcx>,
|
mut place_builder: PlaceBuilder<'tcx>,
|
||||||
pattern: &'pat Pat<'tcx>,
|
pattern: &Pat<'tcx>,
|
||||||
cx: &mut Builder<'_, 'tcx>,
|
cx: &mut Builder<'_, 'tcx>,
|
||||||
) -> MatchPairTree<'pat, 'tcx> {
|
) -> MatchPairTree<'tcx> {
|
||||||
// Force the place type to the pattern's type.
|
// 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): can we use this to simplify slice/array pattern hacks?
|
||||||
if let Some(resolved) = place_builder.resolve_upvar(cx) {
|
if let Some(resolved) = place_builder.resolve_upvar(cx) {
|
||||||
|
@ -125,7 +127,7 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> {
|
||||||
if range.is_full_range(cx.tcx) == Some(true) {
|
if range.is_full_range(cx.tcx) == Some(true) {
|
||||||
default_irrefutable()
|
default_irrefutable()
|
||||||
} else {
|
} else {
|
||||||
TestCase::Range(range)
|
TestCase::Range(Arc::clone(range))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,6 +257,12 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> {
|
||||||
PatKind::Never => TestCase::Never,
|
PatKind::Never => TestCase::Never,
|
||||||
};
|
};
|
||||||
|
|
||||||
MatchPairTree { place, test_case, subpairs, pattern }
|
MatchPairTree {
|
||||||
|
place,
|
||||||
|
test_case,
|
||||||
|
subpairs,
|
||||||
|
pattern_ty: pattern.ty,
|
||||||
|
pattern_span: pattern.span,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ mod util;
|
||||||
use std::assert_matches::assert_matches;
|
use std::assert_matches::assert_matches;
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// Arguments to [`Builder::then_else_break_inner`] that are usually forwarded
|
/// Arguments to [`Builder::then_else_break_inner`] that are usually forwarded
|
||||||
/// to recursive invocations.
|
/// to recursive invocations.
|
||||||
|
@ -989,23 +990,19 @@ impl<'tcx> PatternExtraData<'tcx> {
|
||||||
///
|
///
|
||||||
/// Will typically be incorporated into a [`Candidate`].
|
/// Will typically be incorporated into a [`Candidate`].
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct FlatPat<'pat, 'tcx> {
|
struct FlatPat<'tcx> {
|
||||||
/// To match the pattern, all of these must be satisfied...
|
/// To match the pattern, all of these must be satisfied...
|
||||||
// Invariant: all the match pairs are recursively simplified.
|
// Invariant: all the match pairs are recursively simplified.
|
||||||
// Invariant: or-patterns must be sorted to the end.
|
// Invariant: or-patterns must be sorted to the end.
|
||||||
match_pairs: Vec<MatchPairTree<'pat, 'tcx>>,
|
match_pairs: Vec<MatchPairTree<'tcx>>,
|
||||||
|
|
||||||
extra_data: PatternExtraData<'tcx>,
|
extra_data: PatternExtraData<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx, 'pat> FlatPat<'pat, 'tcx> {
|
impl<'tcx> FlatPat<'tcx> {
|
||||||
/// Creates a `FlatPat` containing a simplified [`MatchPairTree`] list/forest
|
/// Creates a `FlatPat` containing a simplified [`MatchPairTree`] list/forest
|
||||||
/// for the given pattern.
|
/// for the given pattern.
|
||||||
fn new(
|
fn new(place: PlaceBuilder<'tcx>, pattern: &Pat<'tcx>, cx: &mut Builder<'_, 'tcx>) -> Self {
|
||||||
place: PlaceBuilder<'tcx>,
|
|
||||||
pattern: &'pat Pat<'tcx>,
|
|
||||||
cx: &mut Builder<'_, 'tcx>,
|
|
||||||
) -> Self {
|
|
||||||
// First, recursively build a tree of match pairs for the given pattern.
|
// First, recursively build a tree of match pairs for the given pattern.
|
||||||
let mut match_pairs = vec![MatchPairTree::for_pattern(place, pattern, cx)];
|
let mut match_pairs = vec![MatchPairTree::for_pattern(place, pattern, cx)];
|
||||||
let mut extra_data = PatternExtraData {
|
let mut extra_data = PatternExtraData {
|
||||||
|
@ -1033,7 +1030,7 @@ impl<'tcx, 'pat> FlatPat<'pat, 'tcx> {
|
||||||
/// of candidates, where each "leaf" candidate represents one of the ways for
|
/// of candidates, where each "leaf" candidate represents one of the ways for
|
||||||
/// the arm pattern to successfully match.
|
/// the arm pattern to successfully match.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Candidate<'pat, 'tcx> {
|
struct Candidate<'tcx> {
|
||||||
/// For the candidate to match, all of these must be satisfied...
|
/// For the candidate to match, all of these must be satisfied...
|
||||||
///
|
///
|
||||||
/// ---
|
/// ---
|
||||||
|
@ -1055,7 +1052,7 @@ struct Candidate<'pat, 'tcx> {
|
||||||
/// Invariants:
|
/// Invariants:
|
||||||
/// - All [`TestCase::Irrefutable`] patterns have been removed by simplification.
|
/// - All [`TestCase::Irrefutable`] patterns have been removed by simplification.
|
||||||
/// - All or-patterns ([`TestCase::Or`]) have been sorted to the end.
|
/// - All or-patterns ([`TestCase::Or`]) have been sorted to the end.
|
||||||
match_pairs: Vec<MatchPairTree<'pat, 'tcx>>,
|
match_pairs: Vec<MatchPairTree<'tcx>>,
|
||||||
|
|
||||||
/// ...and if this is non-empty, one of these subcandidates also has to match...
|
/// ...and if this is non-empty, one of these subcandidates also has to match...
|
||||||
///
|
///
|
||||||
|
@ -1072,7 +1069,7 @@ struct Candidate<'pat, 'tcx> {
|
||||||
/// Invariant: at the end of match tree lowering, this must not contain an
|
/// Invariant: at the end of match tree lowering, this must not contain an
|
||||||
/// `is_never` candidate, because that would break binding consistency.
|
/// `is_never` candidate, because that would break binding consistency.
|
||||||
/// - See [`Builder::remove_never_subcandidates`].
|
/// - See [`Builder::remove_never_subcandidates`].
|
||||||
subcandidates: Vec<Candidate<'pat, 'tcx>>,
|
subcandidates: Vec<Candidate<'tcx>>,
|
||||||
|
|
||||||
/// ...and if there is a guard it must be evaluated; if it's `false` then branch to `otherwise_block`.
|
/// ...and if there is a guard it must be evaluated; if it's `false` then branch to `otherwise_block`.
|
||||||
///
|
///
|
||||||
|
@ -1107,10 +1104,10 @@ struct Candidate<'pat, 'tcx> {
|
||||||
false_edge_start_block: Option<BasicBlock>,
|
false_edge_start_block: Option<BasicBlock>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
|
impl<'tcx> Candidate<'tcx> {
|
||||||
fn new(
|
fn new(
|
||||||
place: PlaceBuilder<'tcx>,
|
place: PlaceBuilder<'tcx>,
|
||||||
pattern: &'pat Pat<'tcx>,
|
pattern: &Pat<'tcx>,
|
||||||
has_guard: HasMatchGuard,
|
has_guard: HasMatchGuard,
|
||||||
cx: &mut Builder<'_, 'tcx>,
|
cx: &mut Builder<'_, 'tcx>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -1123,7 +1120,7 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Incorporates an already-simplified [`FlatPat`] into a new candidate.
|
/// Incorporates an already-simplified [`FlatPat`] into a new candidate.
|
||||||
fn from_flat_pat(flat_pat: FlatPat<'pat, 'tcx>, has_guard: bool) -> Self {
|
fn from_flat_pat(flat_pat: FlatPat<'tcx>, has_guard: bool) -> Self {
|
||||||
Candidate {
|
Candidate {
|
||||||
match_pairs: flat_pat.match_pairs,
|
match_pairs: flat_pat.match_pairs,
|
||||||
extra_data: flat_pat.extra_data,
|
extra_data: flat_pat.extra_data,
|
||||||
|
@ -1172,7 +1169,7 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
|
||||||
/// reference or by value, and to allow a mutable "context" to be shared by the
|
/// reference or by value, and to allow a mutable "context" to be shared by the
|
||||||
/// traversal callbacks. Most traversals can use the simpler
|
/// traversal callbacks. Most traversals can use the simpler
|
||||||
/// [`Candidate::visit_leaves`] wrapper instead.
|
/// [`Candidate::visit_leaves`] wrapper instead.
|
||||||
fn traverse_candidate<'pat, 'tcx: 'pat, C, T, I>(
|
fn traverse_candidate<'tcx, C, T, I>(
|
||||||
candidate: C,
|
candidate: C,
|
||||||
context: &mut T,
|
context: &mut T,
|
||||||
// Called when visiting a "leaf" candidate (with no subcandidates).
|
// Called when visiting a "leaf" candidate (with no subcandidates).
|
||||||
|
@ -1184,7 +1181,7 @@ fn traverse_candidate<'pat, 'tcx: 'pat, C, T, I>(
|
||||||
// Called after visiting a "node" candidate's children.
|
// Called after visiting a "node" candidate's children.
|
||||||
complete_children: impl Copy + Fn(&mut T),
|
complete_children: impl Copy + Fn(&mut T),
|
||||||
) where
|
) where
|
||||||
C: Borrow<Candidate<'pat, 'tcx>>, // Typically `Candidate` or `&mut Candidate`
|
C: Borrow<Candidate<'tcx>>, // Typically `Candidate` or `&mut Candidate`
|
||||||
I: Iterator<Item = C>,
|
I: Iterator<Item = C>,
|
||||||
{
|
{
|
||||||
if candidate.borrow().subcandidates.is_empty() {
|
if candidate.borrow().subcandidates.is_empty() {
|
||||||
|
@ -1234,20 +1231,20 @@ struct Ascription<'tcx> {
|
||||||
/// participate in or-pattern expansion, where they are transformed into subcandidates.
|
/// participate in or-pattern expansion, where they are transformed into subcandidates.
|
||||||
/// - See [`Builder::expand_and_match_or_candidates`].
|
/// - See [`Builder::expand_and_match_or_candidates`].
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
enum TestCase<'pat, 'tcx> {
|
enum TestCase<'tcx> {
|
||||||
Irrefutable { binding: Option<Binding<'tcx>>, ascription: Option<Ascription<'tcx>> },
|
Irrefutable { binding: Option<Binding<'tcx>>, ascription: Option<Ascription<'tcx>> },
|
||||||
Variant { adt_def: ty::AdtDef<'tcx>, variant_index: VariantIdx },
|
Variant { adt_def: ty::AdtDef<'tcx>, variant_index: VariantIdx },
|
||||||
Constant { value: mir::Const<'tcx> },
|
Constant { value: mir::Const<'tcx> },
|
||||||
Range(&'pat PatRange<'tcx>),
|
Range(Arc<PatRange<'tcx>>),
|
||||||
Slice { len: usize, variable_length: bool },
|
Slice { len: usize, variable_length: bool },
|
||||||
Deref { temp: Place<'tcx>, mutability: Mutability },
|
Deref { temp: Place<'tcx>, mutability: Mutability },
|
||||||
Never,
|
Never,
|
||||||
Or { pats: Box<[FlatPat<'pat, 'tcx>]> },
|
Or { pats: Box<[FlatPat<'tcx>]> },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'pat, 'tcx> TestCase<'pat, 'tcx> {
|
impl<'tcx> TestCase<'tcx> {
|
||||||
fn as_range(&self) -> Option<&'pat PatRange<'tcx>> {
|
fn as_range(&self) -> Option<&PatRange<'tcx>> {
|
||||||
if let Self::Range(v) = self { Some(*v) } else { None }
|
if let Self::Range(v) = self { Some(v.as_ref()) } else { None }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1257,7 +1254,7 @@ impl<'pat, 'tcx> TestCase<'pat, 'tcx> {
|
||||||
/// Each node also has a list of subpairs (possibly empty) that must also match,
|
/// Each node also has a list of subpairs (possibly empty) that must also match,
|
||||||
/// and a reference to the THIR pattern it represents.
|
/// and a reference to the THIR pattern it represents.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct MatchPairTree<'pat, 'tcx> {
|
pub(crate) struct MatchPairTree<'tcx> {
|
||||||
/// This place...
|
/// This place...
|
||||||
///
|
///
|
||||||
/// ---
|
/// ---
|
||||||
|
@ -1272,7 +1269,7 @@ pub(crate) struct MatchPairTree<'pat, 'tcx> {
|
||||||
/// ---
|
/// ---
|
||||||
/// Invariant: after creation and simplification in [`FlatPat::new`],
|
/// Invariant: after creation and simplification in [`FlatPat::new`],
|
||||||
/// this must not be [`TestCase::Irrefutable`].
|
/// this must not be [`TestCase::Irrefutable`].
|
||||||
test_case: TestCase<'pat, 'tcx>,
|
test_case: TestCase<'tcx>,
|
||||||
|
|
||||||
/// ... and these subpairs must match.
|
/// ... and these subpairs must match.
|
||||||
///
|
///
|
||||||
|
@ -1283,8 +1280,10 @@ pub(crate) struct MatchPairTree<'pat, 'tcx> {
|
||||||
/// that tests its field for the value `3`.
|
/// that tests its field for the value `3`.
|
||||||
subpairs: Vec<Self>,
|
subpairs: Vec<Self>,
|
||||||
|
|
||||||
/// The pattern this was created from.
|
/// Type field of the pattern this node was created from.
|
||||||
pattern: &'pat Pat<'tcx>,
|
pattern_ty: Ty<'tcx>,
|
||||||
|
/// Span field of the pattern this node was created from.
|
||||||
|
pattern_span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See [`Test`] for more.
|
/// See [`Test`] for more.
|
||||||
|
@ -1320,7 +1319,7 @@ enum TestKind<'tcx> {
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Test whether the value falls within an inclusive or exclusive range.
|
/// Test whether the value falls within an inclusive or exclusive range.
|
||||||
Range(Box<PatRange<'tcx>>),
|
Range(Arc<PatRange<'tcx>>),
|
||||||
|
|
||||||
/// Test that the length of the slice is `== len` or `>= len`.
|
/// Test that the length of the slice is `== len` or `>= len`.
|
||||||
Len { len: u64, op: BinOp },
|
Len { len: u64, op: BinOp },
|
||||||
|
@ -1423,7 +1422,7 @@ struct BuiltMatchTree<'tcx> {
|
||||||
|
|
||||||
impl<'tcx> MatchTreeSubBranch<'tcx> {
|
impl<'tcx> MatchTreeSubBranch<'tcx> {
|
||||||
fn from_sub_candidate(
|
fn from_sub_candidate(
|
||||||
candidate: Candidate<'_, 'tcx>,
|
candidate: Candidate<'tcx>,
|
||||||
parent_data: &Vec<PatternExtraData<'tcx>>,
|
parent_data: &Vec<PatternExtraData<'tcx>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
debug_assert!(candidate.match_pairs.is_empty());
|
debug_assert!(candidate.match_pairs.is_empty());
|
||||||
|
@ -1449,12 +1448,12 @@ impl<'tcx> MatchTreeSubBranch<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> MatchTreeBranch<'tcx> {
|
impl<'tcx> MatchTreeBranch<'tcx> {
|
||||||
fn from_candidate(candidate: Candidate<'_, 'tcx>) -> Self {
|
fn from_candidate(candidate: Candidate<'tcx>) -> Self {
|
||||||
let mut sub_branches = Vec::new();
|
let mut sub_branches = Vec::new();
|
||||||
traverse_candidate(
|
traverse_candidate(
|
||||||
candidate,
|
candidate,
|
||||||
&mut Vec::new(),
|
&mut Vec::new(),
|
||||||
&mut |candidate: Candidate<'_, '_>, parent_data: &mut Vec<PatternExtraData<'_>>| {
|
&mut |candidate: Candidate<'_>, parent_data: &mut Vec<PatternExtraData<'_>>| {
|
||||||
sub_branches.push(MatchTreeSubBranch::from_sub_candidate(candidate, parent_data));
|
sub_branches.push(MatchTreeSubBranch::from_sub_candidate(candidate, parent_data));
|
||||||
},
|
},
|
||||||
|inner_candidate, parent_data| {
|
|inner_candidate, parent_data| {
|
||||||
|
@ -1485,23 +1484,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
/// `refutable` indicates whether the candidate list is refutable (for `if let` and `let else`)
|
/// `refutable` indicates whether the candidate list is refutable (for `if let` and `let else`)
|
||||||
/// or not (for `let` and `match`). In the refutable case we return the block to which we branch
|
/// or not (for `let` and `match`). In the refutable case we return the block to which we branch
|
||||||
/// on failure.
|
/// on failure.
|
||||||
fn lower_match_tree<'pat>(
|
fn lower_match_tree(
|
||||||
&mut self,
|
&mut self,
|
||||||
block: BasicBlock,
|
block: BasicBlock,
|
||||||
scrutinee_span: Span,
|
scrutinee_span: Span,
|
||||||
scrutinee_place_builder: &PlaceBuilder<'tcx>,
|
scrutinee_place_builder: &PlaceBuilder<'tcx>,
|
||||||
match_start_span: Span,
|
match_start_span: Span,
|
||||||
patterns: Vec<(&'pat Pat<'tcx>, HasMatchGuard)>,
|
patterns: Vec<(&Pat<'tcx>, HasMatchGuard)>,
|
||||||
refutable: bool,
|
refutable: bool,
|
||||||
) -> BuiltMatchTree<'tcx>
|
) -> BuiltMatchTree<'tcx> {
|
||||||
where
|
|
||||||
'tcx: 'pat,
|
|
||||||
{
|
|
||||||
// Assemble the initial list of candidates. These top-level candidates are 1:1 with the
|
// Assemble the initial list of candidates. These top-level candidates are 1:1 with the
|
||||||
// input patterns, but other parts of match lowering also introduce subcandidates (for
|
// input patterns, but other parts of match lowering also introduce subcandidates (for
|
||||||
// sub-or-patterns). So inside the algorithm, the candidates list may not correspond to
|
// sub-or-patterns). So inside the algorithm, the candidates list may not correspond to
|
||||||
// match arms directly.
|
// match arms directly.
|
||||||
let mut candidates: Vec<Candidate<'_, '_>> = patterns
|
let mut candidates: Vec<Candidate<'_>> = patterns
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(pat, has_guard)| {
|
.map(|(pat, has_guard)| {
|
||||||
Candidate::new(scrutinee_place_builder.clone(), pat, has_guard, self)
|
Candidate::new(scrutinee_place_builder.clone(), pat, has_guard, self)
|
||||||
|
@ -1664,7 +1660,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
span: Span,
|
span: Span,
|
||||||
scrutinee_span: Span,
|
scrutinee_span: Span,
|
||||||
start_block: BasicBlock,
|
start_block: BasicBlock,
|
||||||
candidates: &mut [&mut Candidate<'_, 'tcx>],
|
candidates: &mut [&mut Candidate<'tcx>],
|
||||||
) -> BasicBlock {
|
) -> BasicBlock {
|
||||||
ensure_sufficient_stack(|| {
|
ensure_sufficient_stack(|| {
|
||||||
self.match_candidates_inner(span, scrutinee_span, start_block, candidates)
|
self.match_candidates_inner(span, scrutinee_span, start_block, candidates)
|
||||||
|
@ -1678,7 +1674,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
span: Span,
|
span: Span,
|
||||||
scrutinee_span: Span,
|
scrutinee_span: Span,
|
||||||
mut start_block: BasicBlock,
|
mut start_block: BasicBlock,
|
||||||
candidates: &mut [&mut Candidate<'_, 'tcx>],
|
candidates: &mut [&mut Candidate<'tcx>],
|
||||||
) -> BasicBlock {
|
) -> BasicBlock {
|
||||||
if let [first, ..] = candidates {
|
if let [first, ..] = candidates {
|
||||||
if first.false_edge_start_block.is_none() {
|
if first.false_edge_start_block.is_none() {
|
||||||
|
@ -1747,7 +1743,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
/// [otherwise block]: Candidate::otherwise_block
|
/// [otherwise block]: Candidate::otherwise_block
|
||||||
fn select_matched_candidate(
|
fn select_matched_candidate(
|
||||||
&mut self,
|
&mut self,
|
||||||
candidate: &mut Candidate<'_, 'tcx>,
|
candidate: &mut Candidate<'tcx>,
|
||||||
start_block: BasicBlock,
|
start_block: BasicBlock,
|
||||||
) -> BasicBlock {
|
) -> BasicBlock {
|
||||||
assert!(candidate.otherwise_block.is_none());
|
assert!(candidate.otherwise_block.is_none());
|
||||||
|
@ -1765,13 +1761,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
/// Takes a list of candidates such that some of the candidates' first match pairs are
|
/// Takes a list of candidates such that some of the candidates' first match pairs are
|
||||||
/// or-patterns. This expands as many or-patterns as possible and processes the resulting
|
/// or-patterns. This expands as many or-patterns as possible and processes the resulting
|
||||||
/// candidates. Returns the unprocessed candidates if any.
|
/// candidates. Returns the unprocessed candidates if any.
|
||||||
fn expand_and_match_or_candidates<'pat, 'b, 'c>(
|
fn expand_and_match_or_candidates<'b, 'c>(
|
||||||
&mut self,
|
&mut self,
|
||||||
span: Span,
|
span: Span,
|
||||||
scrutinee_span: Span,
|
scrutinee_span: Span,
|
||||||
start_block: BasicBlock,
|
start_block: BasicBlock,
|
||||||
candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>],
|
candidates: &'b mut [&'c mut Candidate<'tcx>],
|
||||||
) -> BlockAnd<&'b mut [&'c mut Candidate<'pat, 'tcx>]> {
|
) -> BlockAnd<&'b mut [&'c mut Candidate<'tcx>]> {
|
||||||
// We can't expand or-patterns freely. The rule is:
|
// We can't expand or-patterns freely. The rule is:
|
||||||
// - If a candidate doesn't start with an or-pattern, we include it in
|
// - If a candidate doesn't start with an or-pattern, we include it in
|
||||||
// the expansion list as-is (i.e. it "expands" to itself).
|
// the expansion list as-is (i.e. it "expands" to itself).
|
||||||
|
@ -1865,14 +1861,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
/// Given a match-pair that corresponds to an or-pattern, expand each subpattern into a new
|
/// Given a match-pair that corresponds to an or-pattern, expand each subpattern into a new
|
||||||
/// subcandidate. Any candidate that has been expanded this way should also be postprocessed
|
/// subcandidate. Any candidate that has been expanded this way should also be postprocessed
|
||||||
/// at the end of [`Self::expand_and_match_or_candidates`].
|
/// at the end of [`Self::expand_and_match_or_candidates`].
|
||||||
fn create_or_subcandidates<'pat>(
|
fn create_or_subcandidates(
|
||||||
&mut self,
|
&mut self,
|
||||||
candidate: &mut Candidate<'pat, 'tcx>,
|
candidate: &mut Candidate<'tcx>,
|
||||||
match_pair: MatchPairTree<'pat, 'tcx>,
|
match_pair: MatchPairTree<'tcx>,
|
||||||
) {
|
) {
|
||||||
let TestCase::Or { pats } = match_pair.test_case else { bug!() };
|
let TestCase::Or { pats } = match_pair.test_case else { bug!() };
|
||||||
debug!("expanding or-pattern: candidate={:#?}\npats={:#?}", candidate, pats);
|
debug!("expanding or-pattern: candidate={:#?}\npats={:#?}", candidate, pats);
|
||||||
candidate.or_span = Some(match_pair.pattern.span);
|
candidate.or_span = Some(match_pair.pattern_span);
|
||||||
candidate.subcandidates = pats
|
candidate.subcandidates = pats
|
||||||
.into_vec()
|
.into_vec()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -1938,7 +1934,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
///
|
///
|
||||||
/// Note that this takes place _after_ the subcandidates have participated
|
/// Note that this takes place _after_ the subcandidates have participated
|
||||||
/// in match tree lowering.
|
/// in match tree lowering.
|
||||||
fn merge_trivial_subcandidates(&mut self, candidate: &mut Candidate<'_, 'tcx>) {
|
fn merge_trivial_subcandidates(&mut self, candidate: &mut Candidate<'tcx>) {
|
||||||
assert!(!candidate.subcandidates.is_empty());
|
assert!(!candidate.subcandidates.is_empty());
|
||||||
if candidate.has_guard {
|
if candidate.has_guard {
|
||||||
// FIXME(or_patterns; matthewjasper) Don't give up if we have a guard.
|
// FIXME(or_patterns; matthewjasper) Don't give up if we have a guard.
|
||||||
|
@ -1981,7 +1977,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
/// Never subcandidates may have a set of bindings inconsistent with their siblings,
|
/// Never subcandidates may have a set of bindings inconsistent with their siblings,
|
||||||
/// which would break later code. So we filter them out. Note that we can't filter out
|
/// which would break later code. So we filter them out. Note that we can't filter out
|
||||||
/// top-level candidates this way.
|
/// top-level candidates this way.
|
||||||
fn remove_never_subcandidates(&mut self, candidate: &mut Candidate<'_, 'tcx>) {
|
fn remove_never_subcandidates(&mut self, candidate: &mut Candidate<'tcx>) {
|
||||||
if candidate.subcandidates.is_empty() {
|
if candidate.subcandidates.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2020,7 +2016,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
&mut self,
|
&mut self,
|
||||||
span: Span,
|
span: Span,
|
||||||
scrutinee_span: Span,
|
scrutinee_span: Span,
|
||||||
candidate: &mut Candidate<'_, 'tcx>,
|
candidate: &mut Candidate<'tcx>,
|
||||||
) {
|
) {
|
||||||
if candidate.match_pairs.is_empty() {
|
if candidate.match_pairs.is_empty() {
|
||||||
return;
|
return;
|
||||||
|
@ -2086,7 +2082,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
/// [`Switch`]: TestKind::Switch
|
/// [`Switch`]: TestKind::Switch
|
||||||
/// [`SwitchInt`]: TestKind::SwitchInt
|
/// [`SwitchInt`]: TestKind::SwitchInt
|
||||||
/// [`Range`]: TestKind::Range
|
/// [`Range`]: TestKind::Range
|
||||||
fn pick_test(&mut self, candidates: &[&mut Candidate<'_, 'tcx>]) -> (Place<'tcx>, Test<'tcx>) {
|
fn pick_test(&mut self, candidates: &[&mut Candidate<'tcx>]) -> (Place<'tcx>, Test<'tcx>) {
|
||||||
// Extract the match-pair from the highest priority candidate
|
// Extract the match-pair from the highest priority candidate
|
||||||
let match_pair = &candidates[0].match_pairs[0];
|
let match_pair = &candidates[0].match_pairs[0];
|
||||||
let test = self.pick_test_for_match_pair(match_pair);
|
let test = self.pick_test_for_match_pair(match_pair);
|
||||||
|
@ -2137,18 +2133,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
/// The sorted candidates are mutated to remove entailed match pairs:
|
/// The sorted candidates are mutated to remove entailed match pairs:
|
||||||
/// - candidate 0 becomes `[z @ true]` since we know that `x` was `true`;
|
/// - candidate 0 becomes `[z @ true]` since we know that `x` was `true`;
|
||||||
/// - candidate 1 becomes `[y @ false]` since we know that `x` was `false`.
|
/// - candidate 1 becomes `[y @ false]` since we know that `x` was `false`.
|
||||||
fn sort_candidates<'b, 'c, 'pat>(
|
fn sort_candidates<'b, 'c>(
|
||||||
&mut self,
|
&mut self,
|
||||||
match_place: Place<'tcx>,
|
match_place: Place<'tcx>,
|
||||||
test: &Test<'tcx>,
|
test: &Test<'tcx>,
|
||||||
mut candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>],
|
mut candidates: &'b mut [&'c mut Candidate<'tcx>],
|
||||||
) -> (
|
) -> (
|
||||||
&'b mut [&'c mut Candidate<'pat, 'tcx>],
|
&'b mut [&'c mut Candidate<'tcx>],
|
||||||
FxIndexMap<TestBranch<'tcx>, Vec<&'b mut Candidate<'pat, 'tcx>>>,
|
FxIndexMap<TestBranch<'tcx>, Vec<&'b mut Candidate<'tcx>>>,
|
||||||
) {
|
) {
|
||||||
// For each of the possible outcomes, collect vector of candidates that apply if the test
|
// For each of the possible outcomes, collect vector of candidates that apply if the test
|
||||||
// has that particular outcome.
|
// has that particular outcome.
|
||||||
let mut target_candidates: FxIndexMap<_, Vec<&mut Candidate<'_, '_>>> = Default::default();
|
let mut target_candidates: FxIndexMap<_, Vec<&mut Candidate<'_>>> = Default::default();
|
||||||
|
|
||||||
let total_candidate_count = candidates.len();
|
let total_candidate_count = candidates.len();
|
||||||
|
|
||||||
|
@ -2274,13 +2270,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// We return the unprocessed candidates.
|
/// We return the unprocessed candidates.
|
||||||
fn test_candidates<'pat, 'b, 'c>(
|
fn test_candidates<'b, 'c>(
|
||||||
&mut self,
|
&mut self,
|
||||||
span: Span,
|
span: Span,
|
||||||
scrutinee_span: Span,
|
scrutinee_span: Span,
|
||||||
candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>],
|
candidates: &'b mut [&'c mut Candidate<'tcx>],
|
||||||
start_block: BasicBlock,
|
start_block: BasicBlock,
|
||||||
) -> BlockAnd<&'b mut [&'c mut Candidate<'pat, 'tcx>]> {
|
) -> BlockAnd<&'b mut [&'c mut Candidate<'tcx>]> {
|
||||||
// Choose a match pair from the first candidate, and use it to determine a
|
// Choose a match pair from the first candidate, and use it to determine a
|
||||||
// test to perform that will confirm or refute that match pair.
|
// test to perform that will confirm or refute that match pair.
|
||||||
let (match_place, test) = self.pick_test(candidates);
|
let (match_place, test) = self.pick_test(candidates);
|
||||||
|
|
|
@ -23,9 +23,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
/// Simplify a list of match pairs so they all require a test. Stores relevant bindings and
|
/// Simplify a list of match pairs so they all require a test. Stores relevant bindings and
|
||||||
/// ascriptions in `extra_data`.
|
/// ascriptions in `extra_data`.
|
||||||
#[instrument(skip(self), level = "debug")]
|
#[instrument(skip(self), level = "debug")]
|
||||||
pub(super) fn simplify_match_pairs<'pat>(
|
pub(super) fn simplify_match_pairs(
|
||||||
&mut self,
|
&mut self,
|
||||||
match_pairs: &mut Vec<MatchPairTree<'pat, 'tcx>>,
|
match_pairs: &mut Vec<MatchPairTree<'tcx>>,
|
||||||
extra_data: &mut PatternExtraData<'tcx>,
|
extra_data: &mut PatternExtraData<'tcx>,
|
||||||
) {
|
) {
|
||||||
// In order to please the borrow checker, in a pattern like `x @ pat` we must lower the
|
// In order to please the borrow checker, in a pattern like `x @ pat` we must lower the
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
// the candidates based on the result.
|
// the candidates based on the result.
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxIndexMap;
|
use rustc_data_structures::fx::FxIndexMap;
|
||||||
use rustc_hir::{LangItem, RangeEnd};
|
use rustc_hir::{LangItem, RangeEnd};
|
||||||
|
@ -26,20 +27,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
/// Identifies what test is needed to decide if `match_pair` is applicable.
|
/// Identifies what test is needed to decide if `match_pair` is applicable.
|
||||||
///
|
///
|
||||||
/// It is a bug to call this with a not-fully-simplified pattern.
|
/// It is a bug to call this with a not-fully-simplified pattern.
|
||||||
pub(super) fn pick_test_for_match_pair<'pat>(
|
pub(super) fn pick_test_for_match_pair(
|
||||||
&mut self,
|
&mut self,
|
||||||
match_pair: &MatchPairTree<'pat, 'tcx>,
|
match_pair: &MatchPairTree<'tcx>,
|
||||||
) -> Test<'tcx> {
|
) -> Test<'tcx> {
|
||||||
let kind = match match_pair.test_case {
|
let kind = match match_pair.test_case {
|
||||||
TestCase::Variant { adt_def, variant_index: _ } => TestKind::Switch { adt_def },
|
TestCase::Variant { adt_def, variant_index: _ } => TestKind::Switch { adt_def },
|
||||||
|
|
||||||
TestCase::Constant { .. } if match_pair.pattern.ty.is_bool() => TestKind::If,
|
TestCase::Constant { .. } if match_pair.pattern_ty.is_bool() => TestKind::If,
|
||||||
TestCase::Constant { .. } if is_switch_ty(match_pair.pattern.ty) => TestKind::SwitchInt,
|
TestCase::Constant { .. } if is_switch_ty(match_pair.pattern_ty) => TestKind::SwitchInt,
|
||||||
TestCase::Constant { value } => TestKind::Eq { value, ty: match_pair.pattern.ty },
|
TestCase::Constant { value } => TestKind::Eq { value, ty: match_pair.pattern_ty },
|
||||||
|
|
||||||
TestCase::Range(range) => {
|
TestCase::Range(ref range) => {
|
||||||
assert_eq!(range.ty, match_pair.pattern.ty);
|
assert_eq!(range.ty, match_pair.pattern_ty);
|
||||||
TestKind::Range(Box::new(range.clone()))
|
TestKind::Range(Arc::clone(range))
|
||||||
}
|
}
|
||||||
|
|
||||||
TestCase::Slice { len, variable_length } => {
|
TestCase::Slice { len, variable_length } => {
|
||||||
|
@ -56,13 +57,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
TestCase::Or { .. } => bug!("or-patterns should have already been handled"),
|
TestCase::Or { .. } => bug!("or-patterns should have already been handled"),
|
||||||
|
|
||||||
TestCase::Irrefutable { .. } => span_bug!(
|
TestCase::Irrefutable { .. } => span_bug!(
|
||||||
match_pair.pattern.span,
|
match_pair.pattern_span,
|
||||||
"simplifiable pattern found: {:?}",
|
"simplifiable pattern found: {:?}",
|
||||||
match_pair.pattern
|
match_pair.pattern_span
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
Test { span: match_pair.pattern.span, kind }
|
Test { span: match_pair.pattern_span, kind }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(self, target_blocks, place), level = "debug")]
|
#[instrument(skip(self, target_blocks, place), level = "debug")]
|
||||||
|
@ -521,8 +522,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
&mut self,
|
&mut self,
|
||||||
test_place: Place<'tcx>,
|
test_place: Place<'tcx>,
|
||||||
test: &Test<'tcx>,
|
test: &Test<'tcx>,
|
||||||
candidate: &mut Candidate<'_, 'tcx>,
|
candidate: &mut Candidate<'tcx>,
|
||||||
sorted_candidates: &FxIndexMap<TestBranch<'tcx>, Vec<&mut Candidate<'_, 'tcx>>>,
|
sorted_candidates: &FxIndexMap<TestBranch<'tcx>, Vec<&mut Candidate<'tcx>>>,
|
||||||
) -> Option<TestBranch<'tcx>> {
|
) -> Option<TestBranch<'tcx>> {
|
||||||
// Find the match_pair for this place (if any). At present,
|
// Find the match_pair for this place (if any). At present,
|
||||||
// afaik, there can be at most one. (In the future, if we
|
// afaik, there can be at most one. (In the future, if we
|
||||||
|
@ -558,14 +559,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
// FIXME(#29623) we could use PatKind::Range to rule
|
// FIXME(#29623) we could use PatKind::Range to rule
|
||||||
// things out here, in some cases.
|
// things out here, in some cases.
|
||||||
(TestKind::SwitchInt, &TestCase::Constant { value })
|
(TestKind::SwitchInt, &TestCase::Constant { value })
|
||||||
if is_switch_ty(match_pair.pattern.ty) =>
|
if is_switch_ty(match_pair.pattern_ty) =>
|
||||||
{
|
{
|
||||||
// An important invariant of candidate sorting is that a candidate
|
// An important invariant of candidate sorting is that a candidate
|
||||||
// must not match in multiple branches. For `SwitchInt` tests, adding
|
// must not match in multiple branches. For `SwitchInt` tests, adding
|
||||||
// a new value might invalidate that property for range patterns that
|
// a new value might invalidate that property for range patterns that
|
||||||
// have already been sorted into the failure arm, so we must take care
|
// have already been sorted into the failure arm, so we must take care
|
||||||
// not to add such values here.
|
// not to add such values here.
|
||||||
let is_covering_range = |test_case: &TestCase<'_, 'tcx>| {
|
let is_covering_range = |test_case: &TestCase<'tcx>| {
|
||||||
test_case.as_range().is_some_and(|range| {
|
test_case.as_range().is_some_and(|range| {
|
||||||
matches!(
|
matches!(
|
||||||
range.contains(value, self.tcx, self.typing_env()),
|
range.contains(value, self.tcx, self.typing_env()),
|
||||||
|
@ -573,7 +574,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
let is_conflicting_candidate = |candidate: &&mut Candidate<'_, 'tcx>| {
|
let is_conflicting_candidate = |candidate: &&mut Candidate<'tcx>| {
|
||||||
candidate
|
candidate
|
||||||
.match_pairs
|
.match_pairs
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -685,8 +686,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(TestKind::Range(test), &TestCase::Range(pat)) => {
|
(TestKind::Range(test), TestCase::Range(pat)) => {
|
||||||
if test.as_ref() == pat {
|
if test == pat {
|
||||||
fully_matched = true;
|
fully_matched = true;
|
||||||
Some(TestBranch::Success)
|
Some(TestBranch::Success)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -67,7 +67,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
/// a MIR pass run after borrow checking.
|
/// a MIR pass run after borrow checking.
|
||||||
pub(super) fn collect_fake_borrows<'tcx>(
|
pub(super) fn collect_fake_borrows<'tcx>(
|
||||||
cx: &mut Builder<'_, 'tcx>,
|
cx: &mut Builder<'_, 'tcx>,
|
||||||
candidates: &[Candidate<'_, 'tcx>],
|
candidates: &[Candidate<'tcx>],
|
||||||
temp_span: Span,
|
temp_span: Span,
|
||||||
scrutinee_base: PlaceBase,
|
scrutinee_base: PlaceBase,
|
||||||
) -> Vec<(Place<'tcx>, Local, FakeBorrowKind)> {
|
) -> Vec<(Place<'tcx>, Local, FakeBorrowKind)> {
|
||||||
|
@ -135,7 +135,7 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_candidate(&mut self, candidate: &Candidate<'_, 'tcx>) {
|
fn visit_candidate(&mut self, candidate: &Candidate<'tcx>) {
|
||||||
for binding in &candidate.extra_data.bindings {
|
for binding in &candidate.extra_data.bindings {
|
||||||
self.visit_binding(binding);
|
self.visit_binding(binding);
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,7 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_flat_pat(&mut self, flat_pat: &FlatPat<'_, 'tcx>) {
|
fn visit_flat_pat(&mut self, flat_pat: &FlatPat<'tcx>) {
|
||||||
for binding in &flat_pat.extra_data.bindings {
|
for binding in &flat_pat.extra_data.bindings {
|
||||||
self.visit_binding(binding);
|
self.visit_binding(binding);
|
||||||
}
|
}
|
||||||
|
@ -153,7 +153,7 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_match_pair(&mut self, match_pair: &MatchPairTree<'_, 'tcx>) {
|
fn visit_match_pair(&mut self, match_pair: &MatchPairTree<'tcx>) {
|
||||||
if let TestCase::Or { pats, .. } = &match_pair.test_case {
|
if let TestCase::Or { pats, .. } = &match_pair.test_case {
|
||||||
for flat_pat in pats.iter() {
|
for flat_pat in pats.iter() {
|
||||||
self.visit_flat_pat(flat_pat)
|
self.visit_flat_pat(flat_pat)
|
||||||
|
|
|
@ -4,6 +4,7 @@ mod check_match;
|
||||||
mod const_to_pat;
|
mod const_to_pat;
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use rustc_abi::{FieldIdx, Integer};
|
use rustc_abi::{FieldIdx, Integer};
|
||||||
use rustc_errors::MultiSpan;
|
use rustc_errors::MultiSpan;
|
||||||
|
@ -260,7 +261,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||||
let hi = hi.unwrap_or(PatRangeBoundary::PosInfinity);
|
let hi = hi.unwrap_or(PatRangeBoundary::PosInfinity);
|
||||||
|
|
||||||
let cmp = lo.compare_with(hi, ty, self.tcx, self.typing_env);
|
let cmp = lo.compare_with(hi, ty, self.tcx, self.typing_env);
|
||||||
let mut kind = PatKind::Range(Box::new(PatRange { lo, hi, end, ty }));
|
let mut kind = PatKind::Range(Arc::new(PatRange { lo, hi, end, ty }));
|
||||||
match (end, cmp) {
|
match (end, cmp) {
|
||||||
// `x..y` where `x < y`.
|
// `x..y` where `x < y`.
|
||||||
(RangeEnd::Excluded, Some(Ordering::Less)) => {}
|
(RangeEnd::Excluded, Some(Ordering::Less)) => {}
|
||||||
|
|
|
@ -373,7 +373,8 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> {
|
||||||
|
|
||||||
match pat.kind {
|
match pat.kind {
|
||||||
thir::PatKind::Constant { value } => value.has_non_region_param(),
|
thir::PatKind::Constant { value } => value.has_non_region_param(),
|
||||||
thir::PatKind::Range(box thir::PatRange { lo, hi, .. }) => {
|
thir::PatKind::Range(ref range) => {
|
||||||
|
let &thir::PatRange { lo, hi, .. } = range.as_ref();
|
||||||
lo.has_non_region_param() || hi.has_non_region_param()
|
lo.has_non_region_param() || hi.has_non_region_param()
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue