1
Fork 0

Auto merge of #136038 - compiler-errors:outlives, r=lcnr

Simplify and consolidate the way we handle construct `OutlivesEnvironment` for lexical region resolution

This is best reviewed commit-by-commit. I tried to consolidate the API for lexical region resolution *first*, then change the API when it was finally behind a single surface.

r? lcnr or reassign
This commit is contained in:
bors 2025-01-30 11:40:32 +00:00
commit 5a45ab9738
20 changed files with 165 additions and 197 deletions

View file

@ -1,6 +1,8 @@
use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::ErrorGuaranteed; use rustc_errors::ErrorGuaranteed;
use rustc_hir::OpaqueTyOrigin;
use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::LocalDefId;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, TyCtxtInferExt as _}; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, TyCtxtInferExt as _};
use rustc_macros::extension; use rustc_macros::extension;
use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::fold::fold_regions;
@ -10,6 +12,7 @@ use rustc_middle::ty::{
TypingMode, TypingMode,
}; };
use rustc_span::Span; use rustc_span::Span;
use rustc_trait_selection::regions::OutlivesEnvironmentBuildExt;
use rustc_trait_selection::traits::ObligationCtxt; use rustc_trait_selection::traits::ObligationCtxt;
use tracing::{debug, instrument}; use tracing::{debug, instrument};
@ -406,10 +409,6 @@ impl<'tcx> LazyOpaqueTyEnv<'tcx> {
} }
fn get_canonical_args(&self) -> ty::GenericArgsRef<'tcx> { fn get_canonical_args(&self) -> ty::GenericArgsRef<'tcx> {
use rustc_hir as hir;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
if let Some(&canonical_args) = self.canonical_args.get() { if let Some(&canonical_args) = self.canonical_args.get() {
return canonical_args; return canonical_args;
} }
@ -417,9 +416,9 @@ impl<'tcx> LazyOpaqueTyEnv<'tcx> {
let &Self { tcx, def_id, .. } = self; let &Self { tcx, def_id, .. } = self;
let origin = tcx.local_opaque_ty_origin(def_id); let origin = tcx.local_opaque_ty_origin(def_id);
let parent = match origin { let parent = match origin {
hir::OpaqueTyOrigin::FnReturn { parent, .. } OpaqueTyOrigin::FnReturn { parent, .. }
| hir::OpaqueTyOrigin::AsyncFn { parent, .. } | OpaqueTyOrigin::AsyncFn { parent, .. }
| hir::OpaqueTyOrigin::TyAlias { parent, .. } => parent, | OpaqueTyOrigin::TyAlias { parent, .. } => parent,
}; };
let param_env = tcx.param_env(parent); let param_env = tcx.param_env(parent);
let args = GenericArgs::identity_for_item(tcx, parent).extend_to( let args = GenericArgs::identity_for_item(tcx, parent).extend_to(
@ -439,8 +438,7 @@ impl<'tcx> LazyOpaqueTyEnv<'tcx> {
tcx.dcx().span_delayed_bug(tcx.def_span(def_id), "error getting implied bounds"); tcx.dcx().span_delayed_bug(tcx.def_span(def_id), "error getting implied bounds");
Default::default() Default::default()
}); });
let implied_bounds = infcx.implied_bounds_tys(param_env, parent, &wf_tys); let outlives_env = OutlivesEnvironment::new(&infcx, parent, param_env, wf_tys);
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
let mut seen = vec![tcx.lifetimes.re_static]; let mut seen = vec![tcx.lifetimes.re_static];
let canonical_args = fold_regions(tcx, args, |r1, _| { let canonical_args = fold_regions(tcx, args, |r1, _| {

View file

@ -27,7 +27,6 @@ use rustc_session::lint::builtin::UNINHABITED_STATIC;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::error_reporting::traits::on_unimplemented::OnUnimplementedDirective; use rustc_trait_selection::error_reporting::traits::on_unimplemented::OnUnimplementedDirective;
use rustc_trait_selection::traits; use rustc_trait_selection::traits;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_type_ir::fold::TypeFoldable; use rustc_type_ir::fold::TypeFoldable;
use tracing::{debug, instrument}; use tracing::{debug, instrument};
use ty::TypingMode; use ty::TypingMode;
@ -417,9 +416,7 @@ fn check_opaque_meets_bounds<'tcx>(
} }
let wf_tys = ocx.assumed_wf_types_and_report_errors(param_env, defining_use_anchor)?; let wf_tys = ocx.assumed_wf_types_and_report_errors(param_env, defining_use_anchor)?;
let implied_bounds = infcx.implied_bounds_tys(param_env, def_id, &wf_tys); ocx.resolve_regions_and_report_errors(defining_use_anchor, param_env, wf_tys)?;
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?;
if infcx.next_trait_solver() { if infcx.next_trait_solver() {
Ok(()) Ok(())

View file

@ -9,7 +9,6 @@ use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_e
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::VisitorExt; use rustc_hir::intravisit::VisitorExt;
use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisit}; use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisit};
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::util; use rustc_infer::traits::util;
use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::error::{ExpectedFound, TypeError};
@ -24,7 +23,6 @@ use rustc_span::Span;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::regions::InferCtxtRegionExt;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::{ use rustc_trait_selection::traits::{
self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt, self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt,
}; };
@ -416,11 +414,7 @@ fn compare_method_predicate_entailment<'tcx>(
// Finally, resolve all regions. This catches wily misuses of // Finally, resolve all regions. This catches wily misuses of
// lifetime parameters. // lifetime parameters.
let outlives_env = OutlivesEnvironment::with_bounds( let errors = infcx.resolve_regions(impl_m_def_id, param_env, wf_tys);
param_env,
infcx.implied_bounds_tys(param_env, impl_m_def_id, &wf_tys),
);
let errors = infcx.resolve_regions(&outlives_env);
if !errors.is_empty() { if !errors.is_empty() {
return Err(infcx return Err(infcx
.tainted_by_errors() .tainted_by_errors()
@ -725,11 +719,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
// Finally, resolve all regions. This catches wily misuses of // Finally, resolve all regions. This catches wily misuses of
// lifetime parameters. // lifetime parameters.
let outlives_env = OutlivesEnvironment::with_bounds( ocx.resolve_regions_and_report_errors(impl_m_def_id, param_env, wf_tys)?;
param_env,
infcx.implied_bounds_tys(param_env, impl_m_def_id, &wf_tys),
);
ocx.resolve_regions_and_report_errors(impl_m_def_id, &outlives_env)?;
let mut remapped_types = DefIdMap::default(); let mut remapped_types = DefIdMap::default();
for (def_id, (ty, args)) in collected_types { for (def_id, (ty, args)) in collected_types {
@ -1883,8 +1873,7 @@ fn compare_const_predicate_entailment<'tcx>(
return Err(infcx.err_ctxt().report_fulfillment_errors(errors)); return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
} }
let outlives_env = OutlivesEnvironment::new(param_env); ocx.resolve_regions_and_report_errors(impl_ct_def_id, param_env, [])
ocx.resolve_regions_and_report_errors(impl_ct_def_id, &outlives_env)
} }
#[instrument(level = "debug", skip(tcx))] #[instrument(level = "debug", skip(tcx))]
@ -2017,8 +2006,7 @@ fn compare_type_predicate_entailment<'tcx>(
// Finally, resolve all regions. This catches wily misuses of // Finally, resolve all regions. This catches wily misuses of
// lifetime parameters. // lifetime parameters.
let outlives_env = OutlivesEnvironment::new(param_env); ocx.resolve_regions_and_report_errors(impl_ty_def_id, param_env, [])
ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env)
} }
/// Validate that `ProjectionCandidate`s created for this associated type will /// Validate that `ProjectionCandidate`s created for this associated type will
@ -2147,9 +2135,7 @@ pub(super) fn check_type_bounds<'tcx>(
// Finally, resolve all regions. This catches wily misuses of // Finally, resolve all regions. This catches wily misuses of
// lifetime parameters. // lifetime parameters.
let implied_bounds = infcx.implied_bounds_tys(param_env, impl_ty_def_id, &assumed_wf_types); ocx.resolve_regions_and_report_errors(impl_ty_def_id, param_env, assumed_wf_types)
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env)
} }
struct ReplaceTy<'tcx> { struct ReplaceTy<'tcx> {

View file

@ -3,7 +3,6 @@ use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_lint_defs::builtin::{REFINING_IMPL_TRAIT_INTERNAL, REFINING_IMPL_TRAIT_REACHABLE}; use rustc_lint_defs::builtin::{REFINING_IMPL_TRAIT_INTERNAL, REFINING_IMPL_TRAIT_REACHABLE};
use rustc_middle::span_bug; use rustc_middle::span_bug;
use rustc_middle::traits::ObligationCause; use rustc_middle::traits::ObligationCause;
@ -13,7 +12,6 @@ use rustc_middle::ty::{
}; };
use rustc_span::Span; use rustc_span::Span;
use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::regions::InferCtxtRegionExt;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt;
use rustc_trait_selection::traits::{ObligationCtxt, elaborate, normalize_param_env_or_error}; use rustc_trait_selection::traits::{ObligationCtxt, elaborate, normalize_param_env_or_error};
/// Check that an implementation does not refine an RPITIT from a trait method signature. /// Check that an implementation does not refine an RPITIT from a trait method signature.
@ -170,11 +168,7 @@ pub(crate) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
tcx.dcx().delayed_bug("encountered errors when checking RPITIT refinement (selection)"); tcx.dcx().delayed_bug("encountered errors when checking RPITIT refinement (selection)");
return; return;
} }
let outlives_env = OutlivesEnvironment::with_bounds( let errors = infcx.resolve_regions(impl_m.def_id.expect_local(), param_env, implied_wf_types);
param_env,
infcx.implied_bounds_tys(param_env, impl_m.def_id.expect_local(), &implied_wf_types),
);
let errors = infcx.resolve_regions(&outlives_env);
if !errors.is_empty() { if !errors.is_empty() {
tcx.dcx().delayed_bug("encountered errors when checking RPITIT refinement (regions)"); tcx.dcx().delayed_bug("encountered errors when checking RPITIT refinement (regions)");
return; return;

View file

@ -5,7 +5,6 @@
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_errors::codes::*; use rustc_errors::codes::*;
use rustc_errors::{ErrorGuaranteed, struct_span_code_err}; use rustc_errors::{ErrorGuaranteed, struct_span_code_err};
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt}; use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
use rustc_infer::traits::{ObligationCause, ObligationCauseCode}; use rustc_infer::traits::{ObligationCause, ObligationCauseCode};
use rustc_middle::ty::util::CheckRegions; use rustc_middle::ty::util::CheckRegions;
@ -192,7 +191,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
return Err(guar.unwrap()); return Err(guar.unwrap());
} }
let errors = ocx.infcx.resolve_regions(&OutlivesEnvironment::new(adt_env)); let errors = ocx.infcx.resolve_regions(adt_def_id, adt_env, []);
if !errors.is_empty() { if !errors.is_empty() {
let mut guar = None; let mut guar = None;
for error in errors { for error in errors {

View file

@ -80,7 +80,6 @@ use rustc_errors::{Diag, ErrorGuaranteed, pluralize, struct_span_code_err};
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::Visitor; use rustc_hir::intravisit::Visitor;
use rustc_index::bit_set::DenseBitSet; use rustc_index::bit_set::DenseBitSet;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{self, TyCtxtInferExt as _}; use rustc_infer::infer::{self, TyCtxtInferExt as _};
use rustc_infer::traits::ObligationCause; use rustc_infer::traits::ObligationCause;
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
@ -655,8 +654,7 @@ pub fn check_function_signature<'tcx>(
} }
} }
let outlives_env = OutlivesEnvironment::new(param_env); if let Err(e) = ocx.resolve_regions_and_report_errors(local_id, param_env, []) {
if let Err(e) = ocx.resolve_regions_and_report_errors(local_id, &outlives_env) {
return Err(e); return Err(e);
} }

View file

@ -25,11 +25,10 @@ use rustc_middle::{bug, span_bug};
use rustc_session::parse::feature_err; use rustc_session::parse::feature_err;
use rustc_span::{DUMMY_SP, Ident, Span, sym}; use rustc_span::{DUMMY_SP, Ident, Span, sym};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::regions::{InferCtxtRegionExt, OutlivesEnvironmentBuildExt};
use rustc_trait_selection::traits::misc::{ use rustc_trait_selection::traits::misc::{
ConstParamTyImplementationError, type_allowed_to_implement_const_param_ty, ConstParamTyImplementationError, type_allowed_to_implement_const_param_ty,
}; };
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_trait_selection::traits::{ use rustc_trait_selection::traits::{
self, FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, ObligationCtxt, self, FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, ObligationCtxt,
@ -128,13 +127,17 @@ where
let infcx_compat = infcx.fork(); let infcx_compat = infcx.fork();
// We specifically want to call the non-compat version of `implied_bounds_tys`; we do this always. // We specifically want to call the non-compat version of `implied_bounds_tys`; we do this always.
let implied_bounds = let outlives_env = OutlivesEnvironment::new_with_implied_bounds_compat(
infcx.implied_bounds_tys_compat(param_env, body_def_id, &assumed_wf_types, false); &infcx,
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); body_def_id,
param_env,
assumed_wf_types.iter().copied(),
false,
);
lint_redundant_lifetimes(tcx, body_def_id, &outlives_env); lint_redundant_lifetimes(tcx, body_def_id, &outlives_env);
let errors = infcx.resolve_regions(&outlives_env); let errors = infcx.resolve_regions_with_outlives_env(&outlives_env);
if errors.is_empty() { if errors.is_empty() {
return Ok(()); return Ok(());
} }
@ -172,10 +175,14 @@ where
// but that does result in slightly more work when this option is set and // but that does result in slightly more work when this option is set and
// just obscures what we mean here anyways. Let's just be explicit. // just obscures what we mean here anyways. Let's just be explicit.
if is_bevy && !infcx.tcx.sess.opts.unstable_opts.no_implied_bounds_compat { if is_bevy && !infcx.tcx.sess.opts.unstable_opts.no_implied_bounds_compat {
let implied_bounds = let outlives_env = OutlivesEnvironment::new_with_implied_bounds_compat(
infcx_compat.implied_bounds_tys_compat(param_env, body_def_id, &assumed_wf_types, true); &infcx,
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); body_def_id,
let errors_compat = infcx_compat.resolve_regions(&outlives_env); param_env,
assumed_wf_types,
true,
);
let errors_compat = infcx_compat.resolve_regions_with_outlives_env(&outlives_env);
if errors_compat.is_empty() { if errors_compat.is_empty() {
Ok(()) Ok(())
} else { } else {
@ -769,12 +776,7 @@ fn test_region_obligations<'tcx>(
add_constraints(&infcx); add_constraints(&infcx);
let outlives_environment = OutlivesEnvironment::with_bounds( let errors = infcx.resolve_regions(id, param_env, wf_tys.iter().copied());
param_env,
infcx.implied_bounds_tys(param_env, id, wf_tys),
);
let errors = infcx.resolve_regions(&outlives_environment);
debug!(?errors, "errors"); debug!(?errors, "errors");
// If we were able to prove that the type outlives the region without // If we were able to prove that the type outlives the region without

View file

@ -10,7 +10,6 @@ use rustc_hir as hir;
use rustc_hir::ItemKind; use rustc_hir::ItemKind;
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{self, RegionResolutionError, TyCtxtInferExt}; use rustc_infer::infer::{self, RegionResolutionError, TyCtxtInferExt};
use rustc_infer::traits::Obligation; use rustc_infer::traits::Obligation;
use rustc_middle::ty::adjustment::CoerceUnsizedInfo; use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
@ -346,8 +345,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
} }
// Finally, resolve all regions. // Finally, resolve all regions.
let outlives_env = OutlivesEnvironment::new(param_env); res = res.and(ocx.resolve_regions_and_report_errors(impl_did, param_env, []));
res = res.and(ocx.resolve_regions_and_report_errors(impl_did, &outlives_env));
} }
res res
} }
@ -564,8 +562,7 @@ pub(crate) fn coerce_unsized_info<'tcx>(
} }
// Finally, resolve all regions. // Finally, resolve all regions.
let outlives_env = OutlivesEnvironment::new(param_env); let _ = ocx.resolve_regions_and_report_errors(impl_did, param_env, []);
let _ = ocx.resolve_regions_and_report_errors(impl_did, &outlives_env);
Ok(CoerceUnsizedInfo { custom_kind: kind }) Ok(CoerceUnsizedInfo { custom_kind: kind })
} }

View file

@ -68,7 +68,6 @@
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::traits::ObligationCause; use rustc_infer::traits::ObligationCause;
use rustc_infer::traits::specialization_graph::Node; use rustc_infer::traits::specialization_graph::Node;
use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::trait_def::TraitSpecializationKind;
@ -77,7 +76,6 @@ use rustc_middle::ty::{
}; };
use rustc_span::{ErrorGuaranteed, Span}; use rustc_span::{ErrorGuaranteed, Span};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::{self, ObligationCtxt, translate_args_with_cause, wf}; use rustc_trait_selection::traits::{self, ObligationCtxt, translate_args_with_cause, wf};
use tracing::{debug, instrument}; use tracing::{debug, instrument};
@ -176,7 +174,6 @@ fn get_impl_args(
let ocx = ObligationCtxt::new_with_diagnostics(infcx); let ocx = ObligationCtxt::new_with_diagnostics(infcx);
let param_env = tcx.param_env(impl1_def_id); let param_env = tcx.param_env(impl1_def_id);
let impl1_span = tcx.def_span(impl1_def_id); let impl1_span = tcx.def_span(impl1_def_id);
let assumed_wf_types = ocx.assumed_wf_types_and_report_errors(param_env, impl1_def_id)?;
let impl1_args = GenericArgs::identity_for_item(tcx, impl1_def_id); let impl1_args = GenericArgs::identity_for_item(tcx, impl1_def_id);
let impl2_args = translate_args_with_cause( let impl2_args = translate_args_with_cause(
@ -194,9 +191,8 @@ fn get_impl_args(
return Err(guar); return Err(guar);
} }
let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_def_id, &assumed_wf_types); let assumed_wf_types = ocx.assumed_wf_types_and_report_errors(param_env, impl1_def_id)?;
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, param_env, assumed_wf_types);
let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env);
let Ok(impl2_args) = infcx.fully_resolve(impl2_args) else { let Ok(impl2_args) = infcx.fully_resolve(impl2_args) else {
let span = tcx.def_span(impl1_def_id); let span = tcx.def_span(impl1_def_id);
let guar = tcx.dcx().emit_err(GenericArgsOnOverriddenImpl { span }); let guar = tcx.dcx().emit_err(GenericArgsOnOverriddenImpl { span });

View file

@ -31,26 +31,14 @@ use crate::traits::query::OutlivesBound;
pub struct OutlivesEnvironment<'tcx> { pub struct OutlivesEnvironment<'tcx> {
pub param_env: ty::ParamEnv<'tcx>, pub param_env: ty::ParamEnv<'tcx>,
free_region_map: FreeRegionMap<'tcx>, free_region_map: FreeRegionMap<'tcx>,
/// FIXME: Your first reaction may be that this is a bit strange. `RegionBoundPairs`
// Contains the implied region bounds in scope for our current body. /// does not contain lifetimes, which are instead in the `FreeRegionMap`, and other
// /// known type outlives are stored in the `known_type_outlives` set. So why do we
// Example: /// have these at all? It turns out that removing these and using `known_type_outlives`
// /// everywhere is just enough of a perf regression to matter. This can/should be
// ``` /// optimized in the future, though.
// fn foo<'a, 'b, T>(x: &'a T, y: &'b ()) {
// bar(x, y, |y: &'b T| { .. } // body B1)
// } // body B0
// ```
//
// Here, when checking the body B0, the list would be `[T: 'a]`, because we
// infer that `T` must outlive `'a` from the implied bounds on the
// fn declaration.
//
// For the body B1 however, the list would be `[T: 'a, T: 'b]`, because we
// also can see that -- within the closure body! -- `T` must
// outlive `'b`. This is not necessarily true outside the closure
// body, since the closure may never be called.
region_bound_pairs: RegionBoundPairs<'tcx>, region_bound_pairs: RegionBoundPairs<'tcx>,
known_type_outlives: Vec<ty::PolyTypeOutlivesPredicate<'tcx>>,
} }
/// "Region-bound pairs" tracks outlives relations that are known to /// "Region-bound pairs" tracks outlives relations that are known to
@ -59,15 +47,10 @@ pub struct OutlivesEnvironment<'tcx> {
pub type RegionBoundPairs<'tcx> = FxIndexSet<ty::OutlivesPredicate<'tcx, GenericKind<'tcx>>>; pub type RegionBoundPairs<'tcx> = FxIndexSet<ty::OutlivesPredicate<'tcx, GenericKind<'tcx>>>;
impl<'tcx> OutlivesEnvironment<'tcx> { impl<'tcx> OutlivesEnvironment<'tcx> {
/// Create a new `OutlivesEnvironment` without extra outlives bounds. /// Create a new `OutlivesEnvironment` from normalized outlives bounds.
#[inline] pub fn from_normalized_bounds(
pub fn new(param_env: ty::ParamEnv<'tcx>) -> Self {
Self::with_bounds(param_env, vec![])
}
/// Create a new `OutlivesEnvironment` with extra outlives bounds.
pub fn with_bounds(
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
known_type_outlives: Vec<ty::PolyTypeOutlivesPredicate<'tcx>>,
extra_bounds: impl IntoIterator<Item = OutlivesBound<'tcx>>, extra_bounds: impl IntoIterator<Item = OutlivesBound<'tcx>>,
) -> Self { ) -> Self {
let mut region_relation = TransitiveRelationBuilder::default(); let mut region_relation = TransitiveRelationBuilder::default();
@ -102,18 +85,21 @@ impl<'tcx> OutlivesEnvironment<'tcx> {
OutlivesEnvironment { OutlivesEnvironment {
param_env, param_env,
known_type_outlives,
free_region_map: FreeRegionMap { relation: region_relation.freeze() }, free_region_map: FreeRegionMap { relation: region_relation.freeze() },
region_bound_pairs, region_bound_pairs,
} }
} }
/// Borrows current value of the `free_region_map`.
pub fn free_region_map(&self) -> &FreeRegionMap<'tcx> { pub fn free_region_map(&self) -> &FreeRegionMap<'tcx> {
&self.free_region_map &self.free_region_map
} }
/// Borrows current `region_bound_pairs`.
pub fn region_bound_pairs(&self) -> &RegionBoundPairs<'tcx> { pub fn region_bound_pairs(&self) -> &RegionBoundPairs<'tcx> {
&self.region_bound_pairs &self.region_bound_pairs
} }
pub fn known_type_outlives(&self) -> &[ty::PolyTypeOutlivesPredicate<'tcx>] {
&self.known_type_outlives
}
} }

View file

@ -67,7 +67,6 @@ use rustc_middle::ty::{
self, GenericArgKind, GenericArgsRef, PolyTypeOutlivesPredicate, Region, Ty, TyCtxt, self, GenericArgKind, GenericArgsRef, PolyTypeOutlivesPredicate, Region, Ty, TyCtxt,
TypeFoldable as _, TypeVisitableExt, TypeFoldable as _, TypeVisitableExt,
}; };
use rustc_span::DUMMY_SP;
use rustc_type_ir::outlives::{Component, push_outlives_components}; use rustc_type_ir::outlives::{Component, push_outlives_components};
use smallvec::smallvec; use smallvec::smallvec;
use tracing::{debug, instrument}; use tracing::{debug, instrument};
@ -142,25 +141,6 @@ impl<'tcx> InferCtxt<'tcx> {
) -> Result<(), (PolyTypeOutlivesPredicate<'tcx>, SubregionOrigin<'tcx>)> { ) -> Result<(), (PolyTypeOutlivesPredicate<'tcx>, SubregionOrigin<'tcx>)> {
assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot"); assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot");
let normalized_caller_bounds: Vec<_> = outlives_env
.param_env
.caller_bounds()
.iter()
.filter_map(|clause| {
let outlives = clause.as_type_outlives_clause()?;
Some(
deeply_normalize_ty(
outlives,
SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP),
)
// FIXME(-Znext-solver): How do we accurately report an error span here :(
.map_err(|NoSolution| {
(outlives, SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP))
}),
)
})
.try_collect()?;
// Must loop since the process of normalizing may itself register region obligations. // Must loop since the process of normalizing may itself register region obligations.
for iteration in 0.. { for iteration in 0.. {
let my_region_obligations = self.take_registered_region_obligations(); let my_region_obligations = self.take_registered_region_obligations();
@ -194,7 +174,7 @@ impl<'tcx> InferCtxt<'tcx> {
self.tcx, self.tcx,
outlives_env.region_bound_pairs(), outlives_env.region_bound_pairs(),
None, None,
&normalized_caller_bounds, outlives_env.known_type_outlives(),
); );
let category = origin.to_constraint_category(); let category = origin.to_constraint_category();
outlives.type_must_outlive(origin, sup_type, sub_region, category); outlives.type_must_outlive(origin, sup_type, sub_region, category);

View file

@ -25,8 +25,8 @@ use rustc_span::{Span, Symbol};
use rustc_trait_selection::errors::{ use rustc_trait_selection::errors::{
AddPreciseCapturingForOvercapture, impl_trait_overcapture_suggestion, AddPreciseCapturingForOvercapture, impl_trait_overcapture_suggestion,
}; };
use rustc_trait_selection::regions::OutlivesEnvironmentBuildExt;
use rustc_trait_selection::traits::ObligationCtxt; use rustc_trait_selection::traits::ObligationCtxt;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt;
use crate::{LateContext, LateLintPass, fluent_generated as fluent}; use crate::{LateContext, LateLintPass, fluent_generated as fluent};
@ -190,9 +190,7 @@ fn check_fn(tcx: TyCtxt<'_>, parent_def_id: LocalDefId) {
let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new(&infcx);
let assumed_wf_tys = ocx.assumed_wf_types(param_env, parent_def_id).unwrap_or_default(); let assumed_wf_tys = ocx.assumed_wf_types(param_env, parent_def_id).unwrap_or_default();
let implied_bounds = OutlivesEnvironment::new(&infcx, parent_def_id, param_env, assumed_wf_tys)
infcx.implied_bounds_tys_compat(param_env, parent_def_id, &assumed_wf_tys, false);
OutlivesEnvironment::with_bounds(param_env, implied_bounds)
}), }),
}); });
} }

View file

@ -1,10 +1,73 @@
use rustc_hir::def_id::LocalDefId;
use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{InferCtxt, RegionResolutionError}; use rustc_infer::infer::{InferCtxt, RegionResolutionError};
use rustc_macros::extension; use rustc_macros::extension;
use rustc_middle::traits::ObligationCause; use rustc_middle::traits::ObligationCause;
use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::{self, Ty};
use crate::traits::ScrubbedTraitError; use crate::traits::ScrubbedTraitError;
use crate::traits::outlives_bounds::InferCtxtExt;
#[extension(pub trait OutlivesEnvironmentBuildExt<'tcx>)]
impl<'tcx> OutlivesEnvironment<'tcx> {
fn new(
infcx: &InferCtxt<'tcx>,
body_id: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>,
) -> Self {
Self::new_with_implied_bounds_compat(
infcx,
body_id,
param_env,
assumed_wf_tys,
!infcx.tcx.sess.opts.unstable_opts.no_implied_bounds_compat,
)
}
fn new_with_implied_bounds_compat(
infcx: &InferCtxt<'tcx>,
body_id: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>,
implied_bounds_compat: bool,
) -> Self {
let mut bounds = vec![];
for bound in param_env.caller_bounds() {
if let Some(mut type_outlives) = bound.as_type_outlives_clause() {
if infcx.next_trait_solver() {
match crate::solve::deeply_normalize::<_, ScrubbedTraitError<'tcx>>(
infcx.at(&ObligationCause::dummy(), param_env),
type_outlives,
) {
Ok(new) => type_outlives = new,
Err(_) => {
infcx.dcx().delayed_bug(format!("could not normalize `{bound}`"));
}
}
}
bounds.push(type_outlives);
}
}
// FIXME: This needs to be modified so that we normalize the known type
// outlives obligations then elaborate them into their region/type components.
// Otherwise, `<W<'a> as Mirror>::Assoc: 'b` will not imply `'a: 'b` even
// if we can normalize `'a`.
OutlivesEnvironment::from_normalized_bounds(
param_env,
bounds,
infcx.implied_bounds_tys_with_compat(
body_id,
param_env,
assumed_wf_tys,
implied_bounds_compat,
),
)
}
}
#[extension(pub trait InferCtxtRegionExt<'tcx>)] #[extension(pub trait InferCtxtRegionExt<'tcx>)]
impl<'tcx> InferCtxt<'tcx> { impl<'tcx> InferCtxt<'tcx> {
@ -15,10 +78,25 @@ impl<'tcx> InferCtxt<'tcx> {
/// Prefer this method over `resolve_regions_with_normalize`, unless you are /// Prefer this method over `resolve_regions_with_normalize`, unless you are
/// doing something specific for normalization. /// doing something specific for normalization.
fn resolve_regions( fn resolve_regions(
&self,
body_id: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>,
) -> Vec<RegionResolutionError<'tcx>> {
self.resolve_regions_with_outlives_env(&OutlivesEnvironment::new(
self,
body_id,
param_env,
assumed_wf_tys,
))
}
/// Don't call this directly unless you know what you're doing.
fn resolve_regions_with_outlives_env(
&self, &self,
outlives_env: &OutlivesEnvironment<'tcx>, outlives_env: &OutlivesEnvironment<'tcx>,
) -> Vec<RegionResolutionError<'tcx>> { ) -> Vec<RegionResolutionError<'tcx>> {
self.resolve_regions_with_normalize(outlives_env, |ty, origin| { self.resolve_regions_with_normalize(&outlives_env, |ty, origin| {
let ty = self.resolve_vars_if_possible(ty); let ty = self.resolve_vars_if_possible(ty);
if self.next_trait_solver() { if self.next_trait_solver() {

View file

@ -6,6 +6,7 @@ use std::iter;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet, IndexEntry}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet, IndexEntry};
use rustc_data_structures::unord::UnordSet; use rustc_data_structures::unord::UnordSet;
use rustc_hir::def_id::CRATE_DEF_ID;
use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::DefineOpaqueTypes;
use rustc_middle::ty::{Region, RegionVid}; use rustc_middle::ty::{Region, RegionVid};
use tracing::debug; use tracing::debug;
@ -13,6 +14,7 @@ use tracing::debug;
use super::*; use super::*;
use crate::errors::UnableToConstructConstantValue; use crate::errors::UnableToConstructConstantValue;
use crate::infer::region_constraints::{Constraint, RegionConstraintData}; use crate::infer::region_constraints::{Constraint, RegionConstraintData};
use crate::regions::OutlivesEnvironmentBuildExt;
use crate::traits::project::ProjectAndUnifyResult; use crate::traits::project::ProjectAndUnifyResult;
// FIXME(twk): this is obviously not nice to duplicate like that // FIXME(twk): this is obviously not nice to duplicate like that
@ -158,7 +160,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
panic!("Unable to fulfill trait {trait_did:?} for '{ty:?}': {errors:?}"); panic!("Unable to fulfill trait {trait_did:?} for '{ty:?}': {errors:?}");
} }
let outlives_env = OutlivesEnvironment::new(full_env); let outlives_env = OutlivesEnvironment::new(&infcx, CRATE_DEF_ID, full_env, []);
let _ = infcx.process_registered_region_obligations(&outlives_env, |ty, _| Ok(ty)); let _ = infcx.process_registered_region_obligations(&outlives_env, |ty, _| Ok(ty));
let region_data = infcx.inner.borrow_mut().unwrap_region_constraints().data().clone(); let region_data = infcx.inner.borrow_mut().unwrap_region_constraints().data().clone();

View file

@ -9,7 +9,7 @@ use std::fmt::Debug;
use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_errors::{Diag, EmissionGuarantee}; use rustc_errors::{Diag, EmissionGuarantee};
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt}; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::PredicateObligations; use rustc_infer::traits::PredicateObligations;
use rustc_middle::bug; use rustc_middle::bug;
@ -27,7 +27,6 @@ use tracing::{debug, instrument, warn};
use super::ObligationCtxt; use super::ObligationCtxt;
use crate::error_reporting::traits::suggest_new_overflow_limit; use crate::error_reporting::traits::suggest_new_overflow_limit;
use crate::infer::InferOk; use crate::infer::InferOk;
use crate::infer::outlives::env::OutlivesEnvironment;
use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor}; use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor};
use crate::solve::{SolverDelegate, deeply_normalize_for_diagnostics, inspect}; use crate::solve::{SolverDelegate, deeply_normalize_for_diagnostics, inspect};
use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::query::evaluate_obligation::InferCtxtExt;
@ -596,8 +595,7 @@ fn try_prove_negated_where_clause<'tcx>(
// FIXME: We could use the assumed_wf_types from both impls, I think, // FIXME: We could use the assumed_wf_types from both impls, I think,
// if that wasn't implemented just for LocalDefId, and we'd need to do // if that wasn't implemented just for LocalDefId, and we'd need to do
// the normalization ourselves since this is totally fallible... // the normalization ourselves since this is totally fallible...
let outlives_env = OutlivesEnvironment::new(param_env); let errors = ocx.resolve_regions(CRATE_DEF_ID, param_env, []);
let errors = ocx.resolve_regions(&outlives_env);
if !errors.is_empty() { if !errors.is_empty() {
return false; return false;
} }

View file

@ -8,7 +8,6 @@ use rustc_infer::infer::at::ToTrace;
use rustc_infer::infer::canonical::{ use rustc_infer::infer::canonical::{
Canonical, CanonicalQueryResponse, CanonicalVarValues, QueryResponse, Canonical, CanonicalQueryResponse, CanonicalVarValues, QueryResponse,
}; };
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk, RegionResolutionError, TypeTrace}; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk, RegionResolutionError, TypeTrace};
use rustc_infer::traits::PredicateObligations; use rustc_infer::traits::PredicateObligations;
use rustc_macros::extension; use rustc_macros::extension;
@ -217,14 +216,15 @@ where
/// will result in region constraints getting ignored. /// will result in region constraints getting ignored.
pub fn resolve_regions_and_report_errors( pub fn resolve_regions_and_report_errors(
self, self,
generic_param_scope: LocalDefId, body_id: LocalDefId,
outlives_env: &OutlivesEnvironment<'tcx>, param_env: ty::ParamEnv<'tcx>,
assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>,
) -> Result<(), ErrorGuaranteed> { ) -> Result<(), ErrorGuaranteed> {
let errors = self.infcx.resolve_regions(outlives_env); let errors = self.infcx.resolve_regions(body_id, param_env, assumed_wf_tys);
if errors.is_empty() { if errors.is_empty() {
Ok(()) Ok(())
} else { } else {
Err(self.infcx.err_ctxt().report_region_errors(generic_param_scope, &errors)) Err(self.infcx.err_ctxt().report_region_errors(body_id, &errors))
} }
} }
@ -235,9 +235,11 @@ where
#[must_use] #[must_use]
pub fn resolve_regions( pub fn resolve_regions(
self, self,
outlives_env: &OutlivesEnvironment<'tcx>, body_id: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>,
) -> Vec<RegionResolutionError<'tcx>> { ) -> Vec<RegionResolutionError<'tcx>> {
self.infcx.resolve_regions(outlives_env) self.infcx.resolve_regions(body_id, param_env, assumed_wf_tys)
} }
} }

View file

@ -4,13 +4,10 @@ use std::assert_matches::assert_matches;
use hir::LangItem; use hir::LangItem;
use rustc_ast::Mutability; use rustc_ast::Mutability;
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt}; use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt, TypingMode}; use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt, TypingMode};
use super::outlives_bounds::InferCtxtExt;
use crate::regions::InferCtxtRegionExt; use crate::regions::InferCtxtRegionExt;
use crate::traits::{self, FulfillmentError, ObligationCause}; use crate::traits::{self, FulfillmentError, ObligationCause};
@ -170,15 +167,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
} }
// Check regions assuming the self type of the impl is WF // Check regions assuming the self type of the impl is WF
let outlives_env = OutlivesEnvironment::with_bounds( let errors = infcx.resolve_regions(parent_cause.body_id, param_env, [self_type]);
param_env,
infcx.implied_bounds_tys(
param_env,
parent_cause.body_id,
&FxIndexSet::from_iter([self_type]),
),
);
let errors = infcx.resolve_regions(&outlives_env);
if !errors.is_empty() { if !errors.is_empty() {
infringing_inner_tys.push((inner_ty, InfringingFieldsReason::Regions(errors))); infringing_inner_tys.push((inner_ty, InfringingFieldsReason::Regions(errors)));
continue; continue;
@ -261,15 +250,7 @@ pub fn all_fields_implement_trait<'tcx>(
} }
// Check regions assuming the self type of the impl is WF // Check regions assuming the self type of the impl is WF
let outlives_env = OutlivesEnvironment::with_bounds( let errors = infcx.resolve_regions(parent_cause.body_id, param_env, [self_type]);
param_env,
infcx.implied_bounds_tys(
param_env,
parent_cause.body_id,
&FxIndexSet::from_iter([self_type]),
),
);
let errors = infcx.resolve_regions(&outlives_env);
if !errors.is_empty() { if !errors.is_empty() {
infringing.push((field, ty, InfringingFieldsReason::Regions(errors))); infringing.push((field, ty, InfringingFieldsReason::Regions(errors)));
} }

View file

@ -290,12 +290,10 @@ fn do_normalize_predicates<'tcx>(
// We can use the `elaborated_env` here; the region code only // We can use the `elaborated_env` here; the region code only
// cares about declarations like `'a: 'b`. // cares about declarations like `'a: 'b`.
let outlives_env = OutlivesEnvironment::new(elaborated_env);
// FIXME: It's very weird that we ignore region obligations but apparently // FIXME: It's very weird that we ignore region obligations but apparently
// still need to use `resolve_regions` as we need the resolved regions in // still need to use `resolve_regions` as we need the resolved regions in
// the normalized predicates. // the normalized predicates.
let errors = infcx.resolve_regions(&outlives_env); let errors = infcx.resolve_regions(cause.body_id, elaborated_env, []);
if !errors.is_empty() { if !errors.is_empty() {
tcx.dcx().span_delayed_bug( tcx.dcx().span_delayed_bug(
span, span,

View file

@ -1,4 +1,3 @@
use rustc_data_structures::fx::FxIndexSet;
use rustc_infer::infer::InferOk; use rustc_infer::infer::InferOk;
use rustc_infer::infer::resolve::OpportunisticRegionResolver; use rustc_infer::infer::resolve::OpportunisticRegionResolver;
use rustc_infer::traits::query::type_op::ImpliedOutlivesBounds; use rustc_infer::traits::query::type_op::ImpliedOutlivesBounds;
@ -12,9 +11,6 @@ use tracing::instrument;
use crate::infer::InferCtxt; use crate::infer::InferCtxt;
use crate::traits::{ObligationCause, ObligationCtxt}; use crate::traits::{ObligationCause, ObligationCtxt};
pub type BoundsCompat<'a, 'tcx: 'a> = impl Iterator<Item = OutlivesBound<'tcx>> + 'a;
pub type Bounds<'a, 'tcx: 'a> = impl Iterator<Item = OutlivesBound<'tcx>> + 'a;
/// Implied bounds are region relationships that we deduce /// Implied bounds are region relationships that we deduce
/// automatically. The idea is that (e.g.) a caller must check that a /// automatically. The idea is that (e.g.) a caller must check that a
/// function's argument types are well-formed immediately before /// function's argument types are well-formed immediately before
@ -110,36 +106,18 @@ fn implied_outlives_bounds<'a, 'tcx>(
bounds bounds
} }
#[extension(pub trait InferCtxtExt<'a, 'tcx>)] #[extension(pub trait InferCtxtExt<'tcx>)]
impl<'a, 'tcx: 'a> InferCtxt<'tcx> { impl<'tcx> InferCtxt<'tcx> {
/// Do *NOT* call this directly. /// Do *NOT* call this directly. You probably want to construct a `OutlivesEnvironment`
fn implied_bounds_tys_compat( /// instead if you're interested in the implied bounds for a given signature.
&'a self, fn implied_bounds_tys_with_compat<Tys: IntoIterator<Item = Ty<'tcx>>>(
param_env: ParamEnv<'tcx>, &self,
body_id: LocalDefId, body_id: LocalDefId,
tys: &'a FxIndexSet<Ty<'tcx>>, param_env: ParamEnv<'tcx>,
tys: Tys,
compat: bool, compat: bool,
) -> BoundsCompat<'a, 'tcx> { ) -> impl Iterator<Item = OutlivesBound<'tcx>> {
tys.iter() tys.into_iter()
.flat_map(move |ty| implied_outlives_bounds(self, param_env, body_id, *ty, compat)) .flat_map(move |ty| implied_outlives_bounds(self, param_env, body_id, ty, compat))
}
/// If `-Z no-implied-bounds-compat` is set, calls `implied_bounds_tys_compat`
/// with `compat` set to `true`, otherwise `false`.
fn implied_bounds_tys(
&'a self,
param_env: ParamEnv<'tcx>,
body_id: LocalDefId,
tys: &'a FxIndexSet<Ty<'tcx>>,
) -> Bounds<'a, 'tcx> {
tys.iter().flat_map(move |ty| {
implied_outlives_bounds(
self,
param_env,
body_id,
*ty,
!self.tcx.sess.opts.unstable_opts.no_implied_bounds_compat,
)
})
} }
} }

View file

@ -40,7 +40,7 @@ requirements of impls and functions as explicit predicates.
### using implicit implied bounds as assumptions ### using implicit implied bounds as assumptions
These bounds are not added to the `ParamEnv` of the affected item itself. For lexical These bounds are not added to the `ParamEnv` of the affected item itself. For lexical
region resolution they are added using [`fn OutlivesEnvironment::with_bounds`]. region resolution they are added using [`fn OutlivesEnvironment::new`].
Similarly, during MIR borrowck we add them using Similarly, during MIR borrowck we add them using
[`fn UniversalRegionRelationsBuilder::add_implied_bounds`]. [`fn UniversalRegionRelationsBuilder::add_implied_bounds`].
@ -55,7 +55,7 @@ The assumed outlives constraints for implicit bounds are computed using the
MIR borrowck adds the outlives constraints for both the normalized and unnormalized types, MIR borrowck adds the outlives constraints for both the normalized and unnormalized types,
lexical region resolution [only uses the unnormalized types][notnorm]. lexical region resolution [only uses the unnormalized types][notnorm].
[`fn OutlivesEnvironment::with_bounds`]: https://github.com/rust-lang/rust/blob/5b8bc568d28b2e922290c9a966b3231d0ce9398b/compiler/rustc_infer/src/infer/outlives/env.rs#L90-L97 [`fn OutlivesEnvironment::new`]: TODO
[`fn UniversalRegionRelationsBuilder::add_implied_bounds`]: https://github.com/rust-lang/rust/blob/5b8bc568d28b2e922290c9a966b3231d0ce9398b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs#L316 [`fn UniversalRegionRelationsBuilder::add_implied_bounds`]: https://github.com/rust-lang/rust/blob/5b8bc568d28b2e922290c9a966b3231d0ce9398b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs#L316
[mir]: https://github.com/rust-lang/rust/blob/91cae1dcdcf1a31bd8a92e4a63793d65cfe289bb/compiler/rustc_borrowck/src/type_check/free_region_relations.rs#L258-L332 [mir]: https://github.com/rust-lang/rust/blob/91cae1dcdcf1a31bd8a92e4a63793d65cfe289bb/compiler/rustc_borrowck/src/type_check/free_region_relations.rs#L258-L332
[`fn assumed_wf_types`]: https://github.com/rust-lang/rust/blob/5b8bc568d28b2e922290c9a966b3231d0ce9398b/compiler/rustc_ty_utils/src/implied_bounds.rs#L21 [`fn assumed_wf_types`]: https://github.com/rust-lang/rust/blob/5b8bc568d28b2e922290c9a966b3231d0ce9398b/compiler/rustc_ty_utils/src/implied_bounds.rs#L21