diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index a497501ef19d..798b98c5def5 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -291,7 +291,7 @@ pub fn type_flags(self) -> TypeFlags { } ty::ReError(_) => { flags = flags | TypeFlags::HAS_FREE_REGIONS; - flags = flags | TypeFlags::HAS_ERROR; + flags = flags | TypeFlags::HAS_RE_ERROR; } } diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index 6962a7ab1d72..f31129811964 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -91,19 +91,24 @@ pub struct TypeFlags: u32 { | TypeFlags::HAS_TY_INHERENT.bits() | TypeFlags::HAS_CT_PROJECTION.bits(); + /// Is a type or const error reachable? + const HAS_NON_REGION_ERROR = 1 << 15; + /// Is a region error reachable? + const HAS_RE_ERROR = 1 << 16; /// Is an error type/lifetime/const reachable? - const HAS_ERROR = 1 << 15; + const HAS_ERROR = TypeFlags::HAS_NON_REGION_ERROR.bits() + | TypeFlags::HAS_RE_ERROR.bits(); /// Does this have any region that "appears free" in the type? /// Basically anything but `ReBound` and `ReErased`. - const HAS_FREE_REGIONS = 1 << 16; + const HAS_FREE_REGIONS = 1 << 17; /// Does this have any `ReBound` regions? - const HAS_RE_BOUND = 1 << 17; + const HAS_RE_BOUND = 1 << 18; /// Does this have any `Bound` types? - const HAS_TY_BOUND = 1 << 18; + const HAS_TY_BOUND = 1 << 19; /// Does this have any `ConstKind::Bound` consts? - const HAS_CT_BOUND = 1 << 19; + const HAS_CT_BOUND = 1 << 20; /// Does this have any bound variables? /// Used to check if a global bound is safe to evaluate. const HAS_BOUND_VARS = TypeFlags::HAS_RE_BOUND.bits() @@ -111,7 +116,7 @@ pub struct TypeFlags: u32 { | TypeFlags::HAS_CT_BOUND.bits(); /// Does this have any `ReErased` regions? - const HAS_RE_ERASED = 1 << 20; + const HAS_RE_ERASED = 1 << 21; /// Does this value have parameters/placeholders/inference variables which could be /// replaced later, in a way that would change the results of `impl` specialization? @@ -123,19 +128,19 @@ pub struct TypeFlags: u32 { | TypeFlags::HAS_CT_INFER.bits(); /// Does this value have `InferTy::FreshTy/FreshIntTy/FreshFloatTy`? - const HAS_TY_FRESH = 1 << 21; + const HAS_TY_FRESH = 1 << 22; /// Does this value have `InferConst::Fresh`? - const HAS_CT_FRESH = 1 << 22; + const HAS_CT_FRESH = 1 << 23; /// Does this have any binders with bound vars (e.g. that need to be anonymized)? - const HAS_BINDER_VARS = 1 << 23; + const HAS_BINDER_VARS = 1 << 24; /// Does this type have any coroutines in it? - const HAS_TY_CORO = 1 << 24; + const HAS_TY_CORO = 1 << 25; /// Does this have have a `Bound(BoundVarIndexKind::Canonical, _)`? - const HAS_CANONICAL_BOUND = 1 << 25; + const HAS_CANONICAL_BOUND = 1 << 26; } } @@ -240,7 +245,7 @@ fn add_kind(&mut self, kind: &ty::TyKind) { | ty::Str | ty::Foreign(..) => {} - ty::Error(_) => self.add_flags(TypeFlags::HAS_ERROR), + ty::Error(_) => self.add_flags(TypeFlags::HAS_NON_REGION_ERROR), ty::Param(_) => { self.add_flags(TypeFlags::HAS_TY_PARAM); @@ -489,7 +494,7 @@ fn add_const_kind(&mut self, c: &ty::ConstKind) { } } ty::ConstKind::Expr(e) => self.add_args(e.args().as_slice()), - ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_ERROR), + ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_NON_REGION_ERROR), } } diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 1ee4bff6b7a1..cfb458896536 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -279,6 +279,8 @@ fn references_error(&self) -> bool { fn error_reported(&self) -> Result<(), I::ErrorGuaranteed>; + fn non_region_error_reported(&self) -> Result<(), I::ErrorGuaranteed>; + fn has_non_region_param(&self) -> bool { self.has_type_flags(TypeFlags::HAS_PARAM - TypeFlags::HAS_RE_PARAM) } @@ -352,6 +354,11 @@ fn has_bound_vars(&self) -> bool { fn still_further_specializable(&self) -> bool { self.has_type_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE) } + + /// True if a type or const error is reachable + fn has_non_region_error(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_NON_REGION_ERROR) + } } impl> TypeVisitableExt for T { @@ -376,6 +383,18 @@ fn error_reported(&self) -> Result<(), I::ErrorGuaranteed> { Ok(()) } } + + fn non_region_error_reported(&self) -> Result<(), I::ErrorGuaranteed> { + if self.has_non_region_error() { + if let ControlFlow::Break(guar) = self.visit_with(&mut HasErrorVisitor) { + Err(guar) + } else { + panic!("type flags said there was an non region error, but now there is not") + } + } else { + Ok(()) + } + } } #[derive(Debug, PartialEq, Eq, Copy, Clone)]