Check for dyn impls in method resolution

This commit is contained in:
Lukas Wirth 2021-02-08 19:13:54 +01:00
parent 4cc333c889
commit 965d31ce5b
2 changed files with 38 additions and 11 deletions

View file

@ -10,25 +10,26 @@ use hir_def::{
builtin_type::{IntBitness, Signedness}, builtin_type::{IntBitness, Signedness},
lang_item::LangItemTarget, lang_item::LangItemTarget,
type_ref::Mutability, type_ref::Mutability,
AssocContainerId, AssocItemId, FunctionId, HasModule, ImplId, Lookup, TraitId, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule, ImplId, Lookup, ModuleId,
TraitId,
}; };
use hir_expand::name::Name; use hir_expand::name::Name;
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use super::Substs;
use crate::{ use crate::{
autoderef, autoderef,
db::HirDatabase, db::HirDatabase,
primitive::{FloatBitness, FloatTy, IntTy}, primitive::{FloatBitness, FloatTy, IntTy},
utils::all_super_traits, utils::all_super_traits,
ApplicationTy, Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty, TyKind, ApplicationTy, Canonical, DebruijnIndex, InEnvironment, Substs, TraitEnvironment, TraitRef, Ty,
TypeCtor, TypeWalk, TyKind, TypeCtor, TypeWalk,
}; };
/// This is used as a key for indexing impls. /// This is used as a key for indexing impls.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum TyFingerprint { pub enum TyFingerprint {
Apply(TypeCtor), Apply(TypeCtor),
Dyn(TraitId),
} }
impl TyFingerprint { impl TyFingerprint {
@ -38,6 +39,7 @@ impl TyFingerprint {
pub(crate) fn for_impl(ty: &Ty) -> Option<TyFingerprint> { pub(crate) fn for_impl(ty: &Ty) -> Option<TyFingerprint> {
match ty { match ty {
Ty::Apply(a_ty) => Some(TyFingerprint::Apply(a_ty.ctor)), Ty::Apply(a_ty) => Some(TyFingerprint::Apply(a_ty.ctor)),
Ty::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_)),
_ => None, _ => None,
} }
} }
@ -245,18 +247,15 @@ impl Ty {
}}; }};
} }
let mod_to_crate_ids = |module: ModuleId| Some(std::iter::once(module.krate()).collect());
let lang_item_targets = match self { let lang_item_targets = match self {
Ty::Apply(a_ty) => match a_ty.ctor { Ty::Apply(a_ty) => match a_ty.ctor {
TypeCtor::Adt(def_id) => { TypeCtor::Adt(def_id) => {
return Some(std::iter::once(def_id.module(db.upcast()).krate()).collect()) return mod_to_crate_ids(def_id.module(db.upcast()));
} }
TypeCtor::ForeignType(type_alias_id) => { TypeCtor::ForeignType(type_alias_id) => {
return Some( return mod_to_crate_ids(type_alias_id.lookup(db.upcast()).module(db.upcast()));
std::iter::once(
type_alias_id.lookup(db.upcast()).module(db.upcast()).krate(),
)
.collect(),
)
} }
TypeCtor::Bool => lang_item_crate!("bool"), TypeCtor::Bool => lang_item_crate!("bool"),
TypeCtor::Char => lang_item_crate!("char"), TypeCtor::Char => lang_item_crate!("char"),
@ -272,6 +271,11 @@ impl Ty {
TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!("mut_ptr"), TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!("mut_ptr"),
_ => return None, _ => return None,
}, },
Ty::Dyn(_) => {
return self.dyn_trait().and_then(|trait_| {
mod_to_crate_ids(GenericDefId::TraitId(trait_).module(db.upcast()))
});
}
_ => return None, _ => return None,
}; };
let res = lang_item_targets let res = lang_item_targets
@ -285,6 +289,7 @@ impl Ty {
Some(res) Some(res)
} }
} }
/// Look up the method with the given name, returning the actual autoderefed /// Look up the method with the given name, returning the actual autoderefed
/// receiver type (but without autoref applied yet). /// receiver type (but without autoref applied yet).
pub(crate) fn lookup_method( pub(crate) fn lookup_method(

View file

@ -1106,3 +1106,25 @@ fn main() {
"#, "#,
); );
} }
#[test]
fn method_on_dyn_impl() {
check_types(
r#"
trait Foo {}
impl Foo for u32 {}
impl dyn Foo {
pub fn dyn_foo(&self) -> u32 {
0
}
}
fn main() {
let f = &42u32 as &dyn Foo<u32>;
f.dyn_foo();
// ^u32
}
"#,
);
}