diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index fda31d5177c..817c27410a1 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -755,7 +755,7 @@ pub struct TypeParam { impl TypeParam { pub fn name(self, db: &impl HirDatabase) -> Name { let params = db.generic_params(self.id.parent); - params.types[self.id.local_id].name.clone() + params.types[self.id.local_id].name.clone().unwrap_or_else(Name::missing) } pub fn module(self, db: &impl HirDatabase) -> Module { diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index e9c28c7309e..7553d8a8719 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs @@ -27,8 +27,16 @@ /// Data about a generic parameter (to a function, struct, impl, ...). #[derive(Clone, PartialEq, Eq, Debug)] pub struct TypeParamData { - pub name: Name, + pub name: Option, pub default: Option, + pub provenance: TypeParamProvenance, +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum TypeParamProvenance { + TypeParamList, + TraitSelf, + ArgumentImplTrait, } /// Data about the generic parameters of a function, struct, impl, etc. @@ -68,6 +76,11 @@ fn new(db: &impl DefDatabase, def: GenericDefId) -> (GenericParams, InFile { let src = it.lookup(db).source(db); generics.fill(&mut sm, &src.value); + // lower `impl Trait` in arguments + let data = db.function_data(it); + for param in &data.params { + generics.fill_implicit_impl_trait_args(param); + } src.file_id } GenericDefId::AdtId(AdtId::StructId(it)) => { @@ -89,8 +102,11 @@ fn new(db: &impl DefDatabase, def: GenericDefId) -> (GenericParams, InFile Option { - self.types.iter().find_map(|(id, p)| if &p.name == name { Some(id) } else { None }) + self.types + .iter() + .find_map(|(id, p)| if p.name.as_ref() == Some(name) { Some(id) } else { None }) } } diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index f7bac580112..05cf4646a89 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs @@ -490,10 +490,12 @@ fn process_names(&self, db: &impl DefDatabase, f: &mut dyn FnMut(Name, ScopeDef) } Scope::GenericParams { params, def } => { for (local_id, param) in params.types.iter() { - f( - param.name.clone(), - ScopeDef::GenericParam(TypeParamId { local_id, parent: *def }), - ) + if let Some(name) = ¶m.name { + f( + name.clone(), + ScopeDef::GenericParam(TypeParamId { local_id, parent: *def }), + ) + } } } Scope::ImplBlockScope(i) => { diff --git a/crates/ra_hir_def/src/type_ref.rs b/crates/ra_hir_def/src/type_ref.rs index 5f10e9a88ba..10941477053 100644 --- a/crates/ra_hir_def/src/type_ref.rs +++ b/crates/ra_hir_def/src/type_ref.rs @@ -124,6 +124,50 @@ pub(crate) fn from_ast_opt(node: Option) -> Self { pub(crate) fn unit() -> TypeRef { TypeRef::Tuple(Vec::new()) } + + pub fn walk(&self, f: &mut impl FnMut(&TypeRef)) { + go(self, f); + + fn go(type_ref: &TypeRef, f: &mut impl FnMut(&TypeRef)) { + f(type_ref); + match type_ref { + TypeRef::Fn(types) | TypeRef::Tuple(types) => { + types.iter().for_each(|t| go(t, f)) + } + TypeRef::RawPtr(type_ref, _) + | TypeRef::Reference(type_ref, _) + | TypeRef::Array(type_ref) + | TypeRef::Slice(type_ref) => go(&type_ref, f), + TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => { + for bound in bounds { + match bound { + TypeBound::Path(path) => go_path(path, f), + TypeBound::Error => (), + } + } + } + TypeRef::Path(path) => go_path(path, f), + TypeRef::Never | TypeRef::Placeholder | TypeRef::Error => {} + }; + } + + fn go_path(path: &Path, f: &mut impl FnMut(&TypeRef)) { + if let Some(type_ref) = path.type_anchor() { + go(type_ref, f); + } + for segment in path.segments().iter() { + if let Some(args_and_bindings) = segment.args_and_bindings { + for arg in &args_and_bindings.args { + let crate::path::GenericArg::Type(type_ref) = arg; + go(type_ref, f); + } + for (_, type_ref) in &args_and_bindings.bindings { + go(type_ref, f); + } + } + } + } + } } pub(crate) fn type_bounds_from_ast(type_bounds_opt: Option) -> Vec { diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 31259a01de7..97cb20cea40 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs @@ -10,7 +10,7 @@ resolver::resolver_for_expr, AdtId, AssocContainerId, Lookup, StructFieldId, }; -use hir_expand::name::{name, Name}; +use hir_expand::name::Name; use ra_syntax::ast::RangeOp; use crate::{ @@ -654,7 +654,7 @@ fn substs_for_method_call( // Parent arguments are unknown, except for the receiver type if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) { for (_id, param) in parent_generics { - if param.name == name![Self] { + if param.provenance == hir_def::generics::TypeParamProvenance::TraitSelf { substs.push(receiver_ty.clone()); } else { substs.push(Ty::Unknown); diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index c64b81f9848..cb7a60352fd 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs @@ -368,7 +368,7 @@ pub fn as_single(&self) -> &Ty { /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). pub(crate) fn identity(generic_params: &Generics) -> Substs { Substs( - generic_params.iter().map(|(idx, p)| Ty::Param { idx, name: p.name.clone() }).collect(), + generic_params.iter().map(|(idx, p)| Ty::Param { idx, name: p.name.clone().unwrap_or_else(Name::missing) }).collect(), ) } diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 39406d8cec5..6f768147520 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -341,6 +341,7 @@ pub(super) fn substs_from_path_segment( // Self type as an implicit first type parameter, but it can't be // actually provided in the type arguments // (well, actually sometimes it can, in the form of type-relative paths: `::default()`) + // TODO handle this using type param provenance substs.push(Ty::Unknown); } if let Some(generic_args) = &segment.args_and_bindings { diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs index 0b1806a84fd..314a3241f9d 100644 --- a/crates/ra_hir_ty/src/utils.rs +++ b/crates/ra_hir_ty/src/utils.rs @@ -127,7 +127,8 @@ pub(crate) fn param_idx(&self, param: TypeParamId) -> u32 { self.find_param(param).0 } pub(crate) fn param_name(&self, param: TypeParamId) -> Name { - self.find_param(param).1.name.clone() + // FIXME make this return Option + self.find_param(param).1.name.clone().unwrap_or_else(Name::missing) } fn find_param(&self, param: TypeParamId) -> (u32, &TypeParamData) { if param.parent == self.def {