diff options
| author | Jonas Schievink <jonasschievink@gmail.com> | 2020-03-29 16:40:30 +0200 |
|---|---|---|
| committer | Jonas Schievink <jonasschievink@gmail.com> | 2020-03-30 19:46:15 +0200 |
| commit | e8910f51d804438b6ed161a27e21dd272d9e969a (patch) | |
| tree | f666e5dee72f050fa5b1f79eaa307fa88e814cd9 | |
| parent | 103771ce57acc240bc01abf4f7365172935bc7fb (diff) | |
| download | rust-e8910f51d804438b6ed161a27e21dd272d9e969a.tar.gz rust-e8910f51d804438b6ed161a27e21dd272d9e969a.zip | |
Sync `Instance::resolve` with the projection code
| -rw-r--r-- | src/librustc_trait_selection/traits/mod.rs | 1 | ||||
| -rw-r--r-- | src/librustc_trait_selection/traits/project.rs | 2 | ||||
| -rw-r--r-- | src/librustc_trait_selection/traits/specialize/mod.rs | 44 | ||||
| -rw-r--r-- | src/librustc_ty/instance.rs | 46 |
4 files changed, 40 insertions, 53 deletions
diff --git a/src/librustc_trait_selection/traits/mod.rs b/src/librustc_trait_selection/traits/mod.rs index d6204975a7b..5f988506330 100644 --- a/src/librustc_trait_selection/traits/mod.rs +++ b/src/librustc_trait_selection/traits/mod.rs @@ -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}; diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs index cd89111a177..aae0d467563 100644 --- a/src/librustc_trait_selection/traits/project.rs +++ b/src/librustc_trait_selection/traits/project.rs @@ -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 diff --git a/src/librustc_trait_selection/traits/specialize/mod.rs b/src/librustc_trait_selection/traits/specialize/mod.rs index f98d8f2fabf..fabd8c89b72 100644 --- a/src/librustc_trait_selection/traits/specialize/mod.rs +++ b/src/librustc_trait_selection/traits/specialize/mod.rs @@ -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; diff --git a/src/librustc_ty/instance.rs b/src/librustc_ty/instance.rs index 447c49e40fb..2b7d7e7e637 100644 --- a/src/librustc_ty/instance.rs +++ b/src/librustc_ty/instance.rs @@ -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); - - let resolved_item = tcx.associated_item(def_id); + debug!( + "resolving VtableImpl: {:?}, {:?}, {:?}, {:?}", + param_env, trait_item, rcvr_substs, impl_data + ); + assert!(!rcvr_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); + 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 { |
