1
Fork 0

Relate binders explicitly, do a leak check too

This commit is contained in:
Michael Goulet 2024-09-30 12:42:29 -04:00
parent eb75d20a55
commit cbb5047d35
2 changed files with 47 additions and 15 deletions

View file

@ -27,7 +27,8 @@ use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType};
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
use rustc_span::{DUMMY_SP, Symbol}; use rustc_span::{DUMMY_SP, Symbol};
use rustc_target::abi::FIRST_VARIANT; use rustc_target::abi::FIRST_VARIANT;
use rustc_trait_selection::infer::TyCtxtInferExt; use rustc_trait_selection::infer::at::ToTrace;
use rustc_trait_selection::infer::{BoundRegionConversionTime, TyCtxtInferExt};
use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt}; use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
use tracing::{debug, info}; use tracing::{debug, info};
@ -113,22 +114,38 @@ pub fn compare_simd_types<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
/// unsound, so let's validate here that the trait refs are subtypes. /// unsound, so let's validate here that the trait refs are subtypes.
pub fn validate_trivial_unsize<'tcx>( pub fn validate_trivial_unsize<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
data_a: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>, source_data: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
data_b: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>, target_data: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
) -> bool { ) -> bool {
match (data_a.principal(), data_b.principal()) { match (source_data.principal(), target_data.principal()) {
(Some(principal_a), Some(principal_b)) => { (Some(hr_source_principal), Some(hr_target_principal)) => {
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build();
let universe = infcx.universe();
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new(&infcx);
let Ok(()) = ocx.sub( infcx.enter_forall(hr_target_principal, |target_principal| {
let source_principal = infcx.instantiate_binder_with_fresh_vars(
DUMMY_SP,
BoundRegionConversionTime::HigherRankedType,
hr_source_principal,
);
let Ok(()) = ocx.eq_trace(
&ObligationCause::dummy(), &ObligationCause::dummy(),
ty::ParamEnv::reveal_all(), ty::ParamEnv::reveal_all(),
principal_a, ToTrace::to_trace(
principal_b, &ObligationCause::dummy(),
hr_target_principal,
hr_source_principal,
),
target_principal,
source_principal,
) else { ) else {
return false; return false;
}; };
ocx.select_all_or_error().is_empty() if !ocx.select_all_or_error().is_empty() {
return false;
}
infcx.leak_check(universe, None).is_ok()
})
} }
(None, None) => true, (None, None) => true,
_ => false, _ => false,

View file

@ -9,12 +9,13 @@ use rustc_infer::infer::canonical::{
Canonical, CanonicalQueryResponse, CanonicalVarValues, QueryResponse, Canonical, CanonicalQueryResponse, CanonicalVarValues, QueryResponse,
}; };
use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk, RegionResolutionError}; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk, RegionResolutionError, TypeTrace};
use rustc_macros::extension; use rustc_macros::extension;
use rustc_middle::arena::ArenaAllocatable; use rustc_middle::arena::ArenaAllocatable;
use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::error::TypeError; use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, Upcast, Variance}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, Upcast, Variance};
use rustc_type_ir::relate::Relate;
use super::{FromSolverError, FulfillmentContext, ScrubbedTraitError, TraitEngine}; use super::{FromSolverError, FulfillmentContext, ScrubbedTraitError, TraitEngine};
use crate::error_reporting::InferCtxtErrorExt; use crate::error_reporting::InferCtxtErrorExt;
@ -133,6 +134,20 @@ where
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) .map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
} }
pub fn eq_trace<T: Relate<TyCtxt<'tcx>>>(
&self,
cause: &ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
trace: TypeTrace<'tcx>,
expected: T,
actual: T,
) -> Result<(), TypeError<'tcx>> {
self.infcx
.at(cause, param_env)
.eq_trace(DefineOpaqueTypes::Yes, trace, expected, actual)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
}
/// Checks whether `expected` is a subtype of `actual`: `expected <: actual`. /// Checks whether `expected` is a subtype of `actual`: `expected <: actual`.
pub fn sub<T: ToTrace<'tcx>>( pub fn sub<T: ToTrace<'tcx>>(
&self, &self,