Link impl items to corresponding trait items in late resolver.
This commit is contained in:
parent
488acf86a7
commit
1be6e2d6e9
9 changed files with 114 additions and 162 deletions
|
@ -1,8 +1,7 @@
|
|||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::struct_span_err;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
|
||||
pub fn provide(providers: &mut ty::query::Providers) {
|
||||
*providers = ty::query::Providers {
|
||||
|
@ -125,115 +124,14 @@ 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,
|
||||
trait_item_def_id: impl_item_ref.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();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue