Add query to avoid name comparison in leaf_def
This commit is contained in:
parent
1b057a33bd
commit
3b7d496f72
8 changed files with 114 additions and 89 deletions
|
@ -630,6 +630,32 @@ rustc_queries! {
|
||||||
desc { |tcx| "collecting associated items of {}", tcx.def_path_str(key) }
|
desc { |tcx| "collecting associated items of {}", tcx.def_path_str(key) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Maps from associated items on a trait to the corresponding associated
|
||||||
|
/// item on the impl specified by `impl_id`.
|
||||||
|
///
|
||||||
|
/// For example, with the following code
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// struct Type {}
|
||||||
|
/// // DefId
|
||||||
|
/// trait Trait { // trait_id
|
||||||
|
/// fn f(); // trait_f
|
||||||
|
/// fn g() {} // trait_g
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// impl Trait for Type { // impl_id
|
||||||
|
/// fn f() {} // impl_f
|
||||||
|
/// fn g() {} // impl_g
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// The map returned for `tcx.impl_item_implementor_ids(impl_id)` would be
|
||||||
|
///`{ trait_f: impl_f, trait_g: impl_g }`
|
||||||
|
query impl_item_implementor_ids(impl_id: DefId) -> FxHashMap<DefId, DefId> {
|
||||||
|
desc { |tcx| "comparing impl items against trait for {}", tcx.def_path_str(impl_id) }
|
||||||
|
storage(ArenaCacheSelector<'tcx>)
|
||||||
|
}
|
||||||
|
|
||||||
/// Given an `impl_id`, return the trait it implements.
|
/// Given an `impl_id`, return the trait it implements.
|
||||||
/// Return `None` if this is an inherent impl.
|
/// Return `None` if this is an inherent impl.
|
||||||
query impl_trait_ref(impl_id: DefId) -> Option<ty::TraitRef<'tcx>> {
|
query impl_trait_ref(impl_id: DefId) -> Option<ty::TraitRef<'tcx>> {
|
||||||
|
|
|
@ -4,7 +4,6 @@ use crate::ty::{self, TyCtxt};
|
||||||
use rustc_data_structures::fx::FxIndexMap;
|
use rustc_data_structures::fx::FxIndexMap;
|
||||||
use rustc_errors::ErrorReported;
|
use rustc_errors::ErrorReported;
|
||||||
use rustc_hir::def_id::{DefId, DefIdMap};
|
use rustc_hir::def_id::{DefId, DefIdMap};
|
||||||
use rustc_span::symbol::Ident;
|
|
||||||
|
|
||||||
/// A per-trait graph of impls in specialization order. At the moment, this
|
/// A per-trait graph of impls in specialization order. At the moment, this
|
||||||
/// graph forms a tree rooted with the trait itself, with all other nodes
|
/// graph forms a tree rooted with the trait itself, with all other nodes
|
||||||
|
@ -75,34 +74,28 @@ pub enum Node {
|
||||||
Trait(DefId),
|
Trait(DefId),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Node {
|
impl Node {
|
||||||
pub fn is_from_trait(&self) -> bool {
|
pub fn is_from_trait(&self) -> bool {
|
||||||
matches!(self, Node::Trait(..))
|
matches!(self, Node::Trait(..))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over the items defined directly by the given (impl or trait) node.
|
/// Trys to find the associated item that implements `trait_item_def_id`
|
||||||
pub fn items(&self, tcx: TyCtxt<'tcx>) -> impl 'tcx + Iterator<Item = &'tcx ty::AssocItem> {
|
/// defined in this node.
|
||||||
tcx.associated_items(self.def_id()).in_definition_order()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Finds an associated item defined in this node.
|
|
||||||
///
|
///
|
||||||
/// If this returns `None`, the item can potentially still be found in
|
/// If this returns `None`, the item can potentially still be found in
|
||||||
/// parents of this node.
|
/// parents of this node.
|
||||||
pub fn item(
|
pub fn item<'tcx>(
|
||||||
&self,
|
&self,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
trait_item_name: Ident,
|
trait_item_def_id: DefId,
|
||||||
trait_item_kind: ty::AssocKind,
|
) -> Option<&'tcx ty::AssocItem> {
|
||||||
trait_def_id: DefId,
|
match *self {
|
||||||
) -> Option<ty::AssocItem> {
|
Node::Trait(_) => Some(tcx.associated_item(trait_item_def_id)),
|
||||||
tcx.associated_items(self.def_id())
|
Node::Impl(impl_def_id) => {
|
||||||
.filter_by_name_unhygienic(trait_item_name.name)
|
let id = tcx.impl_item_implementor_ids(impl_def_id).get(&trait_item_def_id)?;
|
||||||
.find(move |impl_item| {
|
Some(tcx.associated_item(*id))
|
||||||
trait_item_kind == impl_item.kind
|
}
|
||||||
&& tcx.hygienic_eq(impl_item.ident, trait_item_name, trait_def_id)
|
}
|
||||||
})
|
|
||||||
.copied()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn def_id(&self) -> DefId {
|
pub fn def_id(&self) -> DefId {
|
||||||
|
@ -181,17 +174,11 @@ impl LeafDef {
|
||||||
impl<'tcx> Ancestors<'tcx> {
|
impl<'tcx> Ancestors<'tcx> {
|
||||||
/// Finds the bottom-most (ie. most specialized) definition of an associated
|
/// Finds the bottom-most (ie. most specialized) definition of an associated
|
||||||
/// item.
|
/// item.
|
||||||
pub fn leaf_def(
|
pub fn leaf_def(mut self, tcx: TyCtxt<'tcx>, trait_item_def_id: DefId) -> Option<LeafDef> {
|
||||||
mut self,
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
trait_item_name: Ident,
|
|
||||||
trait_item_kind: ty::AssocKind,
|
|
||||||
) -> Option<LeafDef> {
|
|
||||||
let trait_def_id = self.trait_def_id;
|
|
||||||
let mut finalizing_node = None;
|
let mut finalizing_node = None;
|
||||||
|
|
||||||
self.find_map(|node| {
|
self.find_map(|node| {
|
||||||
if let Some(item) = node.item(tcx, trait_item_name, trait_item_kind, trait_def_id) {
|
if let Some(item) = node.item(tcx, trait_item_def_id) {
|
||||||
if finalizing_node.is_none() {
|
if finalizing_node.is_none() {
|
||||||
let is_specializable = item.defaultness.is_default()
|
let is_specializable = item.defaultness.is_default()
|
||||||
|| tcx.impl_defaultness(node.def_id()).is_default();
|
|| tcx.impl_defaultness(node.def_id()).is_default();
|
||||||
|
@ -201,7 +188,7 @@ impl<'tcx> Ancestors<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(LeafDef { item, defining_node: node, finalizing_node })
|
Some(LeafDef { item: *item, defining_node: node, finalizing_node })
|
||||||
} else {
|
} else {
|
||||||
// Item not mentioned. This "finalizes" any defaulted item provided by an ancestor.
|
// Item not mentioned. This "finalizes" any defaulted item provided by an ancestor.
|
||||||
finalizing_node = Some(node);
|
finalizing_node = Some(node);
|
||||||
|
|
|
@ -1310,10 +1310,9 @@ fn create_mono_items_for_default_impls<'tcx>(
|
||||||
if let Some(trait_ref) = tcx.impl_trait_ref(item.def_id) {
|
if let Some(trait_ref) = tcx.impl_trait_ref(item.def_id) {
|
||||||
let param_env = ty::ParamEnv::reveal_all();
|
let param_env = ty::ParamEnv::reveal_all();
|
||||||
let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref);
|
let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref);
|
||||||
let overridden_methods: FxHashSet<_> =
|
let overridden_methods = tcx.impl_item_implementor_ids(item.def_id);
|
||||||
impl_.items.iter().map(|iiref| iiref.ident.normalize_to_macros_2_0()).collect();
|
|
||||||
for method in tcx.provided_trait_methods(trait_ref.def_id) {
|
for method in tcx.provided_trait_methods(trait_ref.def_id) {
|
||||||
if overridden_methods.contains(&method.ident.normalize_to_macros_2_0()) {
|
if overridden_methods.contains_key(&method.def_id) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,26 +93,29 @@ impl<'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for CheckConstTraitVisitor<
|
||||||
for trait_item in self.tcx.associated_items(trait_def_id).in_definition_order()
|
for trait_item in self.tcx.associated_items(trait_def_id).in_definition_order()
|
||||||
{
|
{
|
||||||
if let ty::AssocItem {
|
if let ty::AssocItem {
|
||||||
kind: ty::AssocKind::Fn, ident, defaultness, ..
|
kind: ty::AssocKind::Fn,
|
||||||
} = trait_item
|
defaultness,
|
||||||
|
def_id: trait_item_id,
|
||||||
|
..
|
||||||
|
} = *trait_item
|
||||||
{
|
{
|
||||||
// we can ignore functions that do not have default bodies:
|
// we can ignore functions that do not have default bodies:
|
||||||
// if those are unimplemented it will be catched by typeck.
|
// if those are unimplemented it will be catched by typeck.
|
||||||
if !defaultness.has_value()
|
if !defaultness.has_value()
|
||||||
|| self
|
|| self
|
||||||
.tcx
|
.tcx
|
||||||
.has_attr(trait_item.def_id, sym::default_method_body_is_const)
|
.has_attr(trait_item_id, sym::default_method_body_is_const)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_implemented = ancestors
|
let is_implemented = ancestors
|
||||||
.leaf_def(self.tcx, trait_item.ident, trait_item.kind)
|
.leaf_def(self.tcx, trait_item_id)
|
||||||
.map(|node_item| !node_item.defining_node.is_from_trait())
|
.map(|node_item| !node_item.defining_node.is_from_trait())
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
|
||||||
if !is_implemented {
|
if !is_implemented {
|
||||||
to_implement.push(ident.to_string());
|
to_implement.push(self.tcx.item_name(trait_item_id).to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1883,7 +1883,6 @@ fn assoc_ty_def(
|
||||||
assoc_ty_def_id: DefId,
|
assoc_ty_def_id: DefId,
|
||||||
) -> Result<specialization_graph::LeafDef, ErrorReported> {
|
) -> Result<specialization_graph::LeafDef, ErrorReported> {
|
||||||
let tcx = selcx.tcx();
|
let tcx = selcx.tcx();
|
||||||
let assoc_ty_name = tcx.associated_item(assoc_ty_def_id).ident;
|
|
||||||
let trait_def_id = tcx.impl_trait_ref(impl_def_id).unwrap().def_id;
|
let trait_def_id = tcx.impl_trait_ref(impl_def_id).unwrap().def_id;
|
||||||
let trait_def = tcx.trait_def(trait_def_id);
|
let trait_def = tcx.trait_def(trait_def_id);
|
||||||
|
|
||||||
|
@ -1893,21 +1892,18 @@ fn assoc_ty_def(
|
||||||
// for the associated item at the given impl.
|
// for the associated item at the given impl.
|
||||||
// If there is no such item in that impl, this function will fail with a
|
// If there is no such item in that impl, this function will fail with a
|
||||||
// cycle error if the specialization graph is currently being built.
|
// cycle error if the specialization graph is currently being built.
|
||||||
let impl_node = specialization_graph::Node::Impl(impl_def_id);
|
if let Some(&impl_item_id) = tcx.impl_item_implementor_ids(impl_def_id).get(&assoc_ty_def_id) {
|
||||||
for item in impl_node.items(tcx) {
|
let item = tcx.associated_item(impl_item_id);
|
||||||
if matches!(item.kind, ty::AssocKind::Type)
|
let impl_node = specialization_graph::Node::Impl(impl_def_id);
|
||||||
&& tcx.hygienic_eq(item.ident, assoc_ty_name, trait_def_id)
|
return Ok(specialization_graph::LeafDef {
|
||||||
{
|
item: *item,
|
||||||
return Ok(specialization_graph::LeafDef {
|
defining_node: impl_node,
|
||||||
item: *item,
|
finalizing_node: if item.defaultness.is_default() { None } else { Some(impl_node) },
|
||||||
defining_node: impl_node,
|
});
|
||||||
finalizing_node: if item.defaultness.is_default() { None } else { Some(impl_node) },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let ancestors = trait_def.ancestors(tcx, impl_def_id)?;
|
let ancestors = trait_def.ancestors(tcx, impl_def_id)?;
|
||||||
if let Some(assoc_item) = ancestors.leaf_def(tcx, assoc_ty_name, ty::AssocKind::Type) {
|
if let Some(assoc_item) = ancestors.leaf_def(tcx, assoc_ty_def_id) {
|
||||||
Ok(assoc_item)
|
Ok(assoc_item)
|
||||||
} else {
|
} else {
|
||||||
// This is saying that neither the trait nor
|
// This is saying that neither the trait nor
|
||||||
|
@ -1916,7 +1912,11 @@ fn assoc_ty_def(
|
||||||
// could only arise through a compiler bug --
|
// could only arise through a compiler bug --
|
||||||
// if the user wrote a bad item name, it
|
// if the user wrote a bad item name, it
|
||||||
// should have failed in astconv.
|
// should have failed in astconv.
|
||||||
bug!("No associated type `{}` for {}", assoc_ty_name, tcx.def_path_str(impl_def_id))
|
bug!(
|
||||||
|
"No associated type `{}` for {}",
|
||||||
|
tcx.item_name(assoc_ty_def_id),
|
||||||
|
tcx.def_path_str(impl_def_id)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -197,14 +197,13 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
|
||||||
item: Option<&hir::Item<'tcx>>,
|
item: Option<&hir::Item<'tcx>>,
|
||||||
cause: &mut traits::ObligationCause<'tcx>,
|
cause: &mut traits::ObligationCause<'tcx>,
|
||||||
pred: &ty::Predicate<'tcx>,
|
pred: &ty::Predicate<'tcx>,
|
||||||
mut trait_assoc_items: impl Iterator<Item = &'tcx ty::AssocItem>,
|
|
||||||
) {
|
) {
|
||||||
debug!(
|
debug!(
|
||||||
"extended_cause_with_original_assoc_item_obligation {:?} {:?} {:?} {:?}",
|
"extended_cause_with_original_assoc_item_obligation {:?} {:?} {:?} {:?}",
|
||||||
trait_ref, item, cause, pred
|
trait_ref, item, cause, pred
|
||||||
);
|
);
|
||||||
let items = match item {
|
let (items, impl_def_id) = match item {
|
||||||
Some(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.items,
|
Some(hir::Item { kind: hir::ItemKind::Impl(impl_), def_id, .. }) => (impl_.items, *def_id),
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
let fix_span =
|
let fix_span =
|
||||||
|
@ -222,11 +221,16 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
|
||||||
// `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs` and
|
// `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs` and
|
||||||
// `traits-assoc-type-in-supertrait-bad.rs`.
|
// `traits-assoc-type-in-supertrait-bad.rs`.
|
||||||
if let ty::Projection(projection_ty) = proj.ty.kind() {
|
if let ty::Projection(projection_ty) = proj.ty.kind() {
|
||||||
let trait_assoc_item = tcx.associated_item(projection_ty.item_def_id);
|
if let Some(&impl_item_id) =
|
||||||
if let Some(impl_item_span) =
|
tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.item_def_id)
|
||||||
items.iter().find(|item| item.ident == trait_assoc_item.ident).map(fix_span)
|
|
||||||
{
|
{
|
||||||
cause.span = impl_item_span;
|
if let Some(impl_item_span) = items
|
||||||
|
.iter()
|
||||||
|
.find(|item| item.id.def_id.to_def_id() == impl_item_id)
|
||||||
|
.map(fix_span)
|
||||||
|
{
|
||||||
|
cause.span = impl_item_span;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -235,13 +239,16 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
|
||||||
// can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`.
|
// can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`.
|
||||||
debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred);
|
debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred);
|
||||||
if let ty::Projection(ty::ProjectionTy { item_def_id, .. }) = *pred.self_ty().kind() {
|
if let ty::Projection(ty::ProjectionTy { item_def_id, .. }) = *pred.self_ty().kind() {
|
||||||
if let Some(impl_item_span) = trait_assoc_items
|
if let Some(&impl_item_id) =
|
||||||
.find(|i| i.def_id == item_def_id)
|
tcx.impl_item_implementor_ids(impl_def_id).get(&item_def_id)
|
||||||
.and_then(|trait_assoc_item| {
|
|
||||||
items.iter().find(|i| i.ident == trait_assoc_item.ident).map(fix_span)
|
|
||||||
})
|
|
||||||
{
|
{
|
||||||
cause.span = impl_item_span;
|
if let Some(impl_item_span) = items
|
||||||
|
.iter()
|
||||||
|
.find(|item| item.id.def_id.to_def_id() == impl_item_id)
|
||||||
|
.map(fix_span)
|
||||||
|
{
|
||||||
|
cause.span = impl_item_span;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -312,7 +319,6 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
||||||
item,
|
item,
|
||||||
&mut cause,
|
&mut cause,
|
||||||
&obligation.predicate,
|
&obligation.predicate,
|
||||||
tcx.associated_items(trait_ref.def_id).in_definition_order(),
|
|
||||||
);
|
);
|
||||||
traits::Obligation::with_depth(cause, depth, param_env, obligation.predicate)
|
traits::Obligation::with_depth(cause, depth, param_env, obligation.predicate)
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::struct_span_err;
|
use rustc_errors::struct_span_err;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
|
@ -8,6 +9,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
|
||||||
associated_item,
|
associated_item,
|
||||||
associated_item_def_ids,
|
associated_item_def_ids,
|
||||||
associated_items,
|
associated_items,
|
||||||
|
impl_item_implementor_ids,
|
||||||
trait_of_item,
|
trait_of_item,
|
||||||
..*providers
|
..*providers
|
||||||
};
|
};
|
||||||
|
@ -32,6 +34,13 @@ fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems<'_> {
|
||||||
ty::AssocItems::new(items)
|
ty::AssocItems::new(items)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> FxHashMap<DefId, DefId> {
|
||||||
|
tcx.associated_items(impl_id)
|
||||||
|
.in_definition_order()
|
||||||
|
.filter_map(|item| item.trait_item_def_id.map(|trait_item| (trait_item, item.def_id)))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
/// If the given `DefId` describes an item belonging to a trait,
|
/// If the given `DefId` describes an item belonging to a trait,
|
||||||
/// returns the `DefId` of the trait that the trait item belongs to;
|
/// returns the `DefId` of the trait that the trait item belongs to;
|
||||||
/// otherwise, returns `None`.
|
/// otherwise, returns `None`.
|
||||||
|
|
|
@ -152,8 +152,7 @@ fn inner_resolve_instance<'tcx>(
|
||||||
|
|
||||||
let result = if let Some(trait_def_id) = tcx.trait_of_item(def.did) {
|
let result = if let Some(trait_def_id) = tcx.trait_of_item(def.did) {
|
||||||
debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env);
|
debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env);
|
||||||
let item = tcx.associated_item(def.did);
|
resolve_associated_item(tcx, def.did, param_env, trait_def_id, substs)
|
||||||
resolve_associated_item(tcx, &item, param_env, trait_def_id, substs)
|
|
||||||
} else {
|
} else {
|
||||||
let ty = tcx.type_of(def.def_id_for_type_of());
|
let ty = tcx.type_of(def.def_id_for_type_of());
|
||||||
let item_type = tcx.subst_and_normalize_erasing_regions(substs, param_env, ty);
|
let item_type = tcx.subst_and_normalize_erasing_regions(substs, param_env, ty);
|
||||||
|
@ -204,19 +203,12 @@ fn inner_resolve_instance<'tcx>(
|
||||||
|
|
||||||
fn resolve_associated_item<'tcx>(
|
fn resolve_associated_item<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
trait_item: &ty::AssocItem,
|
trait_item_id: DefId,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
trait_id: DefId,
|
trait_id: DefId,
|
||||||
rcvr_substs: SubstsRef<'tcx>,
|
rcvr_substs: SubstsRef<'tcx>,
|
||||||
) -> Result<Option<Instance<'tcx>>, ErrorReported> {
|
) -> Result<Option<Instance<'tcx>>, ErrorReported> {
|
||||||
let def_id = trait_item.def_id;
|
debug!(?trait_item_id, ?param_env, ?trait_id, ?rcvr_substs, "resolve_associated_item");
|
||||||
debug!(
|
|
||||||
"resolve_associated_item(trait_item={:?}, \
|
|
||||||
param_env={:?}, \
|
|
||||||
trait_id={:?}, \
|
|
||||||
rcvr_substs={:?})",
|
|
||||||
def_id, param_env, trait_id, rcvr_substs
|
|
||||||
);
|
|
||||||
|
|
||||||
let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
|
let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
|
||||||
|
|
||||||
|
@ -232,7 +224,7 @@ fn resolve_associated_item<'tcx>(
|
||||||
traits::ImplSource::UserDefined(impl_data) => {
|
traits::ImplSource::UserDefined(impl_data) => {
|
||||||
debug!(
|
debug!(
|
||||||
"resolving ImplSource::UserDefined: {:?}, {:?}, {:?}, {:?}",
|
"resolving ImplSource::UserDefined: {:?}, {:?}, {:?}, {:?}",
|
||||||
param_env, trait_item, rcvr_substs, impl_data
|
param_env, trait_item_id, rcvr_substs, impl_data
|
||||||
);
|
);
|
||||||
assert!(!rcvr_substs.needs_infer());
|
assert!(!rcvr_substs.needs_infer());
|
||||||
assert!(!trait_ref.needs_infer());
|
assert!(!trait_ref.needs_infer());
|
||||||
|
@ -241,9 +233,9 @@ fn resolve_associated_item<'tcx>(
|
||||||
let trait_def = tcx.trait_def(trait_def_id);
|
let trait_def = tcx.trait_def(trait_def_id);
|
||||||
let leaf_def = trait_def
|
let leaf_def = trait_def
|
||||||
.ancestors(tcx, impl_data.impl_def_id)?
|
.ancestors(tcx, impl_data.impl_def_id)?
|
||||||
.leaf_def(tcx, trait_item.ident, trait_item.kind)
|
.leaf_def(tcx, trait_item_id)
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
bug!("{:?} not found in {:?}", trait_item, impl_data.impl_def_id);
|
bug!("{:?} not found in {:?}", trait_item_id, impl_data.impl_def_id);
|
||||||
});
|
});
|
||||||
|
|
||||||
let substs = tcx.infer_ctxt().enter(|infcx| {
|
let substs = tcx.infer_ctxt().enter(|infcx| {
|
||||||
|
@ -297,22 +289,22 @@ fn resolve_associated_item<'tcx>(
|
||||||
// performs (i.e. that the definition's type in the `impl` matches
|
// performs (i.e. that the definition's type in the `impl` matches
|
||||||
// the declaration in the `trait`), so that we can cheaply check
|
// the declaration in the `trait`), so that we can cheaply check
|
||||||
// here if it failed, instead of approximating it.
|
// here if it failed, instead of approximating it.
|
||||||
if trait_item.kind == ty::AssocKind::Const
|
if leaf_def.item.kind == ty::AssocKind::Const
|
||||||
&& trait_item.def_id != leaf_def.item.def_id
|
&& trait_item_id != leaf_def.item.def_id
|
||||||
&& leaf_def.item.def_id.is_local()
|
&& leaf_def.item.def_id.is_local()
|
||||||
{
|
{
|
||||||
let normalized_type_of = |def_id, substs| {
|
let normalized_type_of = |def_id, substs| {
|
||||||
tcx.subst_and_normalize_erasing_regions(substs, param_env, tcx.type_of(def_id))
|
tcx.subst_and_normalize_erasing_regions(substs, param_env, tcx.type_of(def_id))
|
||||||
};
|
};
|
||||||
|
|
||||||
let original_ty = normalized_type_of(trait_item.def_id, rcvr_substs);
|
let original_ty = normalized_type_of(trait_item_id, rcvr_substs);
|
||||||
let resolved_ty = normalized_type_of(leaf_def.item.def_id, substs);
|
let resolved_ty = normalized_type_of(leaf_def.item.def_id, substs);
|
||||||
|
|
||||||
if original_ty != resolved_ty {
|
if original_ty != resolved_ty {
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
"Instance::resolve: inconsistent associated `const` type: \
|
"Instance::resolve: inconsistent associated `const` type: \
|
||||||
was `{}: {}` but resolved to `{}: {}`",
|
was `{}: {}` but resolved to `{}: {}`",
|
||||||
tcx.def_path_str_with_substs(trait_item.def_id, rcvr_substs),
|
tcx.def_path_str_with_substs(trait_item_id, rcvr_substs),
|
||||||
original_ty,
|
original_ty,
|
||||||
tcx.def_path_str_with_substs(leaf_def.item.def_id, substs),
|
tcx.def_path_str_with_substs(leaf_def.item.def_id, substs),
|
||||||
resolved_ty,
|
resolved_ty,
|
||||||
|
@ -343,19 +335,22 @@ fn resolve_associated_item<'tcx>(
|
||||||
}
|
}
|
||||||
traits::ImplSource::FnPointer(ref data) => match data.fn_ty.kind() {
|
traits::ImplSource::FnPointer(ref data) => match data.fn_ty.kind() {
|
||||||
ty::FnDef(..) | ty::FnPtr(..) => Some(Instance {
|
ty::FnDef(..) | ty::FnPtr(..) => Some(Instance {
|
||||||
def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty),
|
def: ty::InstanceDef::FnPtrShim(trait_item_id, data.fn_ty),
|
||||||
substs: rcvr_substs,
|
substs: rcvr_substs,
|
||||||
}),
|
}),
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
traits::ImplSource::Object(ref data) => {
|
traits::ImplSource::Object(ref data) => {
|
||||||
let index = traits::get_vtable_index_of_object_method(tcx, data, def_id);
|
let index = traits::get_vtable_index_of_object_method(tcx, data, trait_item_id);
|
||||||
Some(Instance { def: ty::InstanceDef::Virtual(def_id, index), substs: rcvr_substs })
|
Some(Instance {
|
||||||
|
def: ty::InstanceDef::Virtual(trait_item_id, index),
|
||||||
|
substs: rcvr_substs,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
traits::ImplSource::Builtin(..) => {
|
traits::ImplSource::Builtin(..) => {
|
||||||
if Some(trait_ref.def_id) == tcx.lang_items().clone_trait() {
|
if Some(trait_ref.def_id) == tcx.lang_items().clone_trait() {
|
||||||
// FIXME(eddyb) use lang items for methods instead of names.
|
// FIXME(eddyb) use lang items for methods instead of names.
|
||||||
let name = tcx.item_name(def_id);
|
let name = tcx.item_name(trait_item_id);
|
||||||
if name == sym::clone {
|
if name == sym::clone {
|
||||||
let self_ty = trait_ref.self_ty();
|
let self_ty = trait_ref.self_ty();
|
||||||
|
|
||||||
|
@ -367,7 +362,7 @@ fn resolve_associated_item<'tcx>(
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(Instance {
|
Some(Instance {
|
||||||
def: ty::InstanceDef::CloneShim(def_id, self_ty),
|
def: ty::InstanceDef::CloneShim(trait_item_id, self_ty),
|
||||||
substs: rcvr_substs,
|
substs: rcvr_substs,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
@ -375,7 +370,7 @@ fn resolve_associated_item<'tcx>(
|
||||||
|
|
||||||
// Use the default `fn clone_from` from `trait Clone`.
|
// Use the default `fn clone_from` from `trait Clone`.
|
||||||
let substs = tcx.erase_regions(rcvr_substs);
|
let substs = tcx.erase_regions(rcvr_substs);
|
||||||
Some(ty::Instance::new(def_id, substs))
|
Some(ty::Instance::new(trait_item_id, substs))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue