only use FnCtxt
for regionck inside of bodies
This commit is contained in:
parent
edd45f9d41
commit
68d70fc5bd
@ -69,6 +69,7 @@
|
||||
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 @@ pub fn process_registered_region_obligations(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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`
|
||||
|
@ -13,6 +13,7 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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::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(())
|
||||
})
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -108,7 +108,6 @@ fn add_implied_bounds(
|
||||
infcx: &InferCtxt<'_, 'tcx>,
|
||||
fn_sig_tys: FxHashSet<Ty<'tcx>>,
|
||||
body_id: hir::HirId,
|
||||
span: Span,
|
||||
);
|
||||
}
|
||||
|
||||
@ -135,11 +134,10 @@ fn add_implied_bounds<'a>(
|
||||
infcx: &InferCtxt<'a, 'tcx>,
|
||||
fn_sig_tys: FxHashSet<Ty<'tcx>>,
|
||||
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 @@ pub fn regionck_body(&self, body: &'tcx hir::Body<'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<Ty<'tcx>>) {
|
||||
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 @@ pub(crate) fn regionck_fn(
|
||||
&self,
|
||||
fn_id: hir::HirId,
|
||||
body: &'tcx hir::Body<'tcx>,
|
||||
span: Span,
|
||||
wf_tys: FxHashSet<Ty<'tcx>>,
|
||||
) {
|
||||
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 @@ fn visit_fn_body(
|
||||
&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 @@ fn visit_fn_body(
|
||||
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 @@ fn visit_region_obligations(&mut self, hir_id: hir::HirId) {
|
||||
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 @@ fn visit_fn(
|
||||
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 @@ fn visit_fn(
|
||||
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);
|
||||
|
@ -62,7 +62,11 @@ pub(super) fn with_fcx<F>(&mut self, f: F)
|
||||
}
|
||||
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();
|
||||
|
||||
|
@ -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 @@ fn implied_outlives_bounds(
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
body_id: hir::HirId,
|
||||
ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
) -> Vec<OutlivesBound<'tcx>>;
|
||||
}
|
||||
|
||||
@ -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<OutlivesBound<'tcx>> {
|
||||
let span = self.tcx.hir().span(body_id);
|
||||
let result = param_env
|
||||
.and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
|
||||
.fully_perform(self);
|
||||
|
Loading…
Reference in New Issue
Block a user