Extract ImplSubject information

This commit is contained in:
Santiago Pastorino 2022-03-20 00:12:03 -03:00
parent 91b52148eb
commit 0cd03c917c
No known key found for this signature in database
GPG key ID: 8131A24E0C79EFAF
3 changed files with 50 additions and 37 deletions

View file

@ -7,10 +7,10 @@ pub mod nested_filter;
pub mod place; pub mod place;
use crate::ty::query::Providers; use crate::ty::query::Providers;
use crate::ty::TyCtxt; use crate::ty::{ImplSubject, TyCtxt};
use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::*; use rustc_hir::*;
use rustc_query_system::ich::StableHashingContext; use rustc_query_system::ich::StableHashingContext;
use rustc_span::DUMMY_SP; use rustc_span::DUMMY_SP;
@ -54,6 +54,12 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn parent_module(self, id: HirId) -> LocalDefId { pub fn parent_module(self, id: HirId) -> LocalDefId {
self.parent_module_from_def_id(id.owner) self.parent_module_from_def_id(id.owner)
} }
pub fn impl_header(self, def_id: DefId) -> ImplSubject<'tcx> {
self.impl_trait_ref(def_id)
.map(ImplSubject::Trait)
.unwrap_or_else(|| ImplSubject::Inherent(self.type_of(def_id)))
}
} }
pub fn provide(providers: &mut Providers) { pub fn provide(providers: &mut Providers) {

View file

@ -172,6 +172,12 @@ pub struct ImplHeader<'tcx> {
pub predicates: Vec<Predicate<'tcx>>, pub predicates: Vec<Predicate<'tcx>>,
} }
#[derive(Debug)]
pub enum ImplSubject<'tcx> {
Trait(TraitRef<'tcx>),
Inherent(Ty<'tcx>),
}
#[derive( #[derive(
Copy, Copy,
Clone, Clone,

View file

@ -24,7 +24,7 @@ use rustc_middle::traits::specialization_graph::OverlapMode;
use rustc_middle::ty::fast_reject::{self, TreatParams}; use rustc_middle::ty::fast_reject::{self, TreatParams};
use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::Subst; use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt};
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
use rustc_span::DUMMY_SP; use rustc_span::DUMMY_SP;
use std::fmt::Debug; use std::fmt::Debug;
@ -307,46 +307,47 @@ fn negative_impl<'cx, 'tcx>(
// create a parameter environment corresponding to a (placeholder) instantiation of impl1 // create a parameter environment corresponding to a (placeholder) instantiation of impl1
let impl1_env = tcx.param_env(impl1_def_id); let impl1_env = tcx.param_env(impl1_def_id);
if let Some(impl1_trait_ref) = tcx.impl_trait_ref(impl1_def_id) { match tcx.impl_header(impl1_def_id) {
// Normalize the trait reference. The WF rules ought to ensure ImplSubject::Trait(impl1_trait_ref) => {
// that this always succeeds. // Normalize the trait reference. The WF rules ought to ensure
let impl1_trait_ref = match traits::fully_normalize( // that this always succeeds.
&infcx, let impl1_trait_ref = match traits::fully_normalize(
FulfillmentContext::new(), &infcx,
ObligationCause::dummy(), FulfillmentContext::new(),
impl1_env, ObligationCause::dummy(),
impl1_trait_ref, impl1_env,
) { impl1_trait_ref,
Ok(impl1_trait_ref) => impl1_trait_ref, ) {
Err(err) => { Ok(impl1_trait_ref) => impl1_trait_ref,
bug!("failed to fully normalize {:?}: {:?}", impl1_trait_ref, err); Err(err) => {
} bug!("failed to fully normalize {:?}: {:?}", impl1_trait_ref, err);
}; }
};
// Attempt to prove that impl2 applies, given all of the above. // Attempt to prove that impl2 applies, given all of the above.
let selcx = &mut SelectionContext::new(&infcx); let selcx = &mut SelectionContext::new(&infcx);
let impl2_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl2_def_id); let impl2_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl2_def_id);
let (impl2_trait_ref, obligations) = let (impl2_trait_ref, obligations) =
impl_trait_ref_and_oblig(selcx, impl1_env, impl2_def_id, impl2_substs); impl_trait_ref_and_oblig(selcx, impl1_env, impl2_def_id, impl2_substs);
!obligations_satisfiable( !equate(
&infcx, &infcx,
impl1_env, impl1_env,
impl1_def_id, impl1_def_id,
impl1_trait_ref, impl1_trait_ref,
impl2_trait_ref, impl2_trait_ref,
obligations, obligations,
) )
} else { }
let ty1 = tcx.type_of(impl1_def_id); ImplSubject::Inherent(ty1) => {
let ty2 = tcx.type_of(impl2_def_id); let ty2 = tcx.type_of(impl2_def_id);
!equate(&infcx, impl1_env, impl1_def_id, ty1, ty2, iter::empty())
!obligations_satisfiable(&infcx, impl1_env, impl1_def_id, ty1, ty2, iter::empty()) }
} }
}) })
} }
fn obligations_satisfiable<'cx, 'tcx, T: Debug + ToTrace<'tcx>>( fn equate<'cx, 'tcx, T: Debug + ToTrace<'tcx>>(
infcx: &InferCtxt<'cx, 'tcx>, infcx: &InferCtxt<'cx, 'tcx>,
impl1_env: ty::ParamEnv<'tcx>, impl1_env: ty::ParamEnv<'tcx>,
impl1_def_id: DefId, impl1_def_id: DefId,