Skip to content

Commit be29cd1

Browse files
committed
Use a unique id instead of by-address indexing
1 parent 8465c82 commit be29cd1

File tree

2 files changed

+25
-36
lines changed

2 files changed

+25
-36
lines changed

compiler/rustc_pattern_analysis/src/pat.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,17 @@ use crate::TypeCx;
99

1010
use self::Constructor::*;
1111

12+
/// A globally unique id to distinguish patterns.
13+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
14+
pub(crate) struct PatId(u32);
15+
impl PatId {
16+
fn new() -> Self {
17+
use std::sync::atomic::{AtomicU32, Ordering};
18+
static PAT_ID: AtomicU32 = AtomicU32::new(0);
19+
PatId(PAT_ID.fetch_add(1, Ordering::SeqCst))
20+
}
21+
}
22+
1223
/// Values and patterns can be represented as a constructor applied to some fields. This represents
1324
/// a pattern in this form. A `DeconstructedPat` will almost always come from user input; the only
1425
/// exception are some `Wildcard`s introduced during pattern lowering.
@@ -24,11 +35,13 @@ pub struct DeconstructedPat<Cx: TypeCx> {
2435
/// Extra data to store in a pattern. `None` if the pattern is a wildcard that does not
2536
/// correspond to a user-supplied pattern.
2637
data: Option<Cx::PatData>,
38+
/// Globally-unique id used to track usefulness at the level of subpatterns.
39+
pub(crate) uid: PatId,
2740
}
2841

2942
impl<Cx: TypeCx> DeconstructedPat<Cx> {
3043
pub fn wildcard(ty: Cx::Ty) -> Self {
31-
DeconstructedPat { ctor: Wildcard, fields: Vec::new(), ty, data: None }
44+
DeconstructedPat { ctor: Wildcard, fields: Vec::new(), ty, data: None, uid: PatId::new() }
3245
}
3346

3447
pub fn new(
@@ -37,7 +50,7 @@ impl<Cx: TypeCx> DeconstructedPat<Cx> {
3750
ty: Cx::Ty,
3851
data: Cx::PatData,
3952
) -> Self {
40-
DeconstructedPat { ctor, fields, ty, data: Some(data) }
53+
DeconstructedPat { ctor, fields, ty, data: Some(data), uid: PatId::new() }
4154
}
4255

4356
pub(crate) fn is_or_pat(&self) -> bool {

compiler/rustc_pattern_analysis/src/usefulness.rs

+10-34
Original file line numberDiff line numberDiff line change
@@ -713,10 +713,9 @@ use rustc_hash::FxHashSet;
713713
use rustc_index::bit_set::BitSet;
714714
use smallvec::{smallvec, SmallVec};
715715
use std::fmt;
716-
use std::ops::Deref;
717716

718717
use crate::constructor::{Constructor, ConstructorSet, IntRange};
719-
use crate::pat::{DeconstructedPat, PatOrWild, WitnessPat};
718+
use crate::pat::{DeconstructedPat, PatId, PatOrWild, WitnessPat};
720719
use crate::{Captures, MatchArm, TypeCx};
721720

722721
use self::ValidityConstraint::*;
@@ -728,36 +727,13 @@ pub fn ensure_sufficient_stack<R>(f: impl FnOnce() -> R) -> R {
728727
f()
729728
}
730729

731-
/// Wrapper type for by-address hashing. Comparison and hashing of the wrapped pointer type will be
732-
/// based on the address of its contents, rather than their value.
733-
struct ByAddress<T>(T);
734-
735-
impl<T: Deref> ByAddress<T> {
736-
fn addr(&self) -> *const T::Target {
737-
(&*self.0) as *const _
738-
}
739-
}
740-
/// Raw pointer hashing and comparison.
741-
impl<T: Deref> std::hash::Hash for ByAddress<T> {
742-
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
743-
self.addr().hash(state)
744-
}
745-
}
746-
impl<T: Deref> PartialEq for ByAddress<T> {
747-
fn eq(&self, other: &Self) -> bool {
748-
std::ptr::eq(self.addr(), other.addr())
749-
}
750-
}
751-
impl<T: Deref> Eq for ByAddress<T> {}
752-
753730
/// Context that provides information for usefulness checking.
754-
struct UsefulnessCtxt<'a, 'p, Cx: TypeCx> {
731+
struct UsefulnessCtxt<'a, Cx: TypeCx> {
755732
/// The context for type information.
756733
tycx: &'a Cx,
757734
/// Collect the patterns found useful during usefulness checking. This is used to lint
758-
/// unreachable (sub)patterns. We distinguish patterns by their address to avoid needing to
759-
/// inspect the contents. They'll all be distinct anyway since they carry a `Span`.
760-
useful_subpatterns: FxHashSet<ByAddress<&'p DeconstructedPat<Cx>>>,
735+
/// unreachable (sub)patterns.
736+
useful_subpatterns: FxHashSet<PatId>,
761737
}
762738

763739
/// Context that provides information local to a place under investigation.
@@ -1398,7 +1374,7 @@ impl<Cx: TypeCx> WitnessMatrix<Cx> {
13981374
/// We can however get false negatives because exhaustiveness does not explore all cases. See the
13991375
/// section on relevancy at the top of the file.
14001376
fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>(
1401-
mcx: &mut UsefulnessCtxt<'_, 'p, Cx>,
1377+
mcx: &mut UsefulnessCtxt<'_, Cx>,
14021378
overlap_range: IntRange,
14031379
matrix: &Matrix<'p, Cx>,
14041380
specialized_matrix: &Matrix<'p, Cx>,
@@ -1471,7 +1447,7 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>(
14711447
/// This is all explained at the top of the file.
14721448
#[instrument(level = "debug", skip(mcx), ret)]
14731449
fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
1474-
mcx: &mut UsefulnessCtxt<'a, 'p, Cx>,
1450+
mcx: &mut UsefulnessCtxt<'a, Cx>,
14751451
matrix: &mut Matrix<'p, Cx>,
14761452
) -> Result<WitnessMatrix<Cx>, Cx::Error> {
14771453
debug_assert!(matrix.rows().all(|r| r.len() == matrix.column_count()));
@@ -1598,7 +1574,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
15981574
for row in matrix.rows() {
15991575
if row.useful {
16001576
if let PatOrWild::Pat(pat) = row.head() {
1601-
mcx.useful_subpatterns.insert(ByAddress(pat));
1577+
mcx.useful_subpatterns.insert(pat.uid);
16021578
}
16031579
}
16041580
}
@@ -1620,14 +1596,14 @@ pub enum Usefulness<'p, Cx: TypeCx> {
16201596

16211597
/// Report whether this pattern was found useful, and its subpatterns that were not useful if any.
16221598
fn collect_pattern_usefulness<'p, Cx: TypeCx>(
1623-
useful_subpatterns: &FxHashSet<ByAddress<&'p DeconstructedPat<Cx>>>,
1599+
useful_subpatterns: &FxHashSet<PatId>,
16241600
pat: &'p DeconstructedPat<Cx>,
16251601
) -> Usefulness<'p, Cx> {
16261602
fn pat_is_useful<'p, Cx: TypeCx>(
1627-
useful_subpatterns: &FxHashSet<ByAddress<&'p DeconstructedPat<Cx>>>,
1603+
useful_subpatterns: &FxHashSet<PatId>,
16281604
pat: &'p DeconstructedPat<Cx>,
16291605
) -> bool {
1630-
if useful_subpatterns.contains(&ByAddress(pat)) {
1606+
if useful_subpatterns.contains(&pat.uid) {
16311607
true
16321608
} else if pat.is_or_pat() && pat.iter_fields().any(|f| pat_is_useful(useful_subpatterns, f))
16331609
{

0 commit comments

Comments
 (0)