mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 06:11:35 +00:00
Check for dyn impls in method resolution
This commit is contained in:
parent
4cc333c889
commit
965d31ce5b
2 changed files with 38 additions and 11 deletions
|
@ -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(
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue