Add trait_item_def_id
to AssocItem
This allows avoiding some lookups by name
This commit is contained in:
parent
0b1ab91d66
commit
d7595853a2
11 changed files with 197 additions and 204 deletions
|
@ -1008,6 +1008,10 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
|||
self.get_impl_data(id).constness
|
||||
}
|
||||
|
||||
fn get_trait_item_def_id(&self, id: DefIndex) -> Option<DefId> {
|
||||
self.root.tables.trait_item_def_id.get(self, id).map(|d| d.decode(self))
|
||||
}
|
||||
|
||||
fn get_coerce_unsized_info(&self, id: DefIndex) -> Option<ty::adjustment::CoerceUnsizedInfo> {
|
||||
self.get_impl_data(id).coerce_unsized_info
|
||||
}
|
||||
|
@ -1289,6 +1293,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
|||
vis: self.get_visibility(id),
|
||||
defaultness: container.defaultness(),
|
||||
def_id: self.local_def_id(id),
|
||||
trait_item_def_id: self.get_trait_item_def_id(id),
|
||||
container: container.with_def_id(parent),
|
||||
fn_has_self_parameter: has_self,
|
||||
}
|
||||
|
|
|
@ -1294,6 +1294,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
}
|
||||
self.encode_ident_span(def_id, impl_item.ident);
|
||||
self.encode_item_type(def_id);
|
||||
if let Some(trait_item_def_id) = impl_item.trait_item_def_id {
|
||||
record!(self.tables.trait_item_def_id[def_id] <- trait_item_def_id);
|
||||
}
|
||||
if impl_item.kind == ty::AssocKind::Fn {
|
||||
record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
|
||||
}
|
||||
|
|
|
@ -302,6 +302,7 @@ define_tables! {
|
|||
ty: Table<DefIndex, Lazy!(Ty<'tcx>)>,
|
||||
fn_sig: Table<DefIndex, Lazy!(ty::PolyFnSig<'tcx>)>,
|
||||
impl_trait_ref: Table<DefIndex, Lazy!(ty::TraitRef<'tcx>)>,
|
||||
trait_item_def_id: Table<DefIndex, Lazy<DefId>>,
|
||||
inherent_impls: Table<DefIndex, Lazy<[DefIndex]>>,
|
||||
variances: Table<DefIndex, Lazy<[ty::Variance]>>,
|
||||
generics: Table<DefIndex, Lazy<ty::Generics>>,
|
||||
|
|
|
@ -40,6 +40,7 @@ impl AssocItemContainer {
|
|||
}
|
||||
}
|
||||
|
||||
/// Information about an associated item
|
||||
#[derive(Copy, Clone, Debug, PartialEq, HashStable, Eq, Hash)]
|
||||
pub struct AssocItem {
|
||||
pub def_id: DefId,
|
||||
|
@ -50,6 +51,10 @@ pub struct AssocItem {
|
|||
pub defaultness: hir::Defaultness,
|
||||
pub container: AssocItemContainer,
|
||||
|
||||
/// If this is an item in an impl of a trait then this is the `DefId` of
|
||||
/// the associated item on the trait that this implements.
|
||||
pub trait_item_def_id: Option<DefId>,
|
||||
|
||||
/// Whether this is a method with an explicit self
|
||||
/// as its first parameter, allowing method calls.
|
||||
pub fn_has_self_parameter: bool,
|
||||
|
|
|
@ -794,19 +794,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
if let Res::Def(DefKind::Trait, trait_did) = t.path.res {
|
||||
for impl_item_ref in items {
|
||||
let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
|
||||
let trait_item_def_id = self
|
||||
.tcx
|
||||
.associated_items(trait_did)
|
||||
.filter_by_name_unhygienic(impl_item.ident.name)
|
||||
.next()
|
||||
.map(|item| item.def_id);
|
||||
if let Some(def_id) = trait_item_def_id {
|
||||
// Pass `None` to skip deprecation warnings.
|
||||
self.tcx.check_stability(def_id, None, impl_item.span, None);
|
||||
}
|
||||
for impl_item_ref in items {
|
||||
let impl_item = self.tcx.associated_item(impl_item_ref.id.def_id);
|
||||
|
||||
if let Some(def_id) = impl_item.trait_item_def_id {
|
||||
// Pass `None` to skip deprecation warnings.
|
||||
self.tcx.check_stability(def_id, None, impl_item_ref.span, None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -710,13 +710,11 @@ impl<'tcx> SaveContext<'tcx> {
|
|||
}
|
||||
Res::Def(HirDefKind::AssocFn, decl_id) => {
|
||||
let def_id = if decl_id.is_local() {
|
||||
let ti = self.tcx.associated_item(decl_id);
|
||||
|
||||
self.tcx
|
||||
.associated_items(ti.container.id())
|
||||
.filter_by_name_unhygienic(ti.ident.name)
|
||||
.find(|item| item.defaultness.has_value())
|
||||
.map(|item| item.def_id)
|
||||
if self.tcx.associated_item(decl_id).defaultness.has_value() {
|
||||
Some(decl_id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
|
@ -436,23 +436,13 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
|
|||
) -> Arc<chalk_solve::rust_ir::AssociatedTyValue<RustInterner<'tcx>>> {
|
||||
let def_id = associated_ty_id.0;
|
||||
let assoc_item = self.interner.tcx.associated_item(def_id);
|
||||
let (impl_id, trait_id) = match assoc_item.container {
|
||||
AssocItemContainer::TraitContainer(def_id) => (def_id, def_id),
|
||||
AssocItemContainer::ImplContainer(def_id) => {
|
||||
(def_id, self.interner.tcx.impl_trait_ref(def_id).unwrap().def_id)
|
||||
}
|
||||
};
|
||||
let impl_id = assoc_item.container.id();
|
||||
match assoc_item.kind {
|
||||
AssocKind::Type => {}
|
||||
_ => unimplemented!("Not possible??"),
|
||||
}
|
||||
|
||||
let trait_item = self
|
||||
.interner
|
||||
.tcx
|
||||
.associated_items(trait_id)
|
||||
.find_by_name_and_kind(self.interner.tcx, assoc_item.ident, assoc_item.kind, trait_id)
|
||||
.unwrap();
|
||||
let trait_item_id = assoc_item.trait_item_def_id.expect("assoc_ty with no trait version");
|
||||
let bound_vars = bound_vars_for_item(self.interner.tcx, def_id);
|
||||
let binders = binders_for(self.interner, bound_vars);
|
||||
let ty = self
|
||||
|
@ -464,7 +454,7 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
|
|||
|
||||
Arc::new(chalk_solve::rust_ir::AssociatedTyValue {
|
||||
impl_id: chalk_ir::ImplId(impl_id),
|
||||
associated_ty_id: chalk_ir::AssocTypeId(trait_item.def_id),
|
||||
associated_ty_id: chalk_ir::AssocTypeId(trait_item_id),
|
||||
value: chalk_ir::Binders::new(
|
||||
binders,
|
||||
chalk_solve::rust_ir::AssociatedTyValueBound { ty },
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_errors::struct_span_err;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_middle::ty::subst::Subst;
|
||||
use rustc_middle::ty::{self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{
|
||||
self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt, TypeFoldable,
|
||||
};
|
||||
use rustc_span::{sym, Span};
|
||||
use rustc_trait_selection::traits;
|
||||
|
||||
|
@ -89,6 +92,7 @@ fn associated_item_from_trait_item_ref(
|
|||
vis: tcx.visibility(def_id),
|
||||
defaultness: trait_item_ref.defaultness,
|
||||
def_id: def_id.to_def_id(),
|
||||
trait_item_def_id: Some(def_id.to_def_id()),
|
||||
container: ty::TraitContainer(parent_def_id.to_def_id()),
|
||||
fn_has_self_parameter: has_self,
|
||||
}
|
||||
|
@ -106,17 +110,119 @@ fn associated_item_from_impl_item_ref(
|
|||
hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
|
||||
};
|
||||
|
||||
let trait_item_def_id = impl_item_base_id(tcx, parent_def_id, impl_item_ref);
|
||||
|
||||
ty::AssocItem {
|
||||
ident: impl_item_ref.ident,
|
||||
kind,
|
||||
vis: tcx.visibility(def_id),
|
||||
defaultness: impl_item_ref.defaultness,
|
||||
def_id: def_id.to_def_id(),
|
||||
trait_item_def_id,
|
||||
container: ty::ImplContainer(parent_def_id.to_def_id()),
|
||||
fn_has_self_parameter: has_self,
|
||||
}
|
||||
}
|
||||
|
||||
fn impl_item_base_id<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
parent_def_id: LocalDefId,
|
||||
impl_item: &hir::ImplItemRef,
|
||||
) -> Option<DefId> {
|
||||
let impl_trait_ref = tcx.impl_trait_ref(parent_def_id)?;
|
||||
|
||||
// If the trait reference itself is erroneous (so the compilation is going
|
||||
// to fail), skip checking the items here -- the `impl_item` table in `tcx`
|
||||
// isn't populated for such impls.
|
||||
if impl_trait_ref.references_error() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Locate trait items
|
||||
let associated_items = tcx.associated_items(impl_trait_ref.def_id);
|
||||
|
||||
// Match item against trait
|
||||
let mut items = associated_items.filter_by_name(tcx, impl_item.ident, impl_trait_ref.def_id);
|
||||
|
||||
let mut trait_item = items.next()?;
|
||||
|
||||
let is_compatible = |ty: &&ty::AssocItem| match (ty.kind, &impl_item.kind) {
|
||||
(ty::AssocKind::Const, hir::AssocItemKind::Const) => true,
|
||||
(ty::AssocKind::Fn, hir::AssocItemKind::Fn { .. }) => true,
|
||||
(ty::AssocKind::Type, hir::AssocItemKind::Type) => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
// If we don't have a compatible item, we'll use the first one whose name matches
|
||||
// to report an error.
|
||||
let mut compatible_kind = is_compatible(&trait_item);
|
||||
|
||||
if !compatible_kind {
|
||||
if let Some(ty_trait_item) = items.find(is_compatible) {
|
||||
compatible_kind = true;
|
||||
trait_item = ty_trait_item;
|
||||
}
|
||||
}
|
||||
|
||||
if compatible_kind {
|
||||
Some(trait_item.def_id)
|
||||
} else {
|
||||
report_mismatch_error(tcx, trait_item.def_id, impl_trait_ref, impl_item);
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
#[cold]
|
||||
fn report_mismatch_error<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
trait_item_def_id: DefId,
|
||||
impl_trait_ref: ty::TraitRef<'tcx>,
|
||||
impl_item: &hir::ImplItemRef,
|
||||
) {
|
||||
let mut err = match impl_item.kind {
|
||||
hir::AssocItemKind::Const => {
|
||||
// Find associated const definition.
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
impl_item.span,
|
||||
E0323,
|
||||
"item `{}` is an associated const, which doesn't match its trait `{}`",
|
||||
impl_item.ident,
|
||||
impl_trait_ref.print_only_trait_path()
|
||||
)
|
||||
}
|
||||
|
||||
hir::AssocItemKind::Fn { .. } => {
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
impl_item.span,
|
||||
E0324,
|
||||
"item `{}` is an associated method, which doesn't match its trait `{}`",
|
||||
impl_item.ident,
|
||||
impl_trait_ref.print_only_trait_path()
|
||||
)
|
||||
}
|
||||
|
||||
hir::AssocItemKind::Type => {
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
impl_item.span,
|
||||
E0325,
|
||||
"item `{}` is an associated type, which doesn't match its trait `{}`",
|
||||
impl_item.ident,
|
||||
impl_trait_ref.print_only_trait_path()
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
err.span_label(impl_item.span, "does not match trait");
|
||||
if let Some(trait_span) = tcx.hir().span_if_local(trait_item_def_id) {
|
||||
err.span_label(trait_span, "item in trait");
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
|
||||
fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
|
||||
let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
|
||||
let parent_id = tcx.hir().get_parent_item(id);
|
||||
|
|
|
@ -841,14 +841,8 @@ pub(super) fn check_specialization_validity<'tcx>(
|
|||
trait_def: &ty::TraitDef,
|
||||
trait_item: &ty::AssocItem,
|
||||
impl_id: DefId,
|
||||
impl_item: &hir::ImplItem<'_>,
|
||||
impl_item: &hir::ImplItemRef,
|
||||
) {
|
||||
let kind = match impl_item.kind {
|
||||
hir::ImplItemKind::Const(..) => ty::AssocKind::Const,
|
||||
hir::ImplItemKind::Fn(..) => ty::AssocKind::Fn,
|
||||
hir::ImplItemKind::TyAlias(_) => ty::AssocKind::Type,
|
||||
};
|
||||
|
||||
let ancestors = match trait_def.ancestors(tcx, impl_id) {
|
||||
Ok(ancestors) => ancestors,
|
||||
Err(_) => return,
|
||||
|
@ -857,7 +851,7 @@ pub(super) fn check_specialization_validity<'tcx>(
|
|||
if parent.is_from_trait() {
|
||||
None
|
||||
} else {
|
||||
Some((parent, parent.item(tcx, trait_item.ident, kind, trait_def.def_id)))
|
||||
Some((parent, parent.item(tcx, trait_item.def_id)))
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -894,7 +888,7 @@ pub(super) fn check_specialization_validity<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn check_impl_items_against_trait<'tcx>(
|
||||
fn check_impl_items_against_trait<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
full_impl_span: Span,
|
||||
impl_id: LocalDefId,
|
||||
|
@ -926,174 +920,81 @@ pub(super) fn check_impl_items_against_trait<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
// Locate trait definition and items
|
||||
let trait_def = tcx.trait_def(impl_trait_ref.def_id);
|
||||
let impl_items = impl_item_refs.iter().map(|iiref| tcx.hir().impl_item(iiref.id));
|
||||
let associated_items = tcx.associated_items(impl_trait_ref.def_id);
|
||||
|
||||
// Check existing impl methods to see if they are both present in trait
|
||||
// and compatible with trait signature
|
||||
for impl_item in impl_items {
|
||||
let ty_impl_item = tcx.associated_item(impl_item.def_id);
|
||||
|
||||
let mut items =
|
||||
associated_items.filter_by_name(tcx, ty_impl_item.ident, impl_trait_ref.def_id);
|
||||
|
||||
let (compatible_kind, ty_trait_item) = if let Some(ty_trait_item) = items.next() {
|
||||
let is_compatible = |ty: &&ty::AssocItem| match (ty.kind, &impl_item.kind) {
|
||||
(ty::AssocKind::Const, hir::ImplItemKind::Const(..)) => true,
|
||||
(ty::AssocKind::Fn, hir::ImplItemKind::Fn(..)) => true,
|
||||
(ty::AssocKind::Type, hir::ImplItemKind::TyAlias(..)) => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
// If we don't have a compatible item, we'll use the first one whose name matches
|
||||
// to report an error.
|
||||
let mut compatible_kind = is_compatible(&ty_trait_item);
|
||||
let mut trait_item = ty_trait_item;
|
||||
|
||||
if !compatible_kind {
|
||||
if let Some(ty_trait_item) = items.find(is_compatible) {
|
||||
compatible_kind = true;
|
||||
trait_item = ty_trait_item;
|
||||
}
|
||||
}
|
||||
|
||||
(compatible_kind, trait_item)
|
||||
for impl_item in impl_item_refs {
|
||||
let ty_impl_item = tcx.associated_item(impl_item.id.def_id);
|
||||
let ty_trait_item = if let Some(trait_item_id) = ty_impl_item.trait_item_def_id {
|
||||
tcx.associated_item(trait_item_id)
|
||||
} else {
|
||||
// Checked in `associated_item`.
|
||||
tcx.sess.delay_span_bug(impl_item.span, "missing associated item in trait");
|
||||
continue;
|
||||
};
|
||||
|
||||
if compatible_kind {
|
||||
match impl_item.kind {
|
||||
hir::ImplItemKind::Const(..) => {
|
||||
// Find associated const definition.
|
||||
compare_const_impl(
|
||||
tcx,
|
||||
&ty_impl_item,
|
||||
impl_item.span,
|
||||
&ty_trait_item,
|
||||
impl_trait_ref,
|
||||
);
|
||||
}
|
||||
hir::ImplItemKind::Fn(..) => {
|
||||
let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
|
||||
compare_impl_method(
|
||||
tcx,
|
||||
&ty_impl_item,
|
||||
impl_item.span,
|
||||
&ty_trait_item,
|
||||
impl_trait_ref,
|
||||
opt_trait_span,
|
||||
);
|
||||
}
|
||||
hir::ImplItemKind::TyAlias(impl_ty) => {
|
||||
let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
|
||||
compare_ty_impl(
|
||||
tcx,
|
||||
&ty_impl_item,
|
||||
impl_ty.span,
|
||||
&ty_trait_item,
|
||||
impl_trait_ref,
|
||||
opt_trait_span,
|
||||
);
|
||||
}
|
||||
match impl_item.kind {
|
||||
hir::AssocItemKind::Const => {
|
||||
// Find associated const definition.
|
||||
compare_const_impl(
|
||||
tcx,
|
||||
&ty_impl_item,
|
||||
impl_item.span,
|
||||
&ty_trait_item,
|
||||
impl_trait_ref,
|
||||
);
|
||||
}
|
||||
hir::AssocItemKind::Fn { .. } => {
|
||||
let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
|
||||
compare_impl_method(
|
||||
tcx,
|
||||
&ty_impl_item,
|
||||
impl_item.span,
|
||||
&ty_trait_item,
|
||||
impl_trait_ref,
|
||||
opt_trait_span,
|
||||
);
|
||||
}
|
||||
hir::AssocItemKind::Type => {
|
||||
let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
|
||||
compare_ty_impl(
|
||||
tcx,
|
||||
&ty_impl_item,
|
||||
impl_item.span,
|
||||
&ty_trait_item,
|
||||
impl_trait_ref,
|
||||
opt_trait_span,
|
||||
);
|
||||
}
|
||||
|
||||
check_specialization_validity(
|
||||
tcx,
|
||||
trait_def,
|
||||
&ty_trait_item,
|
||||
impl_id.to_def_id(),
|
||||
impl_item,
|
||||
);
|
||||
} else {
|
||||
report_mismatch_error(
|
||||
tcx,
|
||||
ty_trait_item.def_id,
|
||||
impl_trait_ref,
|
||||
impl_item,
|
||||
&ty_impl_item,
|
||||
);
|
||||
}
|
||||
|
||||
check_specialization_validity(
|
||||
tcx,
|
||||
trait_def,
|
||||
&ty_trait_item,
|
||||
impl_id.to_def_id(),
|
||||
impl_item,
|
||||
);
|
||||
}
|
||||
|
||||
if let Ok(ancestors) = trait_def.ancestors(tcx, impl_id.to_def_id()) {
|
||||
let impl_span = tcx.sess.source_map().guess_head_span(full_impl_span);
|
||||
|
||||
// Check for missing items from trait
|
||||
let mut missing_items = Vec::new();
|
||||
for trait_item in tcx.associated_items(impl_trait_ref.def_id).in_definition_order() {
|
||||
for &trait_item_id in tcx.associated_item_def_ids(impl_trait_ref.def_id) {
|
||||
let is_implemented = ancestors
|
||||
.leaf_def(tcx, trait_item.ident, trait_item.kind)
|
||||
.map(|node_item| !node_item.defining_node.is_from_trait())
|
||||
.unwrap_or(false);
|
||||
.leaf_def(tcx, trait_item_id)
|
||||
.map_or(false, |node_item| node_item.item.defaultness.has_value());
|
||||
|
||||
if !is_implemented && tcx.impl_defaultness(impl_id).is_final() {
|
||||
if !trait_item.defaultness.has_value() {
|
||||
missing_items.push(*trait_item);
|
||||
}
|
||||
missing_items.push(tcx.associated_item(trait_item_id));
|
||||
}
|
||||
}
|
||||
|
||||
if !missing_items.is_empty() {
|
||||
let impl_span = tcx.sess.source_map().guess_head_span(full_impl_span);
|
||||
missing_items_err(tcx, impl_span, &missing_items, full_impl_span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
#[cold]
|
||||
fn report_mismatch_error<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
trait_item_def_id: DefId,
|
||||
impl_trait_ref: ty::TraitRef<'tcx>,
|
||||
impl_item: &hir::ImplItem<'_>,
|
||||
ty_impl_item: &ty::AssocItem,
|
||||
) {
|
||||
let mut err = match impl_item.kind {
|
||||
hir::ImplItemKind::Const(..) => {
|
||||
// Find associated const definition.
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
impl_item.span,
|
||||
E0323,
|
||||
"item `{}` is an associated const, which doesn't match its trait `{}`",
|
||||
ty_impl_item.ident,
|
||||
impl_trait_ref.print_only_trait_path()
|
||||
)
|
||||
}
|
||||
|
||||
hir::ImplItemKind::Fn(..) => {
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
impl_item.span,
|
||||
E0324,
|
||||
"item `{}` is an associated method, which doesn't match its trait `{}`",
|
||||
ty_impl_item.ident,
|
||||
impl_trait_ref.print_only_trait_path()
|
||||
)
|
||||
}
|
||||
|
||||
hir::ImplItemKind::TyAlias(_) => {
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
impl_item.span,
|
||||
E0325,
|
||||
"item `{}` is an associated type, which doesn't match its trait `{}`",
|
||||
ty_impl_item.ident,
|
||||
impl_trait_ref.print_only_trait_path()
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
err.span_label(impl_item.span, "does not match trait");
|
||||
if let Some(trait_span) = tcx.hir().span_if_local(trait_item_def_id) {
|
||||
err.span_label(trait_span, "item in trait");
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
|
||||
/// Checks whether a type can be represented in memory. In particular, it
|
||||
/// identifies types that contain themselves without indirection through a
|
||||
/// pointer, which would mean their size is unbounded.
|
||||
|
|
|
@ -566,7 +566,7 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId, span: S
|
|||
|
||||
fn report_forbidden_specialization(
|
||||
tcx: TyCtxt<'_>,
|
||||
impl_item: &hir::ImplItem<'_>,
|
||||
impl_item: &hir::ImplItemRef,
|
||||
parent_impl: DefId,
|
||||
) {
|
||||
let mut err = struct_span_err!(
|
||||
|
@ -598,7 +598,7 @@ fn report_forbidden_specialization(
|
|||
fn missing_items_err(
|
||||
tcx: TyCtxt<'_>,
|
||||
impl_span: Span,
|
||||
missing_items: &[ty::AssocItem],
|
||||
missing_items: &[&ty::AssocItem],
|
||||
full_impl_span: Span,
|
||||
) {
|
||||
let missing_items_msg = missing_items
|
||||
|
|
|
@ -3150,21 +3150,12 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
|||
/// applied to the method prototype.
|
||||
fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
||||
if let Some(impl_item) = tcx.opt_associated_item(def_id) {
|
||||
if let ty::AssocItemContainer::ImplContainer(impl_def_id) = impl_item.container {
|
||||
if let Some(trait_def_id) = tcx.trait_id_of_impl(impl_def_id) {
|
||||
if let Some(trait_item) = tcx
|
||||
.associated_items(trait_def_id)
|
||||
.filter_by_name_unhygienic(impl_item.ident.name)
|
||||
.find(move |trait_item| {
|
||||
trait_item.kind == ty::AssocKind::Fn
|
||||
&& tcx.hygienic_eq(impl_item.ident, trait_item.ident, trait_def_id)
|
||||
})
|
||||
{
|
||||
return tcx
|
||||
.codegen_fn_attrs(trait_item.def_id)
|
||||
.flags
|
||||
.intersects(CodegenFnAttrFlags::TRACK_CALLER);
|
||||
}
|
||||
if let ty::AssocItemContainer::ImplContainer(_) = impl_item.container {
|
||||
if let Some(trait_item) = impl_item.trait_item_def_id {
|
||||
return tcx
|
||||
.codegen_fn_attrs(trait_item)
|
||||
.flags
|
||||
.intersects(CodegenFnAttrFlags::TRACK_CALLER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue