Skip to content

Commit 5bcd86d

Browse files
committed
Auto merge of #119329 - Nadrieril:reveal-opaques-early, r=compiler-errors
Exhaustiveness: Statically enforce revealing of opaques In #116821 it was decided that exhaustiveness should operate on the hidden type of an opaque type when relevant. This PR makes sure we consistently reveal opaques within exhaustiveness. This makes it possible to remove `reveal_opaque_ty` from the `TypeCx` trait which was an unfortunate implementation detail. r? `@compiler-errors`
2 parents 595bc6f + c352720 commit 5bcd86d

File tree

5 files changed

+132
-94
lines changed

5 files changed

+132
-94
lines changed

compiler/rustc_mir_build/src/thir/pattern/check_match.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
544544
let cx = self.new_cx(refutability, None, scrut, pat.span);
545545
let pat = self.lower_pattern(&cx, pat)?;
546546
let arms = [MatchArm { pat, arm_data: self.lint_level, has_guard: false }];
547-
let report = analyze_match(&cx, &arms, pat.ty());
547+
let report = analyze_match(&cx, &arms, pat.ty().inner());
548548
Ok((cx, report))
549549
}
550550

@@ -962,7 +962,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(
962962
}
963963
} else if ty == cx.tcx.types.str_ {
964964
err.note("`&str` cannot be matched exhaustively, so a wildcard `_` is necessary");
965-
} else if cx.is_foreign_non_exhaustive_enum(ty) {
965+
} else if cx.is_foreign_non_exhaustive_enum(cx.reveal_opaque_ty(ty)) {
966966
err.note(format!("`{ty}` is marked as non-exhaustive, so a wildcard `_` is necessary to match exhaustively"));
967967
}
968968
}
@@ -1102,12 +1102,12 @@ fn collect_non_exhaustive_tys<'tcx>(
11021102
non_exhaustive_tys: &mut FxIndexSet<Ty<'tcx>>,
11031103
) {
11041104
if matches!(pat.ctor(), Constructor::NonExhaustive) {
1105-
non_exhaustive_tys.insert(pat.ty());
1105+
non_exhaustive_tys.insert(pat.ty().inner());
11061106
}
11071107
if let Constructor::IntRange(range) = pat.ctor() {
11081108
if cx.is_range_beyond_boundaries(range, pat.ty()) {
11091109
// The range denotes the values before `isize::MIN` or the values after `usize::MAX`/`isize::MAX`.
1110-
non_exhaustive_tys.insert(pat.ty());
1110+
non_exhaustive_tys.insert(pat.ty().inner());
11111111
}
11121112
}
11131113
pat.iter_fields()

compiler/rustc_pattern_analysis/src/lib.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,6 @@ pub trait TypeCx: Sized + fmt::Debug {
6161
/// Extra data to store in a pattern.
6262
type PatData: Clone;
6363

64-
/// FIXME(Nadrieril): `Cx` should only give us revealed types.
65-
fn reveal_opaque_ty(&self, ty: Self::Ty) -> Self::Ty;
6664
fn is_exhaustive_patterns_feature_on(&self) -> bool;
6765

6866
/// The number of fields for this constructor.
@@ -114,6 +112,7 @@ pub fn analyze_match<'p, 'tcx>(
114112
) -> rustc::UsefulnessReport<'p, 'tcx> {
115113
// Arena to store the extra wildcards we construct during analysis.
116114
let wildcard_arena = tycx.pattern_arena;
115+
let scrut_ty = tycx.reveal_opaque_ty(scrut_ty);
117116
let scrut_validity = ValidityConstraint::from_bool(tycx.known_valid_scrutinee);
118117
let cx = MatchCtxt { tycx, wildcard_arena };
119118

compiler/rustc_pattern_analysis/src/lints.rs

+8-15
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use smallvec::SmallVec;
22

33
use rustc_data_structures::captures::Captures;
4-
use rustc_middle::ty::{self, Ty};
4+
use rustc_middle::ty;
55
use rustc_session::lint;
66
use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
77
use rustc_span::Span;
@@ -12,10 +12,9 @@ use crate::errors::{
1212
OverlappingRangeEndpoints, Uncovered,
1313
};
1414
use crate::rustc::{
15-
Constructor, DeconstructedPat, MatchArm, MatchCtxt, PlaceCtxt, RustcMatchCheckCtxt,
15+
Constructor, DeconstructedPat, MatchArm, MatchCtxt, PlaceCtxt, RevealedTy, RustcMatchCheckCtxt,
1616
SplitConstructorSet, WitnessPat,
1717
};
18-
use crate::TypeCx;
1918

2019
/// A column of patterns in the matrix, where a column is the intuitive notion of "subpatterns that
2120
/// inspect the same subvalue/place".
@@ -48,14 +47,8 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> {
4847
fn is_empty(&self) -> bool {
4948
self.patterns.is_empty()
5049
}
51-
fn head_ty(&self, cx: MatchCtxt<'_, 'p, 'tcx>) -> Option<Ty<'tcx>> {
52-
if self.patterns.len() == 0 {
53-
return None;
54-
}
55-
56-
let ty = self.patterns[0].ty();
57-
// FIXME(Nadrieril): `Cx` should only give us revealed types.
58-
Some(cx.tycx.reveal_opaque_ty(ty))
50+
fn head_ty(&self) -> Option<RevealedTy<'tcx>> {
51+
self.patterns.first().map(|pat| pat.ty())
5952
}
6053

6154
/// Do constructor splitting on the constructors of the column.
@@ -117,7 +110,7 @@ fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
117110
cx: MatchCtxt<'a, 'p, 'tcx>,
118111
column: &PatternColumn<'p, 'tcx>,
119112
) -> Vec<WitnessPat<'p, 'tcx>> {
120-
let Some(ty) = column.head_ty(cx) else {
113+
let Some(ty) = column.head_ty() else {
121114
return Vec::new();
122115
};
123116
let pcx = &PlaceCtxt::new_dummy(cx, ty);
@@ -164,7 +157,7 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
164157
cx: MatchCtxt<'a, 'p, 'tcx>,
165158
arms: &[MatchArm<'p, 'tcx>],
166159
pat_column: &PatternColumn<'p, 'tcx>,
167-
scrut_ty: Ty<'tcx>,
160+
scrut_ty: RevealedTy<'tcx>,
168161
) {
169162
let rcx: &RustcMatchCheckCtxt<'_, '_> = cx.tycx;
170163
if !matches!(
@@ -182,7 +175,7 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
182175
rcx.match_lint_level,
183176
rcx.scrut_span,
184177
NonExhaustiveOmittedPattern {
185-
scrut_ty,
178+
scrut_ty: scrut_ty.inner(),
186179
uncovered: Uncovered::new(rcx.scrut_span, rcx, witnesses),
187180
},
188181
);
@@ -218,7 +211,7 @@ pub(crate) fn lint_overlapping_range_endpoints<'a, 'p, 'tcx>(
218211
cx: MatchCtxt<'a, 'p, 'tcx>,
219212
column: &PatternColumn<'p, 'tcx>,
220213
) {
221-
let Some(ty) = column.head_ty(cx) else {
214+
let Some(ty) = column.head_ty() else {
222215
return;
223216
};
224217
let pcx = &PlaceCtxt::new_dummy(cx, ty);

0 commit comments

Comments
 (0)