diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index 32af537e271..b3d6b891b11 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -864,6 +864,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { }; // Use the underlying local for this (necessarily interior) borrow. + debug_assert!(region.is_erased()); let ty = local_decls[place.local].ty; let span = statement.source_info.span; @@ -873,8 +874,6 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { ty::TypeAndMut { ty, mutbl: borrow_kind.to_mutbl_lossy() }, ); - *region = tcx.lifetimes.re_erased; - let mut projection = vec![PlaceElem::Deref]; projection.extend(place.projection); place.projection = tcx.mk_place_elems(&projection); diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index d5fb4340e1c..55c01d2084b 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -5,7 +5,7 @@ use rustc_hir::{ForeignItem, ForeignItemKind}; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{ObligationCause, WellFormedLoc}; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, Region, TyCtxt, TypeFoldable, TypeFolder}; +use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::LocalDefId; use rustc_trait_selection::traits::{self, ObligationCtxt}; @@ -68,7 +68,13 @@ fn diagnostic_hir_wf_check<'tcx>( let infcx = self.tcx.infer_ctxt().build(); let ocx = ObligationCtxt::new(&infcx); - let tcx_ty = self.icx.to_ty(ty).fold_with(&mut EraseAllBoundRegions { tcx: self.tcx }); + let tcx_ty = self.icx.to_ty(ty); + // This visitor can walk into binders, resulting in the `tcx_ty` to + // potentially reference escaping bound variables. We simply erase + // those here. + let tcx_ty = self.tcx.fold_regions(tcx_ty, |r, _| { + if r.is_bound() { self.tcx.lifetimes.re_erased } else { r } + }); let cause = traits::ObligationCause::new( ty.span, self.def_id, @@ -178,25 +184,3 @@ fn diagnostic_hir_wf_check<'tcx>( } visitor.cause } - -struct EraseAllBoundRegions<'tcx> { - tcx: TyCtxt<'tcx>, -} - -// Higher ranked regions are complicated. -// To make matters worse, the HIR WF check can instantiate them -// outside of a `Binder`, due to the way we (ab)use -// `ItemCtxt::to_ty`. To make things simpler, we just erase all -// of them, regardless of depth. At worse, this will give -// us an inaccurate span for an error message, but cannot -// lead to unsoundness (we call `delay_span_bug` at the start -// of `diagnostic_hir_wf_check`). -impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EraseAllBoundRegions<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { - self.tcx - } - fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> { - // FIXME(@lcnr): only erase escaping bound regions! - if r.is_bound() { self.tcx.lifetimes.re_erased } else { r } - } -} diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 2dfe7272673..2462ac93632 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -9,7 +9,7 @@ use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion}; -use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; +use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::symbol::sym; @@ -768,41 +768,22 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { } } -struct EraseEarlyRegions<'tcx> { - tcx: TyCtxt<'tcx>, -} - -impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EraseEarlyRegions<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { - self.tcx - } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if ty.has_type_flags(ty::TypeFlags::HAS_FREE_REGIONS) { - ty.super_fold_with(self) - } else { - ty - } - } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - if r.is_bound() { r } else { self.tcx.lifetimes.re_erased } - } -} - impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> { fn interner(&self) -> TyCtxt<'tcx> { self.fcx.tcx } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + let tcx = self.fcx.tcx; match self.fcx.fully_resolve(t) { Ok(t) if self.fcx.next_trait_solver() => { // We must normalize erasing regions here, since later lints // expect that types that show up in the typeck are fully // normalized. - if let Ok(t) = self.fcx.tcx.try_normalize_erasing_regions(self.fcx.param_env, t) { + if let Ok(t) = tcx.try_normalize_erasing_regions(self.fcx.param_env, t) { t } else { - EraseEarlyRegions { tcx: self.fcx.tcx }.fold_ty(t) + tcx.fold_regions(t, |_, _| tcx.lifetimes.re_erased) } } Ok(t) => { @@ -810,7 +791,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> { // (e.g. keep `for<'a>` named `for<'a>`). // This allows NLL to generate error messages that // refer to the higher-ranked lifetime names written by the user. - EraseEarlyRegions { tcx: self.fcx.tcx }.fold_ty(t) + tcx.fold_regions(t, |_, _| tcx.lifetimes.re_erased) } Err(_) => { debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t); diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs index 294bd9d1d54..3ee4710bdef 100644 --- a/compiler/rustc_infer/src/errors/note_and_explain.rs +++ b/compiler/rustc_infer/src/errors/note_and_explain.rs @@ -75,7 +75,7 @@ impl<'a> DescriptionCtx<'a> { // We shouldn't really be having unification failures with ReVar // and ReBound though. // - // FIXME(@lcnr): figure out why we `ReBound` have to handle `ReBound` + // FIXME(@lcnr): figure out why we have to handle `ReBound` // here, this feels somewhat off. ty::ReVar(_) | ty::ReBound(..) | ty::ReErased => { (alt_span, "revar", format!("{region:?}"))