diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 1c1906f3375..15882a471a4 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -69,6 +69,7 @@ use crate::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeFoldable}; +use crate::infer::outlives::env::OutlivesEnvironment; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::undo_log::UndoLogs; use rustc_hir as hir; @@ -177,6 +178,18 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { } } } + + pub fn check_region_obligations_and_report_errors( + &self, + outlives_env: &OutlivesEnvironment<'tcx>, + ) { + self.process_registered_region_obligations( + outlives_env.region_bound_pairs_map(), + outlives_env.param_env, + ); + + self.resolve_regions_and_report_errors(outlives_env) + } } /// The `TypeOutlives` struct has the job of "lowering" a `T: 'a` diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 6222dbb4074..fab4bb0d934 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -13,6 +13,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::{ItemKind, Node, PathSegment}; +use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_infer::traits::Obligation; @@ -736,10 +737,9 @@ fn check_opaque_meets_bounds<'tcx>( hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {} // Can have different predicates to their defining use hir::OpaqueTyOrigin::TyAlias => { - // Finally, resolve all regions. This catches wily misuses of - // lifetime parameters. - let fcx = FnCtxt::new(&inh, param_env, hir_id); - fcx.regionck_item(hir_id, span, FxHashSet::default()); + let mut outlives_environment = OutlivesEnvironment::new(param_env); + outlives_environment.save_implied_bounds(hir_id); + infcx.check_region_obligations_and_report_errors(&outlives_environment); } } diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 65c7c1aee1a..e233c026a39 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1,3 +1,4 @@ +use crate::check::regionck::OutlivesEnvironmentExt; use crate::errors::LifetimesOrBoundsMismatchOnTrait; use rustc_data_structures::stable_set::FxHashSet; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed}; @@ -5,6 +6,7 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit; use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind}; +use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; @@ -78,10 +80,11 @@ fn compare_predicate_entailment<'tcx>( let trait_to_impl_substs = impl_trait_ref.substs; // This node-id should be used for the `body_id` field on each - // `ObligationCause` (and the `FnCtxt`). This is what - // `regionck_item` expects. + // `ObligationCause` (and the `FnCtxt`). + // + // FIXME(@lcnr): remove that after removing `cause.body_id` from + // obligations. let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local()); - // We sometimes modify the span further down. let mut cause = ObligationCause::new( impl_m_span, @@ -398,8 +401,10 @@ fn compare_predicate_entailment<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. - let fcx = FnCtxt::new(&inh, param_env, impl_m_hir_id); - fcx.regionck_item(impl_m_hir_id, impl_m_span, wf_tys); + let mut outlives_environment = OutlivesEnvironment::new(param_env); + outlives_environment.add_implied_bounds(infcx, wf_tys, impl_m_hir_id); + outlives_environment.save_implied_bounds(impl_m_hir_id); + infcx.check_region_obligations_and_report_errors(&outlives_environment); Ok(()) }) @@ -1154,8 +1159,9 @@ pub(crate) fn compare_const_impl<'tcx>( return; } - let fcx = FnCtxt::new(&inh, param_env, impl_c_hir_id); - fcx.regionck_item(impl_c_hir_id, impl_c_span, FxHashSet::default()); + let mut outlives_environment = OutlivesEnvironment::new(param_env); + outlives_environment.save_implied_bounds(impl_c_hir_id); + infcx.resolve_regions_and_report_errors(&outlives_environment); }); } @@ -1273,8 +1279,9 @@ fn compare_type_predicate_entailment<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. - let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id); - fcx.regionck_item(impl_ty_hir_id, impl_ty_span, FxHashSet::default()); + let mut outlives_environment = OutlivesEnvironment::new(param_env); + outlives_environment.save_implied_bounds(impl_ty_hir_id); + infcx.check_region_obligations_and_report_errors(&outlives_environment); Ok(()) }) @@ -1498,12 +1505,17 @@ pub fn check_type_bounds<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. + // + // FIXME: Remove that `FnCtxt`. let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id); let implied_bounds = match impl_ty.container { ty::TraitContainer(_) => FxHashSet::default(), ty::ImplContainer(def_id) => fcx.impl_implied_bounds(def_id, impl_ty_span), }; - fcx.regionck_item(impl_ty_hir_id, impl_ty_span, implied_bounds); + let mut outlives_environment = OutlivesEnvironment::new(param_env); + outlives_environment.add_implied_bounds(infcx, implied_bounds, impl_ty_hir_id); + outlives_environment.save_implied_bounds(impl_ty_hir_id); + infcx.check_region_obligations_and_report_errors(&outlives_environment); Ok(()) }) diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 028df78e6bd..b812085734d 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -491,7 +491,7 @@ fn typeck_with_fallback<'tcx>( fcx.check_asms(); if fn_sig.is_some() { - fcx.regionck_fn(id, body, span, wf_tys); + fcx.regionck_fn(id, body, wf_tys); } else { fcx.regionck_body(body); } diff --git a/compiler/rustc_typeck/src/check/regionck.rs b/compiler/rustc_typeck/src/check/regionck.rs index 06fe7dcd450..bf30ba2278c 100644 --- a/compiler/rustc_typeck/src/check/regionck.rs +++ b/compiler/rustc_typeck/src/check/regionck.rs @@ -108,7 +108,6 @@ pub(crate) trait OutlivesEnvironmentExt<'tcx> { infcx: &InferCtxt<'_, 'tcx>, fn_sig_tys: FxHashSet>, body_id: hir::HirId, - span: Span, ); } @@ -135,11 +134,10 @@ impl<'tcx> OutlivesEnvironmentExt<'tcx> for OutlivesEnvironment<'tcx> { infcx: &InferCtxt<'a, 'tcx>, fn_sig_tys: FxHashSet>, body_id: hir::HirId, - span: Span, ) { for ty in fn_sig_tys { let ty = infcx.resolve_vars_if_possible(ty); - let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty, span); + let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty); self.add_outlives_bounds(Some(infcx), implied_bounds) } } @@ -166,18 +164,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcx.fcx.skip_region_resolution(); } - /// Region checking during the WF phase for items. `wf_tys` are the - /// types from which we should derive implied bounds, if any. - #[instrument(level = "debug", skip(self))] - pub fn regionck_item(&self, item_id: hir::HirId, span: Span, wf_tys: FxHashSet>) { - let body_owner = self.tcx.hir().local_def_id(item_id); - let mut rcx = RegionCtxt::new(self, body_owner, self.param_env); - rcx.outlives_environment.add_implied_bounds(self, wf_tys, item_id, span); - rcx.outlives_environment.save_implied_bounds(rcx.body_id()); - rcx.visit_region_obligations(item_id); - rcx.resolve_regions_and_report_errors(); - } - /// Region check a function body. Not invoked on closures, but /// only on the "root" fn item (in which closures may be /// embedded). Walks the function body and adds various add'l @@ -190,19 +176,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, fn_id: hir::HirId, body: &'tcx hir::Body<'tcx>, - span: Span, wf_tys: FxHashSet>, ) { debug!("regionck_fn(id={})", fn_id); let body_owner = self.tcx.hir().body_owner_def_id(body.id()); let mut rcx = RegionCtxt::new(self, body_owner, self.param_env); // We need to add the implied bounds from the function signature - rcx.outlives_environment.add_implied_bounds(self, wf_tys, fn_id, span); + rcx.outlives_environment.add_implied_bounds(self, wf_tys, fn_id); rcx.outlives_environment.save_implied_bounds(fn_id); if !self.errors_reported_since_creation() { // regionck assumes typeck succeeded - rcx.visit_fn_body(fn_id, body, self.tcx.hir().span(fn_id)); + rcx.visit_fn_body(fn_id, body); } // Checked by NLL @@ -294,7 +279,6 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { &mut self, id: hir::HirId, // the id of the fn itself body: &'tcx hir::Body<'tcx>, - span: Span, ) { // When we enter a function, we can derive debug!("visit_fn_body(id={:?})", id); @@ -313,7 +297,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { let fn_sig_tys: FxHashSet<_> = fn_sig.inputs().iter().cloned().chain(Some(fn_sig.output())).collect(); - self.outlives_environment.add_implied_bounds(self.fcx, fn_sig_tys, body_id.hir_id, span); + self.outlives_environment.add_implied_bounds(self.fcx, fn_sig_tys, body_id.hir_id); self.outlives_environment.save_implied_bounds(body_id.hir_id); self.link_fn_params(body.params); self.visit_body(body); @@ -349,15 +333,6 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { self.select_all_obligations_or_error(); } - fn resolve_regions_and_report_errors(&self) { - self.infcx.process_registered_region_obligations( - self.outlives_environment.region_bound_pairs_map(), - self.param_env, - ); - - self.fcx.resolve_regions_and_report_errors(&self.outlives_environment); - } - fn constrain_bindings_in_pat(&mut self, pat: &hir::Pat<'_>) { debug!("regionck::visit_pat(pat={:?})", pat); pat.each_binding(|_, hir_id, span, _| { @@ -382,7 +357,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionCtxt<'a, 'tcx> { fk: intravisit::FnKind<'tcx>, _: &'tcx hir::FnDecl<'tcx>, body_id: hir::BodyId, - span: Span, + _span: Span, hir_id: hir::HirId, ) { assert!( @@ -396,7 +371,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionCtxt<'a, 'tcx> { let env_snapshot = self.outlives_environment.push_snapshot_pre_typeck_child(); let body = self.tcx.hir().body(body_id); - self.visit_fn_body(hir_id, body, span); + self.visit_fn_body(hir_id, body); // Restore state from previous function. self.outlives_environment.pop_snapshot_post_typeck_child(env_snapshot); diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 652f711ccf4..9240d9e06b9 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -62,7 +62,11 @@ impl<'tcx> CheckWfFcxBuilder<'tcx> { } let wf_tys = f(&fcx); fcx.select_all_obligations_or_error(); - fcx.regionck_item(id, span, wf_tys); + + let mut outlives_environment = OutlivesEnvironment::new(param_env); + outlives_environment.add_implied_bounds(&fcx.infcx, wf_tys, id); + outlives_environment.save_implied_bounds(id); + fcx.infcx.check_region_obligations_and_report_errors(&outlives_environment); }); } } @@ -655,7 +659,7 @@ fn resolve_regions_with_wf_tys<'tcx>( // call individually. tcx.infer_ctxt().enter(|infcx| { let mut outlives_environment = OutlivesEnvironment::new(param_env); - outlives_environment.add_implied_bounds(&infcx, wf_tys.clone(), id, DUMMY_SP); + outlives_environment.add_implied_bounds(&infcx, wf_tys.clone(), id); outlives_environment.save_implied_bounds(id); let region_bound_pairs = outlives_environment.region_bound_pairs_map().get(&id).unwrap(); diff --git a/compiler/rustc_typeck/src/outlives/outlives_bounds.rs b/compiler/rustc_typeck/src/outlives/outlives_bounds.rs index 3bf697e7682..70b8bcd0220 100644 --- a/compiler/rustc_typeck/src/outlives/outlives_bounds.rs +++ b/compiler/rustc_typeck/src/outlives/outlives_bounds.rs @@ -1,6 +1,5 @@ use rustc_hir as hir; use rustc_middle::ty::{self, Ty}; -use rustc_span::source_map::Span; use rustc_trait_selection::infer::InferCtxt; use rustc_trait_selection::traits::query::type_op::{self, TypeOp, TypeOpOutput}; use rustc_trait_selection::traits::query::NoSolution; @@ -14,7 +13,6 @@ pub trait InferCtxtExt<'tcx> { param_env: ty::ParamEnv<'tcx>, body_id: hir::HirId, ty: Ty<'tcx>, - span: Span, ) -> Vec>; } @@ -38,16 +36,14 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { /// Note that this may cause outlives obligations to be injected /// into the inference context with this body-id. /// - `ty`, the type that we are supposed to assume is WF. - /// - `span`, a span to use when normalizing, hopefully not important, - /// might be useful if a `bug!` occurs. - #[instrument(level = "debug", skip(self, param_env, body_id, span))] + #[instrument(level = "debug", skip(self, param_env, body_id))] fn implied_outlives_bounds( &self, param_env: ty::ParamEnv<'tcx>, body_id: hir::HirId, ty: Ty<'tcx>, - span: Span, ) -> Vec> { + let span = self.tcx.hir().span(body_id); let result = param_env .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty }) .fully_perform(self);