Skip to content

Commit

Permalink
Statically enforce revealing of opaques
Browse files Browse the repository at this point in the history
  • Loading branch information
Nadrieril committed Jan 1, 2024
1 parent e51e98d commit c352720
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 94 deletions.
8 changes: 4 additions & 4 deletions compiler/rustc_mir_build/src/thir/pattern/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
let cx = self.new_cx(refutability, None, scrut, pat.span);
let pat = self.lower_pattern(&cx, pat)?;
let arms = [MatchArm { pat, arm_data: self.lint_level, has_guard: false }];
let report = analyze_match(&cx, &arms, pat.ty());
let report = analyze_match(&cx, &arms, pat.ty().inner());
Ok((cx, report))
}

Expand Down Expand Up @@ -972,7 +972,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(
}
} else if ty == cx.tcx.types.str_ {
err.note("`&str` cannot be matched exhaustively, so a wildcard `_` is necessary");
} else if cx.is_foreign_non_exhaustive_enum(ty) {
} else if cx.is_foreign_non_exhaustive_enum(cx.reveal_opaque_ty(ty)) {
err.note(format!("`{ty}` is marked as non-exhaustive, so a wildcard `_` is necessary to match exhaustively"));
}
}
Expand Down Expand Up @@ -1112,12 +1112,12 @@ fn collect_non_exhaustive_tys<'tcx>(
non_exhaustive_tys: &mut FxIndexSet<Ty<'tcx>>,
) {
if matches!(pat.ctor(), Constructor::NonExhaustive) {
non_exhaustive_tys.insert(pat.ty());
non_exhaustive_tys.insert(pat.ty().inner());
}
if let Constructor::IntRange(range) = pat.ctor() {
if cx.is_range_beyond_boundaries(range, pat.ty()) {
// The range denotes the values before `isize::MIN` or the values after `usize::MAX`/`isize::MAX`.
non_exhaustive_tys.insert(pat.ty());
non_exhaustive_tys.insert(pat.ty().inner());
}
}
pat.iter_fields()
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_pattern_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ pub trait TypeCx: Sized + fmt::Debug {
/// Extra data to store in a pattern.
type PatData: Clone;

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

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

Expand Down
23 changes: 8 additions & 15 deletions compiler/rustc_pattern_analysis/src/lints.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use smallvec::SmallVec;

use rustc_data_structures::captures::Captures;
use rustc_middle::ty::{self, Ty};
use rustc_middle::ty;
use rustc_session::lint;
use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
use rustc_span::Span;
Expand All @@ -12,10 +12,9 @@ use crate::errors::{
OverlappingRangeEndpoints, Uncovered,
};
use crate::rustc::{
Constructor, DeconstructedPat, MatchArm, MatchCtxt, PlaceCtxt, RustcMatchCheckCtxt,
Constructor, DeconstructedPat, MatchArm, MatchCtxt, PlaceCtxt, RevealedTy, RustcMatchCheckCtxt,
SplitConstructorSet, WitnessPat,
};
use crate::TypeCx;

/// A column of patterns in the matrix, where a column is the intuitive notion of "subpatterns that
/// inspect the same subvalue/place".
Expand Down Expand Up @@ -48,14 +47,8 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> {
fn is_empty(&self) -> bool {
self.patterns.is_empty()
}
fn head_ty(&self, cx: MatchCtxt<'_, 'p, 'tcx>) -> Option<Ty<'tcx>> {
if self.patterns.len() == 0 {
return None;
}

let ty = self.patterns[0].ty();
// FIXME(Nadrieril): `Cx` should only give us revealed types.
Some(cx.tycx.reveal_opaque_ty(ty))
fn head_ty(&self) -> Option<RevealedTy<'tcx>> {
self.patterns.first().map(|pat| pat.ty())
}

/// Do constructor splitting on the constructors of the column.
Expand Down Expand Up @@ -117,7 +110,7 @@ fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
cx: MatchCtxt<'a, 'p, 'tcx>,
column: &PatternColumn<'p, 'tcx>,
) -> Vec<WitnessPat<'p, 'tcx>> {
let Some(ty) = column.head_ty(cx) else {
let Some(ty) = column.head_ty() else {
return Vec::new();
};
let pcx = &PlaceCtxt::new_dummy(cx, ty);
Expand Down Expand Up @@ -164,7 +157,7 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
cx: MatchCtxt<'a, 'p, 'tcx>,
arms: &[MatchArm<'p, 'tcx>],
pat_column: &PatternColumn<'p, 'tcx>,
scrut_ty: Ty<'tcx>,
scrut_ty: RevealedTy<'tcx>,
) {
let rcx: &RustcMatchCheckCtxt<'_, '_> = cx.tycx;
if !matches!(
Expand All @@ -182,7 +175,7 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
rcx.match_lint_level,
rcx.scrut_span,
NonExhaustiveOmittedPattern {
scrut_ty,
scrut_ty: scrut_ty.inner(),
uncovered: Uncovered::new(rcx.scrut_span, rcx, witnesses),
},
);
Expand Down Expand Up @@ -218,7 +211,7 @@ pub(crate) fn lint_overlapping_range_endpoints<'a, 'p, 'tcx>(
cx: MatchCtxt<'a, 'p, 'tcx>,
column: &PatternColumn<'p, 'tcx>,
) {
let Some(ty) = column.head_ty(cx) else {
let Some(ty) = column.head_ty() else {
return;
};
let pcx = &PlaceCtxt::new_dummy(cx, ty);
Expand Down
Loading

0 comments on commit c352720

Please sign in to comment.