Fix stack overflow in exhaustiveness due to recursive HIR opaque type values
This commit is contained in:
parent
e643f59f6d
commit
b08e9c2a60
4 changed files with 224 additions and 5 deletions
|
@ -1,5 +1,6 @@
|
|||
use std::fmt;
|
||||
use std::iter::once;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use rustc_abi::{FIRST_VARIANT, FieldIdx, Integer, VariantIdx};
|
||||
use rustc_arena::DroplessArena;
|
||||
|
@ -11,7 +12,8 @@ use rustc_middle::mir::{self, Const};
|
|||
use rustc_middle::thir::{self, Pat, PatKind, PatRange, PatRangeBoundary};
|
||||
use rustc_middle::ty::layout::IntegerExt;
|
||||
use rustc_middle::ty::{
|
||||
self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeVisitableExt, VariantDef,
|
||||
self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
|
||||
TypeVisitableExt, TypeVisitor, VariantDef,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::lint;
|
||||
|
@ -135,11 +137,22 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
|
|||
/// Returns the hidden type corresponding to this key if the body under analysis is allowed to
|
||||
/// know it.
|
||||
fn reveal_opaque_key(&self, key: OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>> {
|
||||
self.typeck_results
|
||||
.concrete_opaque_types
|
||||
.get(&key.def_id)
|
||||
.map(|x| ty::EarlyBinder::bind(x.ty).instantiate(self.tcx, key.args))
|
||||
if let Some(hidden_ty) = self.typeck_results.concrete_opaque_types.get(&key.def_id) {
|
||||
let ty = ty::EarlyBinder::bind(hidden_ty.ty).instantiate(self.tcx, key.args);
|
||||
if ty.visit_with(&mut RecursiveOpaque { def_id: key.def_id.into() }).is_continue() {
|
||||
Some(ty)
|
||||
} else {
|
||||
// HACK: We skip revealing opaque types which recursively expand
|
||||
// to themselves. This is because we may infer hidden types like
|
||||
// `Opaque<T> = Opaque<Opaque<T>>` or `Opaque<T> = Opaque<(T,)>`
|
||||
// in hir typeck.
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
// This can take a non-revealed `Ty` because it reveals opaques itself.
|
||||
pub fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
|
||||
!ty.inhabited_predicate(self.tcx).apply_revealing_opaque(
|
||||
|
@ -1105,3 +1118,20 @@ pub fn analyze_match<'p, 'tcx>(
|
|||
|
||||
Ok(report)
|
||||
}
|
||||
|
||||
struct RecursiveOpaque {
|
||||
def_id: DefId,
|
||||
}
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for RecursiveOpaque {
|
||||
type Result = ControlFlow<()>;
|
||||
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
|
||||
if let ty::Alias(ty::Opaque, alias_ty) = t.kind() {
|
||||
if alias_ty.def_id == self.def_id {
|
||||
return ControlFlow::Break(());
|
||||
}
|
||||
}
|
||||
|
||||
if t.has_opaque_types() { t.super_visit_with(self) } else { ControlFlow::Continue(()) }
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue