Skip to content

Commit

Permalink
Auto merge of rust-lang#119329 - Nadrieril:reveal-opaques-early, r=co…
Browse files Browse the repository at this point in the history
…mpiler-errors

Exhaustiveness: Statically enforce revealing of opaques

In rust-lang#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`
  • Loading branch information
bors committed Jan 5, 2024
2 parents 595bc6f + c352720 commit 132c5bb
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
Expand Up @@ -544,7 +544,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 @@ -962,7 +962,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 @@ -1102,12 +1102,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
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
@@ -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

0 comments on commit 132c5bb

Please sign in to comment.