Auto merge of #116821 - Nadrieril:fix-opaque-ice, r=compiler-errors
Exhaustiveness: reveal opaque types properly Previously, exhaustiveness had no clear policy around opaque types. In this PR I propose the following policy: within the body of an item that defines the hidden type of some opaque type, exhaustiveness checking on a value of that opaque type is performed using the concrete hidden type inferred in this body. I'm not sure how consistent this is with other operations allowed on opaque types; I believe this will require FCP. From what I can tell, this doesn't change anything for non-empty types. The observable changes are: - when the real type is uninhabited, matches within the defining scopes can now rely on that for exhaustiveness, e.g.: ```rust #[derive(Copy, Clone)] enum Void {} fn return_never_rpit(x: Void) -> impl Copy { if false { match return_never_rpit(x) {} } x } ``` - this properly fixes ICEs like https://github.com/rust-lang/rust/issues/117100 that occurred because a same match could have some patterns where the type is revealed and some where it is not. Bonus subtle point: if `x` is opaque, a match like `match x { ("", "") => {} ... }` will constrain its type ([playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=901d715330eac40339b4016ac566d6c3)). This is not the case for `match x {}`: this will not constain the type, and will only compile if something else constrains the type to be empty. Fixes https://github.com/rust-lang/rust/issues/117100 r? `@oli-obk` Edited for precision of the wording [Included](https://github.com/rust-lang/rust/pull/116821#issuecomment-1813171764) in the FCP on this PR is this rule: > Within the body of an item that defines the hidden type of some opaque type, exhaustiveness checking on a value of that opaque type is performed using the concrete hidden type inferred in this body.
This commit is contained in:
commit
c1fc1d18cd
7 changed files with 284 additions and 33 deletions
|
@ -28,6 +28,7 @@ use rustc_span::hygiene::DesugaringKind;
|
|||
use rustc_span::Span;
|
||||
|
||||
pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
|
||||
let typeck_results = tcx.typeck(def_id);
|
||||
let (thir, expr) = tcx.thir_body(def_id)?;
|
||||
let thir = thir.borrow();
|
||||
let pattern_arena = TypedArena::default();
|
||||
|
@ -35,6 +36,7 @@ pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), Err
|
|||
let mut visitor = MatchVisitor {
|
||||
tcx,
|
||||
thir: &*thir,
|
||||
typeck_results,
|
||||
param_env: tcx.param_env(def_id),
|
||||
lint_level: tcx.local_def_id_to_hir_id(def_id),
|
||||
let_source: LetSource::None,
|
||||
|
@ -80,6 +82,7 @@ enum LetSource {
|
|||
struct MatchVisitor<'thir, 'p, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
typeck_results: &'tcx ty::TypeckResults<'tcx>,
|
||||
thir: &'thir Thir<'tcx>,
|
||||
lint_level: HirId,
|
||||
let_source: LetSource,
|
||||
|
@ -382,6 +385,7 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
|
|||
scrutinee.map(|scrut| self.is_known_valid_scrutinee(scrut)).unwrap_or(true);
|
||||
MatchCheckCtxt {
|
||||
tcx: self.tcx,
|
||||
typeck_results: self.typeck_results,
|
||||
param_env: self.param_env,
|
||||
module: self.tcx.parent_module(self.lint_level).to_def_id(),
|
||||
pattern_arena: self.pattern_arena,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue