Rollup merge of #127808 - oli-obk:tainting_visitors2, r=lcnr,nnethercote
Make ErrorGuaranteed discoverable outside types, consts, and lifetimes types like `PatKind` could contain `ErrorGuaranteed`, but not return them via `tainted_by_errors` or `error_reported` (see https://github.com/rust-lang/rust/pull/127687#discussion_r1679027883). Now this happens, but it's a bit fragile as you can see with the `TypeSuperVisitable for Ty` impl. We will catch any problems around Ty, Region or Const at runtime with an assert, and everything using derives will not have such issues, as it will just invoke the `TypeVisitable for ErrorGuaranteed` impl
This commit is contained in:
commit
8fd1df8c5f
@ -257,7 +257,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|||||||
crate::ty::adjustment::PointerCoercion,
|
crate::ty::adjustment::PointerCoercion,
|
||||||
::rustc_span::Span,
|
::rustc_span::Span,
|
||||||
::rustc_span::symbol::Ident,
|
::rustc_span::symbol::Ident,
|
||||||
::rustc_errors::ErrorGuaranteed,
|
|
||||||
ty::BoundVar,
|
ty::BoundVar,
|
||||||
ty::ValTree<'tcx>,
|
ty::ValTree<'tcx>,
|
||||||
}
|
}
|
||||||
@ -443,13 +442,14 @@ fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::
|
|||||||
pat.visit_with(visitor)
|
pat.visit_with(visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ty::Error(guar) => guar.visit_with(visitor),
|
||||||
|
|
||||||
ty::Bool
|
ty::Bool
|
||||||
| ty::Char
|
| ty::Char
|
||||||
| ty::Str
|
| ty::Str
|
||||||
| ty::Int(_)
|
| ty::Int(_)
|
||||||
| ty::Uint(_)
|
| ty::Uint(_)
|
||||||
| ty::Float(_)
|
| ty::Float(_)
|
||||||
| ty::Error(_)
|
|
||||||
| ty::Infer(_)
|
| ty::Infer(_)
|
||||||
| ty::Bound(..)
|
| ty::Bound(..)
|
||||||
| ty::Placeholder(..)
|
| ty::Placeholder(..)
|
||||||
@ -602,6 +602,21 @@ fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for rustc_span::ErrorGuaranteed {
|
||||||
|
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
|
||||||
|
visitor.visit_error(*self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for rustc_span::ErrorGuaranteed {
|
||||||
|
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||||
|
self,
|
||||||
|
_folder: &mut F,
|
||||||
|
) -> Result<Self, F::Error> {
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for InferConst {
|
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for InferConst {
|
||||||
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||||
self,
|
self,
|
||||||
@ -617,12 +632,6 @@ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, _visitor: &mut V) -> V::Resul
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::UnevaluatedConst<'tcx> {
|
|
||||||
fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
|
|
||||||
self.args.visit_with(visitor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for TyAndLayout<'tcx, Ty<'tcx>> {
|
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for TyAndLayout<'tcx, Ty<'tcx>> {
|
||||||
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
|
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
|
||||||
visitor.visit_ty(self.ty)
|
visitor.visit_ty(self.ty)
|
||||||
|
@ -101,8 +101,12 @@ fn visit_ty(&mut self, t: I::Ty) -> Self::Result {
|
|||||||
|
|
||||||
// The default region visitor is a no-op because `Region` is non-recursive
|
// The default region visitor is a no-op because `Region` is non-recursive
|
||||||
// and has no `super_visit_with` method to call.
|
// and has no `super_visit_with` method to call.
|
||||||
fn visit_region(&mut self, _r: I::Region) -> Self::Result {
|
fn visit_region(&mut self, r: I::Region) -> Self::Result {
|
||||||
Self::Result::output()
|
if let ty::ReError(guar) = r.kind() {
|
||||||
|
self.visit_error(guar)
|
||||||
|
} else {
|
||||||
|
Self::Result::output()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_const(&mut self, c: I::Const) -> Self::Result {
|
fn visit_const(&mut self, c: I::Const) -> Self::Result {
|
||||||
@ -116,6 +120,10 @@ fn visit_predicate(&mut self, p: I::Predicate) -> Self::Result {
|
|||||||
fn visit_clauses(&mut self, p: I::Clauses) -> Self::Result {
|
fn visit_clauses(&mut self, p: I::Clauses) -> Self::Result {
|
||||||
p.super_visit_with(self)
|
p.super_visit_with(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_error(&mut self, _guar: I::ErrorGuaranteed) -> Self::Result {
|
||||||
|
Self::Result::output()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
@ -439,6 +447,15 @@ fn visit_clauses(&mut self, clauses: I::Clauses) -> Self::Result {
|
|||||||
ControlFlow::Continue(())
|
ControlFlow::Continue(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_error(&mut self, _guar: <I as Interner>::ErrorGuaranteed) -> Self::Result {
|
||||||
|
if self.flags.intersects(TypeFlags::HAS_ERROR) {
|
||||||
|
ControlFlow::Break(FoundFlags)
|
||||||
|
} else {
|
||||||
|
ControlFlow::Continue(())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
@ -547,27 +564,7 @@ fn visit_clauses(&mut self, clauses: I::Clauses) -> Self::Result {
|
|||||||
impl<I: Interner> TypeVisitor<I> for HasErrorVisitor {
|
impl<I: Interner> TypeVisitor<I> for HasErrorVisitor {
|
||||||
type Result = ControlFlow<I::ErrorGuaranteed>;
|
type Result = ControlFlow<I::ErrorGuaranteed>;
|
||||||
|
|
||||||
fn visit_ty(&mut self, t: <I as Interner>::Ty) -> Self::Result {
|
fn visit_error(&mut self, guar: <I as Interner>::ErrorGuaranteed) -> Self::Result {
|
||||||
if let ty::Error(guar) = t.kind() {
|
ControlFlow::Break(guar)
|
||||||
ControlFlow::Break(guar)
|
|
||||||
} else {
|
|
||||||
t.super_visit_with(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_const(&mut self, c: <I as Interner>::Const) -> Self::Result {
|
|
||||||
if let ty::ConstKind::Error(guar) = c.kind() {
|
|
||||||
ControlFlow::Break(guar)
|
|
||||||
} else {
|
|
||||||
c.super_visit_with(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_region(&mut self, r: <I as Interner>::Region) -> Self::Result {
|
|
||||||
if let ty::ReError(guar) = r.kind() {
|
|
||||||
ControlFlow::Break(guar)
|
|
||||||
} else {
|
|
||||||
ControlFlow::Continue(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user