Sync Instance::resolve with the projection code
This commit is contained in:
parent
103771ce57
commit
e8910f51d8
4 changed files with 39 additions and 52 deletions
|
|
@ -54,7 +54,6 @@ pub use self::project::{
|
|||
};
|
||||
pub use self::select::{EvaluationCache, SelectionCache, SelectionContext};
|
||||
pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
|
||||
pub use self::specialize::find_associated_item;
|
||||
pub use self::specialize::specialization_graph::FutureCompatOverlapError;
|
||||
pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
|
||||
pub use self::specialize::{specialization_graph, translate_substs, OverlapError};
|
||||
|
|
|
|||
|
|
@ -1016,7 +1016,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
|
|||
.map_err(|ErrorReported| ())?;
|
||||
|
||||
if node_item.is_final() {
|
||||
// Non-specializable items are always projectable
|
||||
// Non-specializable items are always projectable.
|
||||
true
|
||||
} else {
|
||||
// Only reveal a specializable default if we're past type-checking
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ use rustc_errors::struct_span_err;
|
|||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::lint::LintDiagnosticBuilder;
|
||||
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
|
||||
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
|
||||
use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
|
||||
use rustc_span::DUMMY_SP;
|
||||
|
|
@ -112,48 +112,6 @@ pub fn translate_substs<'a, 'tcx>(
|
|||
source_substs.rebase_onto(infcx.tcx, source_impl, target_substs)
|
||||
}
|
||||
|
||||
/// Given a selected impl described by `impl_data`, returns the
|
||||
/// definition and substitutions for the method with the name `name`
|
||||
/// the kind `kind`, and trait method substitutions `substs`, in
|
||||
/// that impl, a less specialized impl, or the trait default,
|
||||
/// whichever applies.
|
||||
pub fn find_associated_item<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
item: &ty::AssocItem,
|
||||
substs: SubstsRef<'tcx>,
|
||||
impl_data: &super::VtableImplData<'tcx, ()>,
|
||||
) -> (DefId, SubstsRef<'tcx>) {
|
||||
debug!("find_associated_item({:?}, {:?}, {:?}, {:?})", param_env, item, substs, impl_data);
|
||||
assert!(!substs.needs_infer());
|
||||
|
||||
let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap();
|
||||
let trait_def = tcx.trait_def(trait_def_id);
|
||||
|
||||
if let Ok(ancestors) = trait_def.ancestors(tcx, impl_data.impl_def_id) {
|
||||
match ancestors.leaf_def(tcx, item.ident, item.kind) {
|
||||
Some(node_item) => {
|
||||
let substs = tcx.infer_ctxt().enter(|infcx| {
|
||||
let param_env = param_env.with_reveal_all();
|
||||
let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
|
||||
let substs = translate_substs(
|
||||
&infcx,
|
||||
param_env,
|
||||
impl_data.impl_def_id,
|
||||
substs,
|
||||
node_item.defining_node,
|
||||
);
|
||||
infcx.tcx.erase_regions(&substs)
|
||||
});
|
||||
(node_item.item.def_id, substs)
|
||||
}
|
||||
None => bug!("{:?} not found in {:?}", item, impl_data.impl_def_id),
|
||||
}
|
||||
} else {
|
||||
(item.def_id, substs)
|
||||
}
|
||||
}
|
||||
|
||||
/// Is `impl1` a specialization of `impl2`?
|
||||
///
|
||||
/// Specialization is determined by the sets of types to which the impls apply;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::ty::subst::SubstsRef;
|
||||
use rustc_middle::ty::{self, Instance, TyCtxt, TypeFoldable};
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_span::sym;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use rustc_trait_selection::traits;
|
||||
use traits::{Reveal, translate_substs};
|
||||
|
||||
use log::debug;
|
||||
|
||||
|
|
@ -82,21 +84,49 @@ fn resolve_associated_item<'tcx>(
|
|||
// the actual function:
|
||||
match vtbl {
|
||||
traits::VtableImpl(impl_data) => {
|
||||
let (def_id, substs) =
|
||||
traits::find_associated_item(tcx, param_env, trait_item, rcvr_substs, &impl_data);
|
||||
debug!(
|
||||
"resolving VtableImpl: {:?}, {:?}, {:?}, {:?}",
|
||||
param_env, trait_item, rcvr_substs, impl_data
|
||||
);
|
||||
assert!(!rcvr_substs.needs_infer());
|
||||
|
||||
let resolved_item = tcx.associated_item(def_id);
|
||||
let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap();
|
||||
let trait_def = tcx.trait_def(trait_def_id);
|
||||
let leaf_def = trait_def
|
||||
.ancestors(tcx, impl_data.impl_def_id)
|
||||
.ok()?
|
||||
.leaf_def(tcx, trait_item.ident, trait_item.kind)
|
||||
.unwrap_or_else(|| {
|
||||
bug!("{:?} not found in {:?}", trait_item, impl_data.impl_def_id);
|
||||
});
|
||||
let def_id = leaf_def.item.def_id;
|
||||
|
||||
let substs = tcx.infer_ctxt().enter(|infcx| {
|
||||
let param_env = param_env.with_reveal_all();
|
||||
let substs = rcvr_substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
|
||||
let substs = translate_substs(
|
||||
&infcx,
|
||||
param_env,
|
||||
impl_data.impl_def_id,
|
||||
substs,
|
||||
leaf_def.defining_node,
|
||||
);
|
||||
infcx.tcx.erase_regions(&substs)
|
||||
});
|
||||
|
||||
// Since this is a trait item, we need to see if the item is either a trait default item
|
||||
// or a specialization because we can't resolve those unless we can `Reveal::All`.
|
||||
// NOTE: This should be kept in sync with the similar code in
|
||||
// `rustc_middle::traits::project::assemble_candidates_from_impls()`.
|
||||
let eligible = if !resolved_item.defaultness.is_default() {
|
||||
let eligible = if leaf_def.is_final() {
|
||||
// Non-specializable items are always projectable.
|
||||
true
|
||||
} else if param_env.reveal == traits::Reveal::All {
|
||||
!trait_ref.needs_subst()
|
||||
} else {
|
||||
false
|
||||
// Only reveal a specializable default if we're past type-checking
|
||||
// and the obligation is monomorphic, otherwise passes such as
|
||||
// transmute checking and polymorphic MIR optimizations could
|
||||
// get a result which isn't correct for all monomorphizations.
|
||||
if param_env.reveal == Reveal::All { !trait_ref.needs_subst() } else { false }
|
||||
};
|
||||
|
||||
if !eligible {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue