From 4fa8749c44e1c91335002eb46d59b2a72e756bb3 Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Wed, 29 Dec 2021 17:05:59 +0330 Subject: [PATCH 1/2] Preserve order of generic args --- crates/hir/src/attrs.rs | 4 +- crates/hir/src/display.rs | 65 ++++--- crates/hir/src/from_id.rs | 9 +- crates/hir/src/has_source.rs | 16 +- crates/hir/src/lib.rs | 125 +++++++++---- crates/hir/src/semantics.rs | 2 +- crates/hir/src/semantics/source_to_def.rs | 4 +- crates/hir/src/source_analyzer.rs | 14 +- crates/hir_def/src/attr.rs | 53 ++++-- crates/hir_def/src/generics.rs | 174 ++++++++++-------- crates/hir_def/src/item_tree/lower.rs | 13 +- crates/hir_def/src/item_tree/pretty.rs | 36 ++-- crates/hir_def/src/keys.rs | 8 +- crates/hir_def/src/lib.rs | 67 +++++-- crates/hir_def/src/resolver.rs | 45 +++-- crates/hir_expand/src/builtin_derive_macro.rs | 11 +- crates/hir_ty/src/chalk_ext.rs | 46 ++--- crates/hir_ty/src/db.rs | 15 +- crates/hir_ty/src/display.rs | 70 +++---- crates/hir_ty/src/infer/expr.rs | 12 +- crates/hir_ty/src/lib.rs | 10 +- crates/hir_ty/src/lower.rs | 60 +++--- crates/hir_ty/src/mapping.rs | 16 +- crates/hir_ty/src/utils.rs | 52 +++--- crates/ide/src/hover/tests.rs | 21 +++ crates/ide/src/navigation_target.rs | 28 ++- crates/ide/src/syntax_highlighting/inject.rs | 2 +- .../test_data/highlight_doctest.html | 7 + crates/ide/src/syntax_highlighting/tests.rs | 7 + .../src/handlers/generate_default_from_new.rs | 28 +-- .../ide_assists/src/handlers/move_bounds.rs | 13 +- crates/ide_assists/src/utils.rs | 19 +- crates/ide_completion/src/render.rs | 2 +- crates/ide_db/src/apply_change.rs | 4 +- crates/ide_db/src/defs.rs | 2 +- crates/ide_db/src/path_transform.rs | 28 +-- crates/ide_db/src/rename.rs | 23 ++- crates/syntax/src/ast.rs | 2 +- crates/syntax/src/ast/node_ext.rs | 28 ++- 39 files changed, 714 insertions(+), 427 deletions(-) diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index 46e9c54dad65..7e83819a4f51 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs @@ -139,9 +139,9 @@ fn resolve_doc_path( AttrDefId::ImplId(it) => it.resolver(db.upcast()), AttrDefId::ExternBlockId(it) => it.resolver(db.upcast()), AttrDefId::GenericParamId(it) => match it { - GenericParamId::TypeParamId(it) => it.parent, + GenericParamId::TypeParamId(it) => it.parent(), + GenericParamId::ConstParamId(it) => it.parent(), GenericParamId::LifetimeParamId(it) => it.parent, - GenericParamId::ConstParamId(it) => it.parent, } .resolver(db.upcast()), // FIXME diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 1e949771ea01..d411b9d71b12 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -1,7 +1,9 @@ //! HirDisplay implementations for various hir types. use hir_def::{ adt::VariantData, - generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget}, + generics::{ + TypeOrConstParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget, + }, type_ref::{TypeBound, TypeRef}, AdtId, GenericDefId, }; @@ -16,8 +18,8 @@ use syntax::SmolStr; use crate::{ Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasCrate, HasVisibility, - LifetimeParam, Module, Static, Struct, Trait, TyBuilder, Type, TypeAlias, TypeParam, Union, - Variant, + LifetimeParam, Module, Static, Struct, Trait, TyBuilder, Type, TypeAlias, TypeOrConstParam, + TypeParam, Union, Variant, }; impl HirDisplay for Function { @@ -226,8 +228,17 @@ impl HirDisplay for GenericParam { fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { match self { GenericParam::TypeParam(it) => it.hir_fmt(f), - GenericParam::LifetimeParam(it) => it.hir_fmt(f), GenericParam::ConstParam(it) => it.hir_fmt(f), + GenericParam::LifetimeParam(it) => it.hir_fmt(f), + } + } +} + +impl HirDisplay for TypeOrConstParam { + fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { + match self.split(f.db) { + either::Either::Left(x) => x.hir_fmt(f), + either::Either::Right(x) => x.hir_fmt(f), } } } @@ -239,11 +250,11 @@ impl HirDisplay for TypeParam { return Ok(()); } - let bounds = f.db.generic_predicates_for_param(self.id.parent, self.id, None); - let substs = TyBuilder::type_params_subst(f.db, self.id.parent); + let bounds = f.db.generic_predicates_for_param(self.id.parent(), self.id.into(), None); + let substs = TyBuilder::type_params_subst(f.db, self.id.parent()); let predicates: Vec<_> = bounds.iter().cloned().map(|b| b.substitute(Interner, &substs)).collect(); - let krate = self.id.parent.krate(f.db).id; + let krate = self.id.parent().krate(f.db).id; let sized_trait = f.db.lang_item(krate, SmolStr::new_inline("sized")) .and_then(|lang_item| lang_item.as_trait()); @@ -276,11 +287,11 @@ impl HirDisplay for ConstParam { fn write_generic_params(def: GenericDefId, f: &mut HirFormatter) -> Result<(), HirDisplayError> { let params = f.db.generic_params(def); if params.lifetimes.is_empty() - && params.consts.is_empty() && params .types .iter() - .all(|(_, param)| !matches!(param.provenance, TypeParamProvenance::TypeParamList)) + .filter_map(|x| x.1.type_param()) + .all(|param| !matches!(param.provenance, TypeParamProvenance::TypeParamList)) { return Ok(()); } @@ -300,23 +311,27 @@ fn write_generic_params(def: GenericDefId, f: &mut HirFormatter) -> Result<(), H write!(f, "{}", lifetime.name)?; } for (_, ty) in params.types.iter() { - if ty.provenance != TypeParamProvenance::TypeParamList { - continue; - } - if let Some(name) = &ty.name { - delim(f)?; - write!(f, "{}", name)?; - if let Some(default) = &ty.default { - write!(f, " = ")?; - default.hir_fmt(f)?; + if let Some(name) = &ty.name() { + match ty { + TypeOrConstParamData::TypeParamData(ty) => { + if ty.provenance != TypeParamProvenance::TypeParamList { + continue; + } + delim(f)?; + write!(f, "{}", name)?; + if let Some(default) = &ty.default { + write!(f, " = ")?; + default.hir_fmt(f)?; + } + } + TypeOrConstParamData::ConstParamData(c) => { + delim(f)?; + write!(f, "const {}: ", name)?; + c.ty.hir_fmt(f)?; + } } } } - for (_, konst) in params.consts.iter() { - delim(f)?; - write!(f, "const {}: ", konst.name)?; - konst.ty.hir_fmt(f)?; - } write!(f, ">")?; Ok(()) @@ -328,7 +343,7 @@ fn write_where_clause(def: GenericDefId, f: &mut HirFormatter) -> Result<(), Hir // unnamed type targets are displayed inline with the argument itself, e.g. `f: impl Y`. let is_unnamed_type_target = |target: &WherePredicateTypeTarget| match target { WherePredicateTypeTarget::TypeRef(_) => false, - WherePredicateTypeTarget::TypeParam(id) => params.types[*id].name.is_none(), + WherePredicateTypeTarget::TypeOrConstParam(id) => params.types[*id].name().is_none(), }; let has_displayable_predicate = params @@ -344,7 +359,7 @@ fn write_where_clause(def: GenericDefId, f: &mut HirFormatter) -> Result<(), Hir let write_target = |target: &WherePredicateTypeTarget, f: &mut HirFormatter| match target { WherePredicateTypeTarget::TypeRef(ty) => ty.hir_fmt(f), - WherePredicateTypeTarget::TypeParam(id) => match ¶ms.types[*id].name { + WherePredicateTypeTarget::TypeOrConstParam(id) => match ¶ms.types[*id].name() { Some(name) => write!(f, "{}", name), None => write!(f, "{{unnamed}}"), }, diff --git a/crates/hir/src/from_id.rs b/crates/hir/src/from_id.rs index 98c51652d95b..a0b7aa3da22d 100644 --- a/crates/hir/src/from_id.rs +++ b/crates/hir/src/from_id.rs @@ -41,9 +41,10 @@ from_id![ (hir_def::ConstId, crate::Const), (hir_def::FunctionId, crate::Function), (hir_def::ImplId, crate::Impl), + (hir_def::TypeOrConstParamId, crate::TypeOrConstParam), (hir_def::TypeParamId, crate::TypeParam), - (hir_def::LifetimeParamId, crate::LifetimeParam), (hir_def::ConstParamId, crate::ConstParam), + (hir_def::LifetimeParamId, crate::LifetimeParam), (hir_expand::MacroDefId, crate::MacroDef) ]; @@ -71,8 +72,8 @@ impl From for GenericParam { fn from(id: GenericParamId) -> Self { match id { GenericParamId::TypeParamId(it) => GenericParam::TypeParam(it.into()), - GenericParamId::LifetimeParamId(it) => GenericParam::LifetimeParam(it.into()), GenericParamId::ConstParamId(it) => GenericParam::ConstParam(it.into()), + GenericParamId::LifetimeParamId(it) => GenericParam::LifetimeParam(it.into()), } } } @@ -80,9 +81,9 @@ impl From for GenericParam { impl From for GenericParamId { fn from(id: GenericParam) -> Self { match id { - GenericParam::TypeParam(it) => GenericParamId::TypeParamId(it.id), GenericParam::LifetimeParam(it) => GenericParamId::LifetimeParamId(it.id), - GenericParam::ConstParam(it) => GenericParamId::ConstParamId(it.id), + GenericParam::ConstParam(it) => GenericParamId::ConstParamId(it.id.into()), + GenericParam::TypeParam(it) => GenericParamId::TypeParamId(it.id.into()), } } } diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs index 8669b00ca1ac..8683e14f2ad5 100644 --- a/crates/hir/src/has_source.rs +++ b/crates/hir/src/has_source.rs @@ -10,8 +10,8 @@ use hir_expand::InFile; use syntax::ast; use crate::{ - db::HirDatabase, Adt, Const, ConstParam, Enum, Field, FieldSource, Function, Impl, - LifetimeParam, MacroDef, Module, Static, Struct, Trait, TypeAlias, TypeParam, Union, Variant, + db::HirDatabase, Adt, Const, Enum, Field, FieldSource, Function, Impl, LifetimeParam, MacroDef, + Module, Static, Struct, Trait, TypeAlias, TypeOrConstParam, Union, Variant, }; pub trait HasSource { @@ -139,8 +139,8 @@ impl HasSource for Impl { } } -impl HasSource for TypeParam { - type Ast = Either; +impl HasSource for TypeOrConstParam { + type Ast = Either; fn source(self, db: &dyn HirDatabase) -> Option> { let child_source = self.id.parent.child_source(db.upcast()); Some(child_source.map(|it| it[self.id.local_id].clone())) @@ -154,11 +154,3 @@ impl HasSource for LifetimeParam { Some(child_source.map(|it| it[self.id.local_id].clone())) } } - -impl HasSource for ConstParam { - type Ast = ast::ConstParam; - fn source(self, db: &dyn HirDatabase) -> Option> { - let child_source = self.id.parent.child_source(db.upcast()); - Some(child_source.map(|it| it[self.id.local_id].clone())) - } -} diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index e02ba2e7c864..45a4c6a50eb5 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -50,7 +50,7 @@ use hir_def::{ AdtId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, ItemContainerId, LifetimeParamId, LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, - TypeParamId, UnionId, + TypeOrConstParamId, TypeParamId, UnionId, }; use hir_expand::{name::name, MacroCallKind, MacroDefId, MacroDefKind}; use hir_ty::{ @@ -71,7 +71,7 @@ use itertools::Itertools; use nameres::diagnostics::DefDiagnosticKind; use once_cell::unsync::Lazy; use rustc_hash::FxHashSet; -use stdx::{format_to, impl_from}; +use stdx::{format_to, impl_from, never}; use syntax::{ ast::{self, HasAttrs as _, HasDocComments, HasName}, AstNode, AstPtr, SmolStr, SyntaxNodePtr, T, @@ -2007,11 +2007,13 @@ impl_from!( impl GenericDef { pub fn params(self, db: &dyn HirDatabase) -> Vec { let generics = db.generic_params(self.into()); - let ty_params = generics - .types - .iter() - .map(|(local_id, _)| TypeParam { id: TypeParamId { parent: self.into(), local_id } }) - .map(GenericParam::TypeParam); + let ty_params = generics.types.iter().map(|(local_id, _)| { + let toc = TypeOrConstParam { id: TypeOrConstParamId { parent: self.into(), local_id } }; + match toc.split(db) { + Either::Left(x) => GenericParam::ConstParam(x), + Either::Right(x) => GenericParam::TypeParam(x), + } + }); let lt_params = generics .lifetimes .iter() @@ -2019,20 +2021,17 @@ impl GenericDef { id: LifetimeParamId { parent: self.into(), local_id }, }) .map(GenericParam::LifetimeParam); - let const_params = generics - .consts - .iter() - .map(|(local_id, _)| ConstParam { id: ConstParamId { parent: self.into(), local_id } }) - .map(GenericParam::ConstParam); - ty_params.chain(lt_params).chain(const_params).collect() + ty_params.chain(lt_params).collect() } - pub fn type_params(self, db: &dyn HirDatabase) -> Vec { + pub fn type_params(self, db: &dyn HirDatabase) -> Vec { let generics = db.generic_params(self.into()); generics .types .iter() - .map(|(local_id, _)| TypeParam { id: TypeParamId { parent: self.into(), local_id } }) + .map(|(local_id, _)| TypeOrConstParam { + id: TypeOrConstParamId { parent: self.into(), local_id }, + }) .collect() } } @@ -2221,25 +2220,25 @@ impl Label { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum GenericParam { TypeParam(TypeParam), - LifetimeParam(LifetimeParam), ConstParam(ConstParam), + LifetimeParam(LifetimeParam), } -impl_from!(TypeParam, LifetimeParam, ConstParam for GenericParam); +impl_from!(TypeParam, ConstParam, LifetimeParam for GenericParam); impl GenericParam { pub fn module(self, db: &dyn HirDatabase) -> Module { match self { GenericParam::TypeParam(it) => it.module(db), - GenericParam::LifetimeParam(it) => it.module(db), GenericParam::ConstParam(it) => it.module(db), + GenericParam::LifetimeParam(it) => it.module(db), } } pub fn name(self, db: &dyn HirDatabase) -> Name { match self { GenericParam::TypeParam(it) => it.name(db), - GenericParam::LifetimeParam(it) => it.name(db), GenericParam::ConstParam(it) => it.name(db), + GenericParam::LifetimeParam(it) => it.name(db), } } } @@ -2250,19 +2249,23 @@ pub struct TypeParam { } impl TypeParam { + pub fn merge(self) -> TypeOrConstParam { + TypeOrConstParam { id: self.id.into() } + } + pub fn name(self, db: &dyn HirDatabase) -> Name { - let params = db.generic_params(self.id.parent); - params.types[self.id.local_id].name.clone().unwrap_or_else(Name::missing) + self.merge().name(db) } pub fn module(self, db: &dyn HirDatabase) -> Module { - self.id.parent.module(db.upcast()).into() + self.id.parent().module(db.upcast()).into() } pub fn ty(self, db: &dyn HirDatabase) -> Type { - let resolver = self.id.parent.resolver(db.upcast()); - let krate = self.id.parent.module(db.upcast()).krate(); - let ty = TyKind::Placeholder(hir_ty::to_placeholder_idx(db, self.id)).intern(Interner); + let resolver = self.id.parent().resolver(db.upcast()); + let krate = self.id.parent().module(db.upcast()).krate(); + let ty = + TyKind::Placeholder(hir_ty::to_placeholder_idx(db, self.id.into())).intern(Interner); Type::new_with_resolver_inner(db, krate, &resolver, ty) } @@ -2270,7 +2273,7 @@ impl TypeParam { /// parameter, not additional bounds that might be added e.g. by a method if /// the parameter comes from an impl! pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec { - db.generic_predicates_for_param(self.id.parent, self.id, None) + db.generic_predicates_for_param(self.id.parent(), self.id.into(), None) .iter() .filter_map(|pred| match &pred.skip_binders().skip_binders() { hir_ty::WhereClause::Implemented(trait_ref) => { @@ -2282,12 +2285,12 @@ impl TypeParam { } pub fn default(self, db: &dyn HirDatabase) -> Option { - let params = db.generic_defaults(self.id.parent); - let local_idx = hir_ty::param_idx(db, self.id)?; - let resolver = self.id.parent.resolver(db.upcast()); - let krate = self.id.parent.module(db.upcast()).krate(); + let params = db.generic_defaults(self.id.parent()); + let local_idx = hir_ty::param_idx(db, self.id.into())?; + let resolver = self.id.parent().resolver(db.upcast()); + let krate = self.id.parent().module(db.upcast()).krate(); let ty = params.get(local_idx)?.clone(); - let subst = TyBuilder::type_params_subst(db, self.id.parent); + let subst = TyBuilder::type_params_subst(db, self.id.parent()); let ty = ty.substitute(Interner, &subst_prefix(&subst, local_idx)); Some(Type::new_with_resolver_inner(db, krate, &resolver, ty)) } @@ -2319,9 +2322,48 @@ pub struct ConstParam { } impl ConstParam { + pub fn merge(self) -> TypeOrConstParam { + TypeOrConstParam { id: self.id.into() } + } + + pub fn name(self, db: &dyn HirDatabase) -> Name { + let params = db.generic_params(self.id.parent()); + match params.types[self.id.local_id()].name() { + Some(x) => x.clone(), + None => { + never!(); + Name::missing() + } + } + } + + pub fn module(self, db: &dyn HirDatabase) -> Module { + self.id.parent().module(db.upcast()).into() + } + + pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef { + self.id.parent().into() + } + + pub fn ty(self, db: &dyn HirDatabase) -> Type { + let def = self.id.parent(); + let krate = def.module(db.upcast()).krate(); + Type::new(db, krate, def, db.const_param_ty(self.id)) + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct TypeOrConstParam { + pub(crate) id: TypeOrConstParamId, +} + +impl TypeOrConstParam { pub fn name(self, db: &dyn HirDatabase) -> Name { let params = db.generic_params(self.id.parent); - params.consts[self.id.local_id].name.clone() + match params.types[self.id.local_id].name() { + Some(n) => n.clone(), + _ => Name::missing(), + } } pub fn module(self, db: &dyn HirDatabase) -> Module { @@ -2332,10 +2374,23 @@ impl ConstParam { self.id.parent.into() } + pub fn split(self, db: &dyn HirDatabase) -> Either { + let params = db.generic_params(self.id.parent); + match ¶ms.types[self.id.local_id] { + hir_def::generics::TypeOrConstParamData::TypeParamData(_) => { + Either::Right(TypeParam { id: self.id.into() }) + } + hir_def::generics::TypeOrConstParamData::ConstParamData(_) => { + Either::Left(ConstParam { id: self.id.into() }) + } + } + } + pub fn ty(self, db: &dyn HirDatabase) -> Type { - let def = self.id.parent; - let krate = def.module(db.upcast()).krate(); - Type::new(db, krate, def, db.const_param_ty(self.id)) + match self.split(db) { + Either::Left(x) => x.ty(db), + Either::Right(x) => x.ty(db), + } } } diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 2e0dbf82b777..3af47000f41a 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -70,7 +70,7 @@ impl PathResolution { | PathResolution::Local(_) | PathResolution::Macro(_) | PathResolution::ConstParam(_) => None, - PathResolution::TypeParam(param) => Some(TypeNs::GenericParam((*param).into())), + PathResolution::TypeParam(param) => Some(TypeNs::GenericParam(param.merge().into())), PathResolution::SelfType(impl_def) => Some(TypeNs::SelfType((*impl_def).into())), PathResolution::AssocItem(AssocItem::Const(_) | AssocItem::Function(_)) => None, PathResolution::AssocItem(AssocItem::TypeAlias(alias)) => { diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs index dddb8e33dcc0..6f93f8ac9434 100644 --- a/crates/hir/src/semantics/source_to_def.rs +++ b/crates/hir/src/semantics/source_to_def.rs @@ -282,7 +282,7 @@ impl SourceToDefCtx<'_, '_> { pub(super) fn type_param_to_def(&mut self, src: InFile) -> Option { let container: ChildContainer = self.find_generic_param_container(src.syntax())?.into(); let dyn_map = self.cache_for(container, src.file_id); - dyn_map[keys::TYPE_PARAM].get(&src.value).copied() + dyn_map[keys::TYPE_PARAM].get(&src.value).copied().map(|x| x.into()) } pub(super) fn lifetime_param_to_def( @@ -300,7 +300,7 @@ impl SourceToDefCtx<'_, '_> { ) -> Option { let container: ChildContainer = self.find_generic_param_container(src.syntax())?.into(); let dyn_map = self.cache_for(container, src.file_id); - dyn_map[keys::CONST_PARAM].get(&src.value).copied() + dyn_map[keys::CONST_PARAM].get(&src.value).copied().map(|x| x.into()) } pub(super) fn generic_param_to_def( diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index ef32a5891c78..1295d050071f 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -34,7 +34,7 @@ use syntax::{ use crate::{ db::HirDatabase, semantics::PathResolution, Adt, BuiltinAttr, BuiltinType, Const, Field, Function, Local, MacroDef, ModuleDef, Static, Struct, ToolModule, Trait, Type, TypeAlias, - TypeParam, Variant, + TypeOrConstParam, Variant, }; use base_db::CrateId; @@ -609,7 +609,10 @@ fn resolve_hir_path_( let res = match ty { TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), - TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }), + TypeNs::GenericParam(id) => match (TypeOrConstParam { id }).split(db) { + either::Either::Left(x) => PathResolution::ConstParam(x), + either::Either::Right(x) => PathResolution::TypeParam(x), + }, TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { PathResolution::Def(Adt::from(it).into()) } @@ -650,7 +653,7 @@ fn resolve_hir_path_( ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()), ValueNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()), ValueNs::ImplSelf(impl_id) => PathResolution::SelfType(impl_id.into()), - ValueNs::GenericParam(it) => PathResolution::ConstParam(it.into()), + ValueNs::GenericParam(id) => PathResolution::ConstParam(id.into()), }; Some(res) }) @@ -703,7 +706,10 @@ fn resolve_hir_path_qualifier( resolver.resolve_path_in_type_ns_fully(db.upcast(), path.mod_path()).map(|ty| match ty { TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), - TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }), + TypeNs::GenericParam(id) => match (TypeOrConstParam { id }).split(db) { + either::Either::Left(x) => PathResolution::ConstParam(x), + either::Either::Right(x) => PathResolution::TypeParam(x), + }, TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => PathResolution::Def(Adt::from(it).into()), TypeNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()), TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()), diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index 3ff2d7b915ed..694c24a4fee8 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs @@ -367,23 +367,36 @@ impl AttrsWithOwner { AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db), AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db), AttrDefId::GenericParamId(it) => match it { + GenericParamId::ConstParamId(it) => { + let src = it.parent().child_source(db); + RawAttrs::from_attrs_owner( + db, + src.with_value(src.value[it.local_id()].as_ref().either( + |it| match it { + ast::TypeOrConstParam::Type(it) => it as _, + ast::TypeOrConstParam::Const(it) => it as _, + }, + |it| it as _, + )), + ) + } GenericParamId::TypeParamId(it) => { - let src = it.parent.child_source(db); + let src = it.parent().child_source(db); RawAttrs::from_attrs_owner( db, - src.with_value( - src.value[it.local_id].as_ref().either(|it| it as _, |it| it as _), - ), + src.with_value(src.value[it.local_id()].as_ref().either( + |it| match it { + ast::TypeOrConstParam::Type(it) => it as _, + ast::TypeOrConstParam::Const(it) => it as _, + }, + |it| it as _, + )), ) } GenericParamId::LifetimeParamId(it) => { let src = it.parent.child_source(db); RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id])) } - GenericParamId::ConstParamId(it) => { - let src = it.parent.child_source(db); - RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id])) - } }, AttrDefId::ExternBlockId(it) => attrs_from_item_tree(it.lookup(db).id, db), }; @@ -454,9 +467,25 @@ impl AttrsWithOwner { ), AttrDefId::ImplId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new), AttrDefId::GenericParamId(id) => match id { + GenericParamId::ConstParamId(id) => { + id.parent().child_source(db).map(|source| match &source[id.local_id()] { + Either::Left(ast::TypeOrConstParam::Type(id)) => { + ast::AnyHasAttrs::new(id.clone()) + } + Either::Left(ast::TypeOrConstParam::Const(id)) => { + ast::AnyHasAttrs::new(id.clone()) + } + Either::Right(id) => ast::AnyHasAttrs::new(id.clone()), + }) + } GenericParamId::TypeParamId(id) => { - id.parent.child_source(db).map(|source| match &source[id.local_id] { - Either::Left(id) => ast::AnyHasAttrs::new(id.clone()), + id.parent().child_source(db).map(|source| match &source[id.local_id()] { + Either::Left(ast::TypeOrConstParam::Type(id)) => { + ast::AnyHasAttrs::new(id.clone()) + } + Either::Left(ast::TypeOrConstParam::Const(id)) => { + ast::AnyHasAttrs::new(id.clone()) + } Either::Right(id) => ast::AnyHasAttrs::new(id.clone()), }) } @@ -464,10 +493,6 @@ impl AttrsWithOwner { .parent .child_source(db) .map(|source| ast::AnyHasAttrs::new(source[id.local_id].clone())), - GenericParamId::ConstParamId(id) => id - .parent - .child_source(db) - .map(|source| ast::AnyHasAttrs::new(source[id.local_id].clone())), }, AttrDefId::ExternBlockId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new), }; diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs index 7febf1b5e86e..341d444d6196 100644 --- a/crates/hir_def/src/generics.rs +++ b/crates/hir_def/src/generics.rs @@ -9,9 +9,10 @@ use hir_expand::{ name::{AsName, Name}, ExpandResult, HirFileId, InFile, }; -use la_arena::{Arena, ArenaMap}; +use la_arena::{Arena, ArenaMap, Idx}; use once_cell::unsync::Lazy; use std::ops::DerefMut; +use stdx::impl_from; use syntax::ast::{self, HasGenericParams, HasName, HasTypeBounds}; use crate::{ @@ -23,8 +24,8 @@ use crate::{ keys, src::{HasChildSource, HasSource}, type_ref::{LifetimeRef, TypeBound, TypeRef}, - AdtId, ConstParamId, GenericDefId, HasModule, LifetimeParamId, LocalConstParamId, - LocalLifetimeParamId, LocalTypeParamId, Lookup, TypeParamId, + AdtId, GenericDefId, HasModule, LifetimeParamId, LocalLifetimeParamId, LocalTypeOrConstParamId, + Lookup, TypeOrConstParamId, }; /// Data about a generic type parameter (to a function, struct, impl, ...). @@ -55,12 +56,44 @@ pub enum TypeParamProvenance { ArgumentImplTrait, } +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub enum TypeOrConstParamData { + TypeParamData(TypeParamData), + ConstParamData(ConstParamData), +} + +impl TypeOrConstParamData { + pub fn name(&self) -> Option<&Name> { + match self { + TypeOrConstParamData::TypeParamData(x) => x.name.as_ref(), + TypeOrConstParamData::ConstParamData(x) => Some(&x.name), + } + } + + pub fn type_param(&self) -> Option<&TypeParamData> { + match self { + TypeOrConstParamData::TypeParamData(x) => Some(&x), + TypeOrConstParamData::ConstParamData(_) => None, + } + } + + pub fn is_trait_self(&self) -> bool { + match self { + TypeOrConstParamData::TypeParamData(x) => { + x.provenance == TypeParamProvenance::TraitSelf + } + TypeOrConstParamData::ConstParamData(_) => false, + } + } +} + +impl_from!(TypeParamData, ConstParamData for TypeOrConstParamData); + /// Data about the generic parameters of a function, struct, impl, etc. #[derive(Clone, PartialEq, Eq, Debug, Default, Hash)] pub struct GenericParams { - pub types: Arena, + pub types: Arena, pub lifetimes: Arena, - pub consts: Arena, pub where_predicates: Vec, } @@ -89,10 +122,18 @@ pub enum WherePredicate { pub enum WherePredicateTypeTarget { TypeRef(Interned), /// For desugared where predicates that can directly refer to a type param. - TypeParam(LocalTypeParamId), + TypeOrConstParam(LocalTypeOrConstParamId), } impl GenericParams { + // FIXME: almost every usecase of this function is wrong. every one should check + // const generics + pub fn type_iter<'a>( + &'a self, + ) -> impl Iterator, &TypeParamData)> { + self.types.iter().filter_map(|x| x.1.type_param().map(|y| (x.0, y))) + } + pub(crate) fn generic_params_query( db: &dyn DefDatabase, def: GenericDefId, @@ -184,19 +225,32 @@ impl GenericParams { } fn fill_params(&mut self, lower_ctx: &LowerCtx, params: ast::GenericParamList) { - for type_param in params.type_params() { - let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); - // FIXME: Use `Path::from_src` - let default = - type_param.default_type().map(|it| Interned::new(TypeRef::from_ast(lower_ctx, it))); - let param = TypeParamData { - name: Some(name.clone()), - default, - provenance: TypeParamProvenance::TypeParamList, - }; - self.types.alloc(param); - let type_ref = TypeRef::Path(name.into()); - self.fill_bounds(lower_ctx, &type_param, Either::Left(type_ref)); + for type_or_const_param in params.type_or_const_params() { + match type_or_const_param { + ast::TypeOrConstParam::Type(type_param) => { + let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); + // FIXME: Use `Path::from_src` + let default = type_param + .default_type() + .map(|it| Interned::new(TypeRef::from_ast(lower_ctx, it))); + let param = TypeParamData { + name: Some(name.clone()), + default, + provenance: TypeParamProvenance::TypeParamList, + }; + self.types.alloc(param.into()); + let type_ref = TypeRef::Path(name.into()); + self.fill_bounds(lower_ctx, &type_param, Either::Left(type_ref)); + } + ast::TypeOrConstParam::Const(const_param) => { + let name = const_param.name().map_or_else(Name::missing, |it| it.as_name()); + let ty = const_param + .ty() + .map_or(TypeRef::Error, |it| TypeRef::from_ast(lower_ctx, it)); + let param = ConstParamData { name, ty: Interned::new(ty) }; + self.types.alloc(param.into()); + } + } } for lifetime_param in params.lifetime_params() { let name = @@ -206,12 +260,6 @@ impl GenericParams { let lifetime_ref = LifetimeRef::new_name(name); self.fill_bounds(lower_ctx, &lifetime_param, Either::Right(lifetime_ref)); } - for const_param in params.const_params() { - let name = const_param.name().map_or_else(Name::missing, |it| it.as_name()); - let ty = const_param.ty().map_or(TypeRef::Error, |it| TypeRef::from_ast(lower_ctx, it)); - let param = ConstParamData { name, ty: Interned::new(ty) }; - self.consts.alloc(param); - } } fn fill_where_predicates(&mut self, lower_ctx: &LowerCtx, where_clause: ast::WhereClause) { @@ -287,10 +335,10 @@ impl GenericParams { default: None, provenance: TypeParamProvenance::ArgumentImplTrait, }; - let param_id = self.types.alloc(param); + let param_id = self.types.alloc(param.into()); for bound in bounds { self.where_predicates.push(WherePredicate::TypeBound { - target: WherePredicateTypeTarget::TypeParam(param_id), + target: WherePredicateTypeTarget::TypeOrConstParam(param_id), bound: bound.clone(), }); } @@ -311,27 +359,26 @@ impl GenericParams { } pub(crate) fn shrink_to_fit(&mut self) { - let Self { consts, lifetimes, types, where_predicates } = self; - consts.shrink_to_fit(); + let Self { lifetimes, types, where_predicates } = self; lifetimes.shrink_to_fit(); types.shrink_to_fit(); where_predicates.shrink_to_fit(); } - pub fn find_type_by_name(&self, name: &Name) -> Option { + pub fn find_type_or_const_by_name(&self, name: &Name) -> Option { self.types .iter() - .find_map(|(id, p)| if p.name.as_ref() == Some(name) { Some(id) } else { None }) + .find_map(|(id, p)| if p.name().as_ref() == Some(&name) { Some(id) } else { None }) } - pub fn find_const_by_name(&self, name: &Name) -> Option { - self.consts.iter().find_map(|(id, p)| if p.name == *name { Some(id) } else { None }) - } - - pub fn find_trait_self_param(&self) -> Option { + pub fn find_trait_self_param(&self) -> Option { self.types.iter().find_map(|(id, p)| { - if p.provenance == TypeParamProvenance::TraitSelf { - Some(id) + if let TypeOrConstParamData::TypeParamData(p) = p { + if p.provenance == TypeParamProvenance::TraitSelf { + Some(id) + } else { + None + } } else { None } @@ -377,12 +424,12 @@ fn file_id_and_params_of( } } -impl HasChildSource for GenericDefId { - type Value = Either; +impl HasChildSource for GenericDefId { + type Value = Either; fn child_source( &self, db: &dyn DefDatabase, - ) -> InFile> { + ) -> InFile> { let generic_params = db.generic_params(*self); let mut idx_iter = generic_params.types.iter().map(|(idx, _)| idx); @@ -398,7 +445,7 @@ impl HasChildSource for GenericDefId { } if let Some(generic_params_list) = generic_params_list { - for (idx, ast_param) in idx_iter.zip(generic_params_list.type_params()) { + for (idx, ast_param) in idx_iter.zip(generic_params_list.type_or_const_params()) { params.insert(idx, Either::Left(ast_param)); } } @@ -430,29 +477,6 @@ impl HasChildSource for GenericDefId { } } -impl HasChildSource for GenericDefId { - type Value = ast::ConstParam; - fn child_source( - &self, - db: &dyn DefDatabase, - ) -> InFile> { - let generic_params = db.generic_params(*self); - let idx_iter = generic_params.consts.iter().map(|(idx, _)| idx); - - let (file_id, generic_params_list) = file_id_and_params_of(*self, db); - - let mut params = ArenaMap::default(); - - if let Some(generic_params_list) = generic_params_list { - for (idx, ast_param) in idx_iter.zip(generic_params_list.const_params()) { - params.insert(idx, ast_param); - } - } - - InFile::new(file_id, params) - } -} - impl ChildBySource for GenericDefId { fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) { let (gfile_id, generic_params_list) = file_id_and_params_of(*self, db); @@ -461,28 +485,28 @@ impl ChildBySource for GenericDefId { } let generic_params = db.generic_params(*self); - let mut types_idx_iter = generic_params.types.iter().map(|(idx, _)| idx); + let mut toc_idx_iter = generic_params.types.iter().map(|(idx, _)| idx); let lts_idx_iter = generic_params.lifetimes.iter().map(|(idx, _)| idx); - let consts_idx_iter = generic_params.consts.iter().map(|(idx, _)| idx); // For traits the first type index is `Self`, skip it. if let GenericDefId::TraitId(_) = *self { - types_idx_iter.next().unwrap(); // advance_by(1); + toc_idx_iter.next().unwrap(); // advance_by(1); } if let Some(generic_params_list) = generic_params_list { - for (local_id, ast_param) in types_idx_iter.zip(generic_params_list.type_params()) { - let id = TypeParamId { parent: *self, local_id }; - res[keys::TYPE_PARAM].insert(ast_param, id); + for (local_id, ast_param) in + toc_idx_iter.zip(generic_params_list.type_or_const_params()) + { + let id = TypeOrConstParamId { parent: *self, local_id }; + match ast_param { + ast::TypeOrConstParam::Type(a) => res[keys::TYPE_PARAM].insert(a, id), + ast::TypeOrConstParam::Const(a) => res[keys::CONST_PARAM].insert(a, id), + } } for (local_id, ast_param) in lts_idx_iter.zip(generic_params_list.lifetime_params()) { let id = LifetimeParamId { parent: *self, local_id }; res[keys::LIFETIME_PARAM].insert(ast_param, id); } - for (local_id, ast_param) in consts_idx_iter.zip(generic_params_list.const_params()) { - let id = ConstParamId { parent: *self, local_id }; - res[keys::CONST_PARAM].insert(ast_param, id); - } } } } diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index f1b378a3be5f..d215ce101f09 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs @@ -582,11 +582,14 @@ impl<'a> Ctx<'a> { } GenericsOwner::Trait(trait_def) => { // traits get the Self type as an implicit first type parameter - generics.types.alloc(TypeParamData { - name: Some(name![Self]), - default: None, - provenance: TypeParamProvenance::TraitSelf, - }); + generics.types.alloc( + TypeParamData { + name: Some(name![Self]), + default: None, + provenance: TypeParamProvenance::TraitSelf, + } + .into(), + ); // add super traits as bounds on Self // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar let self_param = TypeRef::Path(name![Self].into()); diff --git a/crates/hir_def/src/item_tree/pretty.rs b/crates/hir_def/src/item_tree/pretty.rs index 0df6e97dd463..5b211a142ab4 100644 --- a/crates/hir_def/src/item_tree/pretty.rs +++ b/crates/hir_def/src/item_tree/pretty.rs @@ -6,7 +6,7 @@ use itertools::Itertools; use crate::{ attr::RawAttrs, - generics::{WherePredicate, WherePredicateTypeTarget}, + generics::{TypeOrConstParamData, WherePredicate, WherePredicateTypeTarget}, path::GenericArg, type_ref::TraitBoundModifier, visibility::RawVisibility, @@ -626,7 +626,7 @@ impl<'a> Printer<'a> { } fn print_generic_params(&mut self, params: &GenericParams) { - if params.types.is_empty() && params.lifetimes.is_empty() && params.consts.is_empty() { + if params.types.is_empty() && params.lifetimes.is_empty() { return; } @@ -639,23 +639,21 @@ impl<'a> Printer<'a> { first = false; w!(self, "{}", lt.name); } - for (idx, ty) in params.types.iter() { + for (idx, x) in params.types.iter() { if !first { w!(self, ", "); } first = false; - match &ty.name { - Some(name) => w!(self, "{}", name), - None => w!(self, "_anon_{}", idx.into_raw()), - } - } - for (_, konst) in params.consts.iter() { - if !first { - w!(self, ", "); + match x { + TypeOrConstParamData::TypeParamData(ty) => match &ty.name { + Some(name) => w!(self, "{}", name), + None => w!(self, "_anon_{}", idx.into_raw()), + }, + TypeOrConstParamData::ConstParamData(konst) => { + w!(self, "const {}: ", konst.name); + self.print_type_ref(&konst.ty); + } } - first = false; - w!(self, "const {}: ", konst.name); - self.print_type_ref(&konst.ty); } w!(self, ">"); } @@ -702,10 +700,12 @@ impl<'a> Printer<'a> { match target { WherePredicateTypeTarget::TypeRef(ty) => this.print_type_ref(ty), - WherePredicateTypeTarget::TypeParam(id) => match ¶ms.types[*id].name { - Some(name) => w!(this, "{}", name), - None => w!(this, "_anon_{}", id.into_raw()), - }, + WherePredicateTypeTarget::TypeOrConstParam(id) => { + match ¶ms.types[*id].name() { + Some(name) => w!(this, "{}", name), + None => w!(this, "_anon_{}", id.into_raw()), + } + } } w!(this, ": "); this.print_type_bounds(std::slice::from_ref(bound)); diff --git a/crates/hir_def/src/keys.rs b/crates/hir_def/src/keys.rs index 8cd2d7717214..5f2191430559 100644 --- a/crates/hir_def/src/keys.rs +++ b/crates/hir_def/src/keys.rs @@ -9,8 +9,8 @@ use syntax::{ast, AstNode, AstPtr}; use crate::{ attr::AttrId, dyn_map::{DynMap, Policy}, - ConstId, ConstParamId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId, - StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, + ConstId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId, StaticId, + StructId, TraitId, TypeAliasId, TypeOrConstParamId, UnionId, }; pub type Key = crate::dyn_map::Key>; @@ -28,9 +28,9 @@ pub const ENUM: Key = Key::new(); pub const VARIANT: Key = Key::new(); pub const TUPLE_FIELD: Key = Key::new(); pub const RECORD_FIELD: Key = Key::new(); -pub const TYPE_PARAM: Key = Key::new(); +pub const TYPE_PARAM: Key = Key::new(); +pub const CONST_PARAM: Key = Key::new(); pub const LIFETIME_PARAM: Key = Key::new(); -pub const CONST_PARAM: Key = Key::new(); pub const MACRO: Key = Key::new(); pub const ATTR_MACRO_CALL: Key = Key::new(); diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index bb65d1dec87d..21096166d7b2 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs @@ -279,26 +279,67 @@ pub struct BlockLoc { impl_intern!(BlockId, BlockLoc, intern_block, lookup_intern_block); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct TypeParamId { +pub struct TypeOrConstParamId { pub parent: GenericDefId, - pub local_id: LocalTypeParamId, + pub local_id: LocalTypeOrConstParamId, } -pub type LocalTypeParamId = Idx; +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +/// A TypeOrConstParamId with an invariant that it actually belongs to a type +pub struct TypeParamId(TypeOrConstParamId); + +impl TypeParamId { + pub fn parent(&self) -> GenericDefId { + self.0.parent + } + pub fn local_id(&self) -> LocalTypeOrConstParamId { + self.0.local_id + } +} + +impl From for TypeParamId { + fn from(x: TypeOrConstParamId) -> Self { + Self(x) + } +} +impl From for TypeOrConstParamId { + fn from(x: TypeParamId) -> Self { + x.0 + } +} #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct LifetimeParamId { - pub parent: GenericDefId, - pub local_id: LocalLifetimeParamId, +/// A TypeOrConstParamId with an invariant that it actually belongs to a const +pub struct ConstParamId(TypeOrConstParamId); + +impl ConstParamId { + pub fn parent(&self) -> GenericDefId { + self.0.parent + } + pub fn local_id(&self) -> LocalTypeOrConstParamId { + self.0.local_id + } } -pub type LocalLifetimeParamId = Idx; + +impl From for ConstParamId { + fn from(x: TypeOrConstParamId) -> Self { + Self(x) + } +} +impl From for TypeOrConstParamId { + fn from(x: ConstParamId) -> Self { + x.0 + } +} + +pub type LocalTypeOrConstParamId = Idx; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct ConstParamId { +pub struct LifetimeParamId { pub parent: GenericDefId, - pub local_id: LocalConstParamId, + pub local_id: LocalLifetimeParamId, } -pub type LocalConstParamId = Idx; +pub type LocalLifetimeParamId = Idx; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum ItemContainerId { @@ -322,8 +363,8 @@ impl_from!(StructId, UnionId, EnumId for AdtId); #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum GenericParamId { TypeParamId(TypeParamId), - LifetimeParamId(LifetimeParamId), ConstParamId(ConstParamId), + LifetimeParamId(LifetimeParamId), } impl_from!(TypeParamId, LifetimeParamId, ConstParamId for GenericParamId); @@ -632,9 +673,9 @@ impl AttrDefId { AttrDefId::ExternBlockId(it) => it.lookup(db).container.krate, AttrDefId::GenericParamId(it) => { match it { - GenericParamId::TypeParamId(it) => it.parent, + GenericParamId::TypeParamId(it) => it.parent(), + GenericParamId::ConstParamId(it) => it.parent(), GenericParamId::LifetimeParamId(it) => it.parent, - GenericParamId::ConstParamId(it) => it.parent, } .module(db) .krate diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index 9f68b800a55e..e19e8543b41d 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs @@ -15,7 +15,7 @@ use crate::{ builtin_type::BuiltinType, db::DefDatabase, expr::{ExprId, LabelId, PatId}, - generics::GenericParams, + generics::{GenericParams, TypeOrConstParamData}, intern::Interned, item_scope::{BuiltinShadowMode, BUILTIN_SCOPE}, nameres::DefMap, @@ -25,7 +25,7 @@ use crate::{ AdtId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, ExternBlockId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, ItemContainerId, LifetimeParamId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, - TypeParamId, VariantId, + TypeOrConstParamId, VariantId, }; #[derive(Debug, Clone, Default)] @@ -68,7 +68,7 @@ enum Scope { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum TypeNs { SelfType(ImplId), - GenericParam(TypeParamId), + GenericParam(TypeOrConstParamId), AdtId(AdtId), AdtSelfType(AdtId), // Yup, enum variants are added to the types ns, but any usage of variant as @@ -192,10 +192,12 @@ impl Resolver { Scope::GenericParams { .. } | Scope::ImplDefScope(_) if skip_to_mod => continue, Scope::GenericParams { params, def } => { - if let Some(local_id) = params.find_type_by_name(first_name) { + if let Some(local_id) = params.find_type_or_const_by_name(first_name) { let idx = if path.segments().len() == 1 { None } else { Some(1) }; return Some(( - TypeNs::GenericParam(TypeParamId { local_id, parent: *def }), + TypeNs::GenericParam( + TypeOrConstParamId { local_id, parent: *def }.into(), + ), idx, )); } @@ -285,14 +287,18 @@ impl Resolver { Scope::ExprScope(_) => continue, Scope::GenericParams { params, def } if n_segments > 1 => { - if let Some(local_id) = params.find_type_by_name(first_name) { - let ty = TypeNs::GenericParam(TypeParamId { local_id, parent: *def }); + if let Some(local_id) = params.find_type_or_const_by_name(first_name) { + let ty = TypeNs::GenericParam( + TypeOrConstParamId { local_id, parent: *def }.into(), + ); return Some(ResolveValueResult::Partial(ty, 1)); } } Scope::GenericParams { params, def } if n_segments == 1 => { - if let Some(local_id) = params.find_const_by_name(first_name) { - let val = ValueNs::GenericParam(ConstParamId { local_id, parent: *def }); + if let Some(local_id) = params.find_type_or_const_by_name(first_name) { + let val = ValueNs::GenericParam( + TypeOrConstParamId { local_id, parent: *def }.into(), + ); return Some(ResolveValueResult::ValueNs(val)); } } @@ -521,15 +527,22 @@ impl Scope { Scope::GenericParams { params, def: parent } => { let parent = *parent; for (local_id, param) in params.types.iter() { - if let Some(name) = ¶m.name { - let id = TypeParamId { parent, local_id }; - acc.add(name, ScopeDef::GenericParam(id.into())) + if let Some(name) = ¶m.name() { + let id = TypeOrConstParamId { parent, local_id }; + let data = &db.generic_params(parent).types[local_id]; + acc.add( + name, + ScopeDef::GenericParam(match data { + TypeOrConstParamData::TypeParamData(_) => { + GenericParamId::TypeParamId(id.into()) + } + TypeOrConstParamData::ConstParamData(_) => { + GenericParamId::ConstParamId(id.into()) + } + }), + ); } } - for (local_id, param) in params.consts.iter() { - let id = ConstParamId { parent, local_id }; - acc.add(¶m.name, ScopeDef::GenericParam(id.into())) - } for (local_id, param) in params.lifetimes.iter() { let id = LifetimeParamId { parent, local_id }; acc.add(¶m.name, ScopeDef::GenericParam(id.into())) diff --git a/crates/hir_expand/src/builtin_derive_macro.rs b/crates/hir_expand/src/builtin_derive_macro.rs index dd7d249efa35..d56cd99269ca 100644 --- a/crates/hir_expand/src/builtin_derive_macro.rs +++ b/crates/hir_expand/src/builtin_derive_macro.rs @@ -71,7 +71,7 @@ pub fn find_builtin_derive( struct BasicAdtInfo { name: tt::Ident, - type_params: usize, + type_or_const_params: usize, } fn parse_adt(tt: &tt::Subtree) -> Result { @@ -104,8 +104,9 @@ fn parse_adt(tt: &tt::Subtree) -> Result { .token_by_range(name.syntax().text_range()) .unwrap_or_else(|| TokenId::unspecified()); let name_token = tt::Ident { id: name_token_id, text: name.text().into() }; - let type_params = params.map_or(0, |type_param_list| type_param_list.type_params().count()); - Ok(BasicAdtInfo { name: name_token, type_params }) + let type_or_const_params = + params.map_or(0, |type_param_list| type_param_list.type_or_const_params().count()); + Ok(BasicAdtInfo { name: name_token, type_or_const_params }) } fn make_type_args(n: usize, bound: Vec) -> Vec { @@ -157,8 +158,8 @@ fn expand_simple_derive(tt: &tt::Subtree, trait_path: tt::Subtree) -> ExpandResu let name = info.name; let trait_path_clone = trait_path.token_trees.clone(); let bound = (quote! { : ##trait_path_clone }).token_trees; - let type_params = make_type_args(info.type_params, bound); - let type_args = make_type_args(info.type_params, Vec::new()); + let type_params = make_type_args(info.type_or_const_params, bound); + let type_args = make_type_args(info.type_or_const_params, Vec::new()); let trait_path = trait_path.token_trees; let expanded = quote! { impl ##type_params ##trait_path for #name ##type_args {} diff --git a/crates/hir_ty/src/chalk_ext.rs b/crates/hir_ty/src/chalk_ext.rs index bd5aab1b3d59..d34257f11849 100644 --- a/crates/hir_ty/src/chalk_ext.rs +++ b/crates/hir_ty/src/chalk_ext.rs @@ -3,6 +3,7 @@ use chalk_ir::{FloatTy, IntTy, Mutability, Scalar, UintTy}; use hir_def::{ builtin_type::{BuiltinFloat, BuiltinInt, BuiltinType, BuiltinUint}, + generics::TypeOrConstParamData, type_ref::Rawness, FunctionId, GenericDefId, HasModule, ItemContainerId, Lookup, TraitId, }; @@ -237,27 +238,30 @@ impl TyExt for Ty { let id = from_placeholder_idx(db, *idx); let generic_params = db.generic_params(id.parent); let param_data = &generic_params.types[id.local_id]; - match param_data.provenance { - hir_def::generics::TypeParamProvenance::ArgumentImplTrait => { - let substs = TyBuilder::type_params_subst(db, id.parent); - let predicates = db - .generic_predicates(id.parent) - .iter() - .map(|pred| pred.clone().substitute(Interner, &substs)) - .filter(|wc| match &wc.skip_binders() { - WhereClause::Implemented(tr) => { - &tr.self_type_parameter(Interner) == self - } - WhereClause::AliasEq(AliasEq { - alias: AliasTy::Projection(proj), - ty: _, - }) => &proj.self_type_parameter(Interner) == self, - _ => false, - }) - .collect::>(); - - Some(predicates) - } + match param_data { + TypeOrConstParamData::TypeParamData(p) => match p.provenance { + hir_def::generics::TypeParamProvenance::ArgumentImplTrait => { + let substs = TyBuilder::type_params_subst(db, id.parent); + let predicates = db + .generic_predicates(id.parent) + .iter() + .map(|pred| pred.clone().substitute(Interner, &substs)) + .filter(|wc| match &wc.skip_binders() { + WhereClause::Implemented(tr) => { + &tr.self_type_parameter(Interner) == self + } + WhereClause::AliasEq(AliasEq { + alias: AliasTy::Projection(proj), + ty: _, + }) => &proj.self_type_parameter(Interner) == self, + _ => false, + }) + .collect::>(); + + Some(predicates) + } + _ => None, + }, _ => None, } } diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs index c3b9255baf42..e144dd43f44d 100644 --- a/crates/hir_ty/src/db.rs +++ b/crates/hir_ty/src/db.rs @@ -6,7 +6,7 @@ use std::sync::Arc; use base_db::{impl_intern_key, salsa, CrateId, Upcast}; use hir_def::{ db::DefDatabase, expr::ExprId, BlockId, ConstParamId, DefWithBodyId, FunctionId, GenericDefId, - ImplId, LifetimeParamId, LocalFieldId, TypeParamId, VariantId, + ImplId, LifetimeParamId, LocalFieldId, TypeOrConstParamId, VariantId, }; use la_arena::ArenaMap; @@ -61,7 +61,7 @@ pub trait HirDatabase: DefDatabase + Upcast { fn generic_predicates_for_param( &self, def: GenericDefId, - param_id: TypeParamId, + param_id: TypeOrConstParamId, assoc_name: Option, ) -> Arc<[Binders]>; @@ -94,12 +94,13 @@ pub trait HirDatabase: DefDatabase + Upcast { #[salsa::interned] fn intern_callable_def(&self, callable_def: CallableDefId) -> InternedCallableDefId; #[salsa::interned] - fn intern_type_param_id(&self, param_id: TypeParamId) -> InternedTypeParamId; + fn intern_type_or_const_param_id( + &self, + param_id: TypeOrConstParamId, + ) -> InternedTypeOrConstParamId; #[salsa::interned] fn intern_lifetime_param_id(&self, param_id: LifetimeParamId) -> InternedLifetimeParamId; #[salsa::interned] - fn intern_const_param_id(&self, param_id: ConstParamId) -> InternedConstParamId; - #[salsa::interned] fn intern_impl_trait_id(&self, id: ImplTraitId) -> InternedOpaqueTyId; #[salsa::interned] fn intern_closure(&self, id: (DefWithBodyId, ExprId)) -> InternedClosureId; @@ -186,8 +187,8 @@ fn hir_database_is_object_safe() { } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct InternedTypeParamId(salsa::InternId); -impl_intern_key!(InternedTypeParamId); +pub struct InternedTypeOrConstParamId(salsa::InternId); +impl_intern_key!(InternedTypeOrConstParamId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct InternedLifetimeParamId(salsa::InternId); diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 2020834fbc49..a2644e74b8d6 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs @@ -10,7 +10,7 @@ use hir_def::{ body, db::DefDatabase, find_path, - generics::TypeParamProvenance, + generics::{TypeOrConstParamData, TypeParamProvenance}, intern::{Internable, Interned}, item_scope::ItemInNs, path::{Path, PathKind}, @@ -23,7 +23,6 @@ use itertools::Itertools; use syntax::SmolStr; use crate::{ - const_from_placeholder_idx, db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, lt_from_placeholder_idx, mapping::from_chalk, @@ -319,10 +318,10 @@ impl HirDisplay for Const { ConstValue::BoundVar(idx) => idx.hir_fmt(f), ConstValue::InferenceVar(..) => write!(f, "_"), ConstValue::Placeholder(idx) => { - let id = const_from_placeholder_idx(f.db, idx); + let id = from_placeholder_idx(f.db, idx); let generics = generics(f.db.upcast(), id.parent); - let param_data = &generics.params.consts[id.local_id]; - write!(f, "{}", param_data.name) + let param_data = &generics.params.types[id.local_id]; + write!(f, "{}", param_data.name().unwrap()) } ConstValue::Concrete(c) => write!(f, "{}", c.interned), } @@ -682,34 +681,39 @@ impl HirDisplay for Ty { let id = from_placeholder_idx(f.db, *idx); let generics = generics(f.db.upcast(), id.parent); let param_data = &generics.params.types[id.local_id]; - match param_data.provenance { - TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => { - write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? - } - TypeParamProvenance::ArgumentImplTrait => { - let substs = generics.type_params_subst(f.db); - let bounds = - f.db.generic_predicates(id.parent) - .iter() - .map(|pred| pred.clone().substitute(Interner, &substs)) - .filter(|wc| match &wc.skip_binders() { - WhereClause::Implemented(tr) => { - &tr.self_type_parameter(Interner) == self - } - WhereClause::AliasEq(AliasEq { - alias: AliasTy::Projection(proj), - ty: _, - }) => &proj.self_type_parameter(Interner) == self, - _ => false, - }) - .collect::>(); - let krate = id.parent.module(f.db.upcast()).krate(); - write_bounds_like_dyn_trait_with_prefix( - "impl", - &bounds, - SizedByDefault::Sized { anchor: krate }, - f, - )?; + match param_data { + TypeOrConstParamData::TypeParamData(p) => match p.provenance { + TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => { + write!(f, "{}", p.name.clone().unwrap_or_else(Name::missing))? + } + TypeParamProvenance::ArgumentImplTrait => { + let substs = generics.type_params_subst(f.db); + let bounds = + f.db.generic_predicates(id.parent) + .iter() + .map(|pred| pred.clone().substitute(Interner, &substs)) + .filter(|wc| match &wc.skip_binders() { + WhereClause::Implemented(tr) => { + &tr.self_type_parameter(Interner) == self + } + WhereClause::AliasEq(AliasEq { + alias: AliasTy::Projection(proj), + ty: _, + }) => &proj.self_type_parameter(Interner) == self, + _ => false, + }) + .collect::>(); + let krate = id.parent.module(f.db.upcast()).krate(); + write_bounds_like_dyn_trait_with_prefix( + "impl", + &bounds, + SizedByDefault::Sized { anchor: krate }, + f, + )?; + } + }, + TypeOrConstParamData::ConstParamData(p) => { + write!(f, "{}", p.name)?; } } } diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index ad54b72b4b55..c52dd3e8edb6 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -10,6 +10,7 @@ use std::{ use chalk_ir::{cast::Cast, fold::Shift, Mutability, TyVariableKind}; use hir_def::{ expr::{ArithOp, Array, BinaryOp, CmpOp, Expr, ExprId, Literal, Ordering, Statement, UnaryOp}, + generics::TypeOrConstParamData, path::{GenericArg, GenericArgs}, resolver::resolver_for_expr, FieldId, FunctionId, ItemContainerId, Lookup, @@ -1037,8 +1038,15 @@ impl<'a> InferenceContext<'a> { let total_len = parent_params + type_params + impl_trait_params; let mut substs = Vec::with_capacity(total_len); // Parent arguments are unknown - for _ in def_generics.iter_parent() { - substs.push(self.table.new_type_var()); + for (_id, param) in def_generics.iter_parent() { + match param { + TypeOrConstParamData::TypeParamData(_) => { + substs.push(self.table.new_type_var()); + } + TypeOrConstParamData::ConstParamData(_) => { + // FIXME: here we should do something + } + } } // handle provided type arguments if let Some(generic_args) = generic_args { diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index f1280fcc101c..b57ad6206846 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -40,7 +40,7 @@ use chalk_ir::{ use hir_def::{ expr::ExprId, type_ref::{ConstScalar, Rawness}, - TypeParamId, + TypeOrConstParamId, }; use crate::{db::HirDatabase, utils::generics}; @@ -55,9 +55,9 @@ pub use lower::{ TyDefId, TyLoweringContext, ValueTyDefId, }; pub use mapping::{ - const_from_placeholder_idx, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, - from_placeholder_idx, lt_from_placeholder_idx, to_assoc_type_id, to_chalk_trait_id, - to_foreign_def_id, to_placeholder_idx, + from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx, + lt_from_placeholder_idx, to_assoc_type_id, to_chalk_trait_id, to_foreign_def_id, + to_placeholder_idx, }; pub use traits::TraitEnvironment; pub use utils::all_super_traits; @@ -129,7 +129,7 @@ pub fn subst_prefix(s: &Substitution, n: usize) -> Substitution { } /// Return an index of a parameter in the generic type parameter list by it's id. -pub fn param_idx(db: &dyn HirDatabase, id: TypeParamId) -> Option { +pub fn param_idx(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option { generics(db.upcast(), id.parent).param_idx(id) } diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index a140dd4057c6..3444ffd2020e 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -10,6 +10,7 @@ use std::{iter, sync::Arc}; use base_db::CrateId; use chalk_ir::{cast::Cast, fold::Shift, interner::HasInterner, Mutability, Safety}; +use hir_def::generics::TypeOrConstParamData; use hir_def::intern::Interned; use hir_def::{ adt::StructKind, @@ -19,15 +20,16 @@ use hir_def::{ path::{GenericArg, Path, PathSegment, PathSegments}, resolver::{HasResolver, Resolver, TypeNs}, type_ref::{TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef}, - AdtId, AssocItemId, ConstId, ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, - HasModule, ImplId, ItemContainerId, LocalFieldId, Lookup, StaticId, StructId, TraitId, - TypeAliasId, TypeParamId, UnionId, VariantId, + AdtId, AssocItemId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, + ImplId, ItemContainerId, LocalFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, + UnionId, VariantId, }; +use hir_def::{ConstParamId, TypeOrConstParamId}; use hir_expand::{name::Name, ExpandResult}; use la_arena::ArenaMap; use rustc_hash::FxHashSet; use smallvec::SmallVec; -use stdx::impl_from; +use stdx::{impl_from, never}; use syntax::{ast, SmolStr}; use crate::all_super_traits; @@ -267,7 +269,7 @@ impl<'a> TyLoweringContext<'a> { if let Some(def) = self.resolver.generic_def() { let generics = generics(self.db.upcast(), def); let param = generics - .iter() + .type_iter() .filter(|(_, data)| { data.provenance == TypeParamProvenance::ArgumentImplTrait }) @@ -353,7 +355,7 @@ impl<'a> TyLoweringContext<'a> { /// This is only for `generic_predicates_for_param`, where we can't just /// lower the self types of the predicates since that could lead to cycles. /// So we just check here if the `type_ref` resolves to a generic param, and which. - fn lower_ty_only_param(&self, type_ref: &TypeRef) -> Option { + fn lower_ty_only_param(&self, type_ref: &TypeRef) -> Option { let path = match type_ref { TypeRef::Path(path) => path, _ => return None, @@ -469,10 +471,10 @@ impl<'a> TyLoweringContext<'a> { ); match self.type_param_mode { TypeParamLoweringMode::Placeholder => { - TyKind::Placeholder(to_placeholder_idx(self.db, param_id)) + TyKind::Placeholder(to_placeholder_idx(self.db, param_id.into())) } TypeParamLoweringMode::Variable => { - let idx = generics.param_idx(param_id).expect("matching generics"); + let idx = generics.param_idx(param_id.into()).expect("matching generics"); TyKind::BoundVar(BoundVar::new(self.in_binders, idx)) } } @@ -758,11 +760,13 @@ impl<'a> TyLoweringContext<'a> { | WherePredicate::TypeBound { target, bound } => { let self_ty = match target { WherePredicateTypeTarget::TypeRef(type_ref) => self.lower_ty(type_ref), - WherePredicateTypeTarget::TypeParam(param_id) => { + WherePredicateTypeTarget::TypeOrConstParam(param_id) => { let generic_def = self.resolver.generic_def().expect("generics in scope"); let generics = generics(self.db.upcast(), generic_def); - let param_id = - hir_def::TypeParamId { parent: generic_def, local_id: *param_id }; + let param_id = hir_def::TypeOrConstParamId { + parent: generic_def, + local_id: *param_id, + }; let placeholder = to_placeholder_idx(self.db, param_id); match self.type_param_mode { TypeParamLoweringMode::Placeholder => TyKind::Placeholder(placeholder), @@ -973,7 +977,7 @@ fn named_associated_type_shorthand_candidates( db.impl_trait(impl_id)?.into_value_and_skipped_binders().0, ), TypeNs::GenericParam(param_id) => { - let predicates = db.generic_predicates_for_param(def, param_id, assoc_name); + let predicates = db.generic_predicates_for_param(def, param_id.into(), assoc_name); let res = predicates.iter().find_map(|pred| match pred.skip_binders().skip_binders() { // FIXME: how to correctly handle higher-ranked bounds here? WhereClause::Implemented(tr) => search( @@ -989,9 +993,7 @@ fn named_associated_type_shorthand_candidates( // Handle `Self::Type` referring to own associated type in trait definitions if let GenericDefId::TraitId(trait_id) = param_id.parent { let generics = generics(db.upcast(), trait_id.into()); - if generics.params.types[param_id.local_id].provenance - == TypeParamProvenance::TraitSelf - { + if generics.params.types[param_id.local_id].is_trait_self() { let trait_ref = TyBuilder::trait_ref(db, trait_id) .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0) .build(); @@ -1036,7 +1038,7 @@ pub(crate) fn field_types_query( pub(crate) fn generic_predicates_for_param_query( db: &dyn HirDatabase, def: GenericDefId, - param_id: TypeParamId, + param_id: TypeOrConstParamId, assoc_name: Option, ) -> Arc<[Binders]> { let resolver = def.resolver(db.upcast()); @@ -1051,11 +1053,11 @@ pub(crate) fn generic_predicates_for_param_query( | WherePredicate::TypeBound { target, bound, .. } => { match target { WherePredicateTypeTarget::TypeRef(type_ref) => { - if ctx.lower_ty_only_param(type_ref) != Some(param_id) { + if ctx.lower_ty_only_param(type_ref) != Some(param_id.into()) { return false; } } - WherePredicateTypeTarget::TypeParam(local_id) => { + WherePredicateTypeTarget::TypeOrConstParam(local_id) => { if *local_id != param_id.local_id { return false; } @@ -1105,7 +1107,7 @@ pub(crate) fn generic_predicates_for_param_recover( _db: &dyn HirDatabase, _cycle: &[String], _def: &GenericDefId, - _param_id: &TypeParamId, + _param_id: &TypeOrConstParamId, _assoc_name: &Option, ) -> Arc<[Binders]> { Arc::new([]) @@ -1233,7 +1235,7 @@ pub(crate) fn generic_defaults_query( let generic_params = generics(db.upcast(), def); let defaults = generic_params - .iter() + .type_iter() .enumerate() .map(|(idx, (_, p))| { let mut ty = @@ -1267,7 +1269,7 @@ pub(crate) fn generic_defaults_recover( // we still need one default per parameter let defaults = generic_params - .iter() + .type_iter() .enumerate() .map(|(idx, _)| { let ty = TyKind::Error.intern(Interner); @@ -1497,13 +1499,19 @@ pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binde make_binders(&generics, ctx.lower_ty(&impl_data.self_ty)) } +// returns None if def is a type arg pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty { - let parent_data = db.generic_params(def.parent); - let data = &parent_data.consts[def.local_id]; - let resolver = def.parent.resolver(db.upcast()); + let parent_data = db.generic_params(def.parent()); + let data = &parent_data.types[def.local_id()]; + let resolver = def.parent().resolver(db.upcast()); let ctx = TyLoweringContext::new(db, &resolver); - - ctx.lower_ty(&data.ty) + match data { + TypeOrConstParamData::TypeParamData(_) => { + never!(); + Ty::new(Interner, TyKind::Error) + } + TypeOrConstParamData::ConstParamData(d) => ctx.lower_ty(&d.ty), + } } pub(crate) fn impl_self_ty_recover( diff --git a/crates/hir_ty/src/mapping.rs b/crates/hir_ty/src/mapping.rs index 5e86fafe5d6b..d765fee0e1f4 100644 --- a/crates/hir_ty/src/mapping.rs +++ b/crates/hir_ty/src/mapping.rs @@ -6,7 +6,7 @@ use chalk_solve::rust_ir; use base_db::salsa::{self, InternKey}; -use hir_def::{ConstParamId, LifetimeParamId, TraitId, TypeAliasId, TypeParamId}; +use hir_def::{LifetimeParamId, TraitId, TypeAliasId, TypeOrConstParamId}; use crate::{ chalk_db, db::HirDatabase, AssocTypeId, CallableDefId, ChalkTraitId, FnDefId, ForeignDefId, @@ -119,14 +119,14 @@ pub fn from_assoc_type_id(id: AssocTypeId) -> TypeAliasId { salsa::InternKey::from_intern_id(id.0) } -pub fn from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> TypeParamId { +pub fn from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> TypeOrConstParamId { assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT); let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx)); - db.lookup_intern_type_param_id(interned_id) + db.lookup_intern_type_or_const_param_id(interned_id) } -pub fn to_placeholder_idx(db: &dyn HirDatabase, id: TypeParamId) -> PlaceholderIndex { - let interned_id = db.intern_type_param_id(id); +pub fn to_placeholder_idx(db: &dyn HirDatabase, id: TypeOrConstParamId) -> PlaceholderIndex { + let interned_id = db.intern_type_or_const_param_id(id); PlaceholderIndex { ui: chalk_ir::UniverseIndex::ROOT, idx: salsa::InternKey::as_intern_id(&interned_id).as_usize(), @@ -139,12 +139,6 @@ pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> L db.lookup_intern_lifetime_param_id(interned_id) } -pub fn const_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> ConstParamId { - assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT); - let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx)); - db.lookup_intern_const_param_id(interned_id) -} - pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId { chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id)) } diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs index c5646e08e6cf..cf8e284c6274 100644 --- a/crates/hir_ty/src/utils.rs +++ b/crates/hir_ty/src/utils.rs @@ -8,13 +8,14 @@ use chalk_ir::{fold::Shift, BoundVar, DebruijnIndex}; use hir_def::{ db::DefDatabase, generics::{ - GenericParams, TypeParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget, + GenericParams, TypeOrConstParamData, TypeParamData, TypeParamProvenance, WherePredicate, + WherePredicateTypeTarget, }, intern::Interned, path::Path, resolver::{HasResolver, TypeNs}, type_ref::{TraitBoundModifier, TypeRef}, - GenericDefId, ItemContainerId, Lookup, TraitId, TypeAliasId, TypeParamId, + GenericDefId, ItemContainerId, Lookup, TraitId, TypeAliasId, TypeOrConstParamId, }; use hir_expand::name::{name, Name}; use rustc_hash::FxHashSet; @@ -55,7 +56,9 @@ fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> SmallVec<[Trait TypeRef::Path(p) if p == &Path::from(name![Self]) => bound.as_path(), _ => None, }, - WherePredicateTypeTarget::TypeParam(local_id) if Some(*local_id) == trait_self => { + WherePredicateTypeTarget::TypeOrConstParam(local_id) + if Some(*local_id) == trait_self => + { bound.as_path() } _ => None, @@ -80,7 +83,7 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec TypeParamId { parent: trait_ref.hir_trait_id().into(), local_id: p }, + Some(p) => TypeOrConstParamId { parent: trait_ref.hir_trait_id().into(), local_id: p }, None => return Vec::new(), }; db.generic_predicates_for_param(trait_self.parent, trait_self, None) @@ -181,34 +184,33 @@ pub(crate) struct Generics { } impl Generics { - pub(crate) fn iter<'a>( + // FIXME: we should drop this and handle const and type generics at the same time + pub(crate) fn type_iter<'a>( &'a self, - ) -> impl Iterator + 'a { + ) -> impl Iterator + 'a { self.parent_generics .as_ref() .into_iter() .flat_map(|it| { it.params - .types - .iter() - .map(move |(local_id, p)| (TypeParamId { parent: it.def, local_id }, p)) + .type_iter() + .map(move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p)) }) .chain( - self.params - .types - .iter() - .map(move |(local_id, p)| (TypeParamId { parent: self.def, local_id }, p)), + self.params.type_iter().map(move |(local_id, p)| { + (TypeOrConstParamId { parent: self.def, local_id }, p) + }), ) } pub(crate) fn iter_parent<'a>( &'a self, - ) -> impl Iterator + 'a { + ) -> impl Iterator + 'a { self.parent_generics.as_ref().into_iter().flat_map(|it| { it.params .types .iter() - .map(move |(local_id, p)| (TypeParamId { parent: it.def, local_id }, p)) + .map(move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p)) }) } @@ -219,7 +221,8 @@ impl Generics { /// (total, parents, child) pub(crate) fn len_split(&self) -> (usize, usize, usize) { let parent = self.parent_generics.as_ref().map_or(0, |p| p.len()); - let child = self.params.types.len(); + // FIXME: we should not filter const generics here, but at now it breaks tests + let child = self.params.types.iter().filter_map(|x| x.1.type_param()).count(); (parent + child, parent, child) } @@ -230,28 +233,31 @@ impl Generics { .params .types .iter() - .filter(|(_, p)| p.provenance == TypeParamProvenance::TraitSelf) + .filter_map(|x| x.1.type_param()) + .filter(|p| p.provenance == TypeParamProvenance::TraitSelf) .count(); let list_params = self .params .types .iter() - .filter(|(_, p)| p.provenance == TypeParamProvenance::TypeParamList) + .filter_map(|x| x.1.type_param()) + .filter(|p| p.provenance == TypeParamProvenance::TypeParamList) .count(); let impl_trait_params = self .params .types .iter() - .filter(|(_, p)| p.provenance == TypeParamProvenance::ArgumentImplTrait) + .filter_map(|x| x.1.type_param()) + .filter(|p| p.provenance == TypeParamProvenance::ArgumentImplTrait) .count(); (parent, self_params, list_params, impl_trait_params) } - pub(crate) fn param_idx(&self, param: TypeParamId) -> Option { + pub(crate) fn param_idx(&self, param: TypeOrConstParamId) -> Option { Some(self.find_param(param)?.0) } - fn find_param(&self, param: TypeParamId) -> Option<(usize, &TypeParamData)> { + fn find_param(&self, param: TypeOrConstParamId) -> Option<(usize, &TypeOrConstParamData)> { if param.parent == self.def { let (idx, (_local_id, data)) = self .params @@ -271,7 +277,7 @@ impl Generics { pub(crate) fn bound_vars_subst(&self, debruijn: DebruijnIndex) -> Substitution { Substitution::from_iter( Interner, - self.iter() + self.type_iter() .enumerate() .map(|(idx, _)| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(Interner)), ) @@ -281,7 +287,7 @@ impl Generics { pub(crate) fn type_params_subst(&self, db: &dyn HirDatabase) -> Substitution { Substitution::from_iter( Interner, - self.iter().map(|(id, _)| { + self.type_iter().map(|(id, _)| { TyKind::Placeholder(crate::to_placeholder_idx(db, id)).intern(Interner) }), ) diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index df0ca941c99d..ab10bc6ef5c1 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -2913,6 +2913,27 @@ fn main() { ); } +#[test] +fn const_generic_order() { + check( + r#" +struct Foo; +struct S$0T(T); +"#, + expect![[r#" + *ST* + + ```rust + test + ``` + + ```rust + struct ST + ``` + "#]], + ); +} + #[test] fn hover_self_param_shows_type() { check( diff --git a/crates/ide/src/navigation_target.rs b/crates/ide/src/navigation_target.rs index 834668960f36..97545bd20ddf 100644 --- a/crates/ide/src/navigation_target.rs +++ b/crates/ide/src/navigation_target.rs @@ -12,6 +12,7 @@ use ide_db::{ SymbolKind, }; use ide_db::{defs::Definition, RootDatabase}; +use stdx::never; use syntax::{ ast::{self, HasName}, match_ast, AstNode, SmolStr, SyntaxNode, TextRange, @@ -435,9 +436,18 @@ impl ToNav for hir::Label { impl TryToNav for hir::TypeParam { fn try_to_nav(&self, db: &RootDatabase) -> Option { - let InFile { file_id, value } = self.source(db)?; + let InFile { file_id, value } = self.merge().source(db)?; let name = self.name(db).to_smol_str(); + let value = match value { + Either::Left(ast::TypeOrConstParam::Type(x)) => Either::Left(x), + Either::Left(ast::TypeOrConstParam::Const(_)) => { + never!(); + return None; + } + Either::Right(x) => Either::Right(x), + }; + let range = |syntax: &_| InFile::new(file_id, syntax).original_file_range(db); let focus_range = |syntax: &_| InFile::new(file_id, syntax).original_file_range_opt(db); let FileRange { file_id, range: full_range } = match &value { @@ -464,6 +474,12 @@ impl TryToNav for hir::TypeParam { } } +impl TryToNav for hir::TypeOrConstParam { + fn try_to_nav(&self, db: &RootDatabase) -> Option { + self.split(db).try_to_nav(db) + } +} + impl TryToNav for hir::LifetimeParam { fn try_to_nav(&self, db: &RootDatabase) -> Option { let InFile { file_id, value } = self.source(db)?; @@ -486,9 +502,17 @@ impl TryToNav for hir::LifetimeParam { impl TryToNav for hir::ConstParam { fn try_to_nav(&self, db: &RootDatabase) -> Option { - let InFile { file_id, value } = self.source(db)?; + let InFile { file_id, value } = self.merge().source(db)?; let name = self.name(db).to_smol_str(); + let value = match value { + Either::Left(ast::TypeOrConstParam::Const(x)) => x, + _ => { + never!(); + return None; + } + }; + let focus_range = value.name().and_then(|it| orig_focus_range(db, file_id, it.syntax())); let FileRange { file_id, range: full_range } = InFile::new(file_id, value.syntax()).original_file_range(db); diff --git a/crates/ide/src/syntax_highlighting/inject.rs b/crates/ide/src/syntax_highlighting/inject.rs index a3b05ee26332..ec1df6d1de5a 100644 --- a/crates/ide/src/syntax_highlighting/inject.rs +++ b/crates/ide/src/syntax_highlighting/inject.rs @@ -259,8 +259,8 @@ fn module_def_to_hl_tag(def: Definition) -> HlTag { Definition::Local(_) => SymbolKind::Local, Definition::GenericParam(gp) => match gp { hir::GenericParam::TypeParam(_) => SymbolKind::TypeParam, - hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam, hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam, + hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam, }, Definition::Label(_) => SymbolKind::Label, Definition::BuiltinAttr(_) => SymbolKind::BuiltinAttr, diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html index a04a211825d4..bd8d9faae84d 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html @@ -109,6 +109,13 @@ /// let foobar = Foo::new().bar(); /// ``` /// + /// ``` + /// // functions + /// fn foo<T, const X: usize>(arg: i32) { + /// let x: T = X; + /// } + /// ``` + /// /// ```sh /// echo 1 /// ``` diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs index 27686ab9447b..c14e3330e312 100644 --- a/crates/ide/src/syntax_highlighting/tests.rs +++ b/crates/ide/src/syntax_highlighting/tests.rs @@ -599,6 +599,13 @@ impl Foo { /// let foobar = Foo::new().bar(); /// ``` /// + /// ``` + /// // functions + /// fn foo(arg: i32) { + /// let x: T = X; + /// } + /// ``` + /// /// ```sh /// echo 1 /// ``` diff --git a/crates/ide_assists/src/handlers/generate_default_from_new.rs b/crates/ide_assists/src/handlers/generate_default_from_new.rs index 680ec0d1cd87..6f158ceb993d 100644 --- a/crates/ide_assists/src/handlers/generate_default_from_new.rs +++ b/crates/ide_assists/src/handlers/generate_default_from_new.rs @@ -85,21 +85,23 @@ fn generate_trait_impl_text_from_impl(impl_: &ast::Impl, trait_text: &str, code: if let Some(generic_params) = &generic_params { let lifetimes = generic_params.lifetime_params().map(|lt| format!("{}", lt.syntax())); - let type_params = generic_params.type_params().map(|type_param| { - let mut buf = String::new(); - if let Some(it) = type_param.name() { - format_to!(buf, "{}", it.syntax()); + let toc_params = generic_params.type_or_const_params().map(|toc_param| match toc_param { + ast::TypeOrConstParam::Type(type_param) => { + let mut buf = String::new(); + if let Some(it) = type_param.name() { + format_to!(buf, "{}", it.syntax()); + } + if let Some(it) = type_param.colon_token() { + format_to!(buf, "{} ", it); + } + if let Some(it) = type_param.type_bound_list() { + format_to!(buf, "{}", it.syntax()); + } + buf } - if let Some(it) = type_param.colon_token() { - format_to!(buf, "{} ", it); - } - if let Some(it) = type_param.type_bound_list() { - format_to!(buf, "{}", it.syntax()); - } - buf + ast::TypeOrConstParam::Const(const_param) => const_param.syntax().to_string(), }); - let const_params = generic_params.const_params().map(|t| t.syntax().to_string()); - let generics = lifetimes.chain(type_params).chain(const_params).format(", "); + let generics = lifetimes.chain(toc_params).format(", "); format_to!(buf, "<{}>", generics); } diff --git a/crates/ide_assists/src/handlers/move_bounds.rs b/crates/ide_assists/src/handlers/move_bounds.rs index 01c6eea225b8..425dba1a75fd 100644 --- a/crates/ide_assists/src/handlers/move_bounds.rs +++ b/crates/ide_assists/src/handlers/move_bounds.rs @@ -23,8 +23,11 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { let type_param_list = ctx.find_node_at_offset::()?; - let mut type_params = type_param_list.type_params(); - if type_params.all(|p| p.type_bound_list().is_none()) { + let mut type_params = type_param_list.type_or_const_params(); + if type_params.all(|p| match p { + ast::TypeOrConstParam::Type(t) => t.type_bound_list().is_none(), + ast::TypeOrConstParam::Const(_) => true, + }) { return None; } @@ -50,7 +53,11 @@ pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext } }; - for type_param in type_param_list.type_params() { + for toc_param in type_param_list.type_or_const_params() { + let type_param = match toc_param { + ast::TypeOrConstParam::Type(x) => x, + ast::TypeOrConstParam::Const(_) => continue, + }; if let Some(tbl) = type_param.type_bound_list() { if let Some(predicate) = build_predicate(type_param) { where_clause.add_predicate(predicate) diff --git a/crates/ide_assists/src/utils.rs b/crates/ide_assists/src/utils.rs index e1ee3f3ad450..116f150ef2db 100644 --- a/crates/ide_assists/src/utils.rs +++ b/crates/ide_assists/src/utils.rs @@ -435,7 +435,11 @@ fn generate_impl_text_inner(adt: &ast::Adt, trait_text: Option<&str>, code: &str buf.push_str("impl"); if let Some(generic_params) = &generic_params { let lifetimes = generic_params.lifetime_params().map(|lt| format!("{}", lt.syntax())); - let type_params = generic_params.type_params().map(|type_param| { + let toc_params = generic_params.type_or_const_params().map(|toc_param| { + let type_param = match toc_param { + ast::TypeOrConstParam::Type(x) => x, + ast::TypeOrConstParam::Const(x) => return x.syntax().to_string(), + }; let mut buf = String::new(); if let Some(it) = type_param.name() { format_to!(buf, "{}", it.syntax()); @@ -448,8 +452,7 @@ fn generate_impl_text_inner(adt: &ast::Adt, trait_text: Option<&str>, code: &str } buf }); - let const_params = generic_params.const_params().map(|t| t.syntax().to_string()); - let generics = lifetimes.chain(type_params).chain(const_params).format(", "); + let generics = lifetimes.chain(toc_params).format(", "); format_to!(buf, "<{}>", generics); } buf.push(' '); @@ -463,15 +466,11 @@ fn generate_impl_text_inner(adt: &ast::Adt, trait_text: Option<&str>, code: &str .lifetime_params() .filter_map(|it| it.lifetime()) .map(|it| SmolStr::from(it.text())); - let type_params = generic_params - .type_params() - .filter_map(|it| it.name()) - .map(|it| SmolStr::from(it.text())); - let const_params = generic_params - .const_params() + let toc_params = generic_params + .type_or_const_params() .filter_map(|it| it.name()) .map(|it| SmolStr::from(it.text())); - format_to!(buf, "<{}>", lifetime_params.chain(type_params).chain(const_params).format(", ")) + format_to!(buf, "<{}>", lifetime_params.chain(toc_params).format(", ")) } match adt.where_clause() { diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs index 027fb5352715..d5618f147433 100644 --- a/crates/ide_completion/src/render.rs +++ b/crates/ide_completion/src/render.rs @@ -201,8 +201,8 @@ fn render_resolution_( ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType, ScopeDef::GenericParam(param) => CompletionItemKind::SymbolKind(match param { hir::GenericParam::TypeParam(_) => SymbolKind::TypeParam, - hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam, hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam, + hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam, }), ScopeDef::Local(..) => CompletionItemKind::SymbolKind(SymbolKind::Local), ScopeDef::Label(..) => CompletionItemKind::SymbolKind(SymbolKind::Label), diff --git a/crates/ide_db/src/apply_change.rs b/crates/ide_db/src/apply_change.rs index 6c085ffc9790..98b0e9c947a7 100644 --- a/crates/ide_db/src/apply_change.rs +++ b/crates/ide_db/src/apply_change.rs @@ -129,12 +129,12 @@ impl RootDatabase { hir::db::FnDefDatumQuery hir::db::ReturnTypeImplTraitsQuery hir::db::InternCallableDefQuery - hir::db::InternTypeParamIdQuery + hir::db::InternTypeOrConstParamIdQuery hir::db::InternImplTraitIdQuery hir::db::InternClosureQuery hir::db::AssociatedTyValueQuery hir::db::TraitSolveQueryQuery - hir::db::InternTypeParamIdQuery + hir::db::InternTypeOrConstParamIdQuery // SymbolsDatabase crate::symbol_index::ModuleSymbolsQuery diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs index e41c97ea9532..80988986ce58 100644 --- a/crates/ide_db/src/defs.rs +++ b/crates/ide_db/src/defs.rs @@ -482,9 +482,9 @@ impl From for Definition { } PathResolution::Local(local) => Definition::Local(local), PathResolution::TypeParam(par) => Definition::GenericParam(par.into()), + PathResolution::ConstParam(par) => Definition::GenericParam(par.into()), PathResolution::Macro(def) => Definition::Macro(def), PathResolution::SelfType(impl_def) => Definition::SelfType(impl_def), - PathResolution::ConstParam(par) => Definition::GenericParam(par.into()), PathResolution::BuiltinAttr(attr) => Definition::BuiltinAttr(attr), PathResolution::ToolModule(tool) => Definition::ToolModule(tool), } diff --git a/crates/ide_db/src/path_transform.rs b/crates/ide_db/src/path_transform.rs index 524af7fe8f01..a293713026f5 100644 --- a/crates/ide_db/src/path_transform.rs +++ b/crates/ide_db/src/path_transform.rs @@ -1,6 +1,7 @@ //! See [`PathTransform`]. use crate::helpers::mod_path_to_ast; +use either::Either; use hir::{HirDisplay, SemanticsScope}; use rustc_hash::FxHashMap; use syntax::{ @@ -94,15 +95,20 @@ impl<'a> PathTransform<'a> { // a default type. If they do, go for that type from `hir` to `ast` so // the resulting change can be applied correctly. .zip(self.substs.iter().map(Some).chain(std::iter::repeat(None))) - .filter_map(|(k, v)| match v { - Some(v) => Some((k, v.clone())), - None => { - let default = k.default(db)?; - Some(( - k, - ast::make::ty(&default.display_source_code(db, source_module.into()).ok()?), - )) - } + .filter_map(|(k, v)| match k.split(db) { + Either::Left(_) => None, + Either::Right(t) => match v { + Some(v) => Some((k, v.clone())), + None => { + let default = t.default(db)?; + Some(( + k, + ast::make::ty( + &default.display_source_code(db, source_module.into()).ok()?, + ), + )) + } + }, }) .collect(); let res = Ctx { substs: substs_by_param, target_module, source_scope: self.source_scope }; @@ -111,7 +117,7 @@ impl<'a> PathTransform<'a> { } struct Ctx<'a> { - substs: FxHashMap, + substs: FxHashMap, target_module: hir::Module, source_scope: &'a SemanticsScope<'a>, } @@ -150,7 +156,7 @@ impl<'a> Ctx<'a> { match resolution { hir::PathResolution::TypeParam(tp) => { - if let Some(subst) = self.substs.get(&tp) { + if let Some(subst) = self.substs.get(&tp.merge()) { let parent = path.syntax().parent()?; if let Some(parent) = ast::Path::cast(parent.clone()) { // Path inside path means that there is an associated diff --git a/crates/ide_db/src/rename.rs b/crates/ide_db/src/rename.rs index 404e17c022b6..970ca2b6d7a4 100644 --- a/crates/ide_db/src/rename.rs +++ b/crates/ide_db/src/rename.rs @@ -124,20 +124,23 @@ impl Definition { src.with_value(name.syntax()).original_file_range_opt(sema.db) } Definition::GenericParam(generic_param) => match generic_param { - hir::GenericParam::TypeParam(type_param) => { - let src = type_param.source(sema.db)?; + hir::GenericParam::LifetimeParam(lifetime_param) => { + let src = lifetime_param.source(sema.db)?; + src.with_value(src.value.lifetime()?.syntax()).original_file_range_opt(sema.db) + } + _ => { + let x = match generic_param { + hir::GenericParam::TypeParam(it) => it.merge(), + hir::GenericParam::ConstParam(it) => it.merge(), + hir::GenericParam::LifetimeParam(_) => return None, + }; + let src = x.source(sema.db)?; let name = match &src.value { - Either::Left(type_param) => type_param.name()?, - Either::Right(_trait) => return None, + Either::Left(x) => x.name()?, + Either::Right(_) => return None, }; src.with_value(name.syntax()).original_file_range_opt(sema.db) } - hir::GenericParam::LifetimeParam(lifetime_param) => { - let src = lifetime_param.source(sema.db)?; - let lifetime = src.value.lifetime()?; - src.with_value(lifetime.syntax()).original_file_range_opt(sema.db) - } - hir::GenericParam::ConstParam(it) => name_range(it, sema), }, Definition::Label(label) => { let src = label.source(sema.db); diff --git a/crates/syntax/src/ast.rs b/crates/syntax/src/ast.rs index 91b46cf8e9d8..4aa64d0d6e8a 100644 --- a/crates/syntax/src/ast.rs +++ b/crates/syntax/src/ast.rs @@ -22,7 +22,7 @@ pub use self::{ generated::{nodes::*, tokens::*}, node_ext::{ AttrKind, FieldKind, Macro, NameLike, NameOrNameRef, PathSegmentKind, SelfParamKind, - SlicePatComponents, StructKind, TypeBoundKind, VisibilityKind, + SlicePatComponents, StructKind, TypeBoundKind, TypeOrConstParam, VisibilityKind, }, operators::{ArithOp, BinaryOp, CmpOp, LogicOp, Ordering, RangeOp, UnaryOp}, token_ext::{CommentKind, CommentPlacement, CommentShape, IsString, QuoteOffsets, Radix}, diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index 97455abd8094..229c71c76b1a 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs @@ -638,6 +638,21 @@ impl ast::TypeBound { } } +#[derive(Debug, Clone)] +pub enum TypeOrConstParam { + Type(ast::TypeParam), + Const(ast::ConstParam), +} + +impl TypeOrConstParam { + pub fn name(&self) -> Option { + match self { + TypeOrConstParam::Type(x) => x.name(), + TypeOrConstParam::Const(x) => x.name(), + } + } +} + pub enum VisibilityKind { In(ast::Path), PubCrate, @@ -746,16 +761,11 @@ impl ast::GenericParamList { ast::GenericParam::TypeParam(_) | ast::GenericParam::ConstParam(_) => None, }) } - pub fn type_params(&self) -> impl Iterator { - self.generic_params().filter_map(|param| match param { - ast::GenericParam::TypeParam(it) => Some(it), - ast::GenericParam::LifetimeParam(_) | ast::GenericParam::ConstParam(_) => None, - }) - } - pub fn const_params(&self) -> impl Iterator { + pub fn type_or_const_params(&self) -> impl Iterator { self.generic_params().filter_map(|param| match param { - ast::GenericParam::ConstParam(it) => Some(it), - ast::GenericParam::TypeParam(_) | ast::GenericParam::LifetimeParam(_) => None, + ast::GenericParam::TypeParam(it) => Some(ast::TypeOrConstParam::Type(it)), + ast::GenericParam::LifetimeParam(_) => None, + ast::GenericParam::ConstParam(it) => Some(ast::TypeOrConstParam::Const(it)), }) } } From 660fd4ab415e9543e4d677622aba309ca716ca12 Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Fri, 4 Mar 2022 12:30:53 +0330 Subject: [PATCH 2/2] Resolve only type params in type ns --- crates/hir/src/semantics.rs | 2 +- crates/hir/src/source_analyzer.rs | 12 +++--------- crates/hir_def/src/generics.rs | 7 +++++++ crates/hir_def/src/resolver.rs | 6 +++--- crates/hir_ty/src/lower.rs | 6 +++--- 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 3af47000f41a..2e0dbf82b777 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -70,7 +70,7 @@ impl PathResolution { | PathResolution::Local(_) | PathResolution::Macro(_) | PathResolution::ConstParam(_) => None, - PathResolution::TypeParam(param) => Some(TypeNs::GenericParam(param.merge().into())), + PathResolution::TypeParam(param) => Some(TypeNs::GenericParam((*param).into())), PathResolution::SelfType(impl_def) => Some(TypeNs::SelfType((*impl_def).into())), PathResolution::AssocItem(AssocItem::Const(_) | AssocItem::Function(_)) => None, PathResolution::AssocItem(AssocItem::TypeAlias(alias)) => { diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 1295d050071f..c6462a2c78ac 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -34,7 +34,7 @@ use syntax::{ use crate::{ db::HirDatabase, semantics::PathResolution, Adt, BuiltinAttr, BuiltinType, Const, Field, Function, Local, MacroDef, ModuleDef, Static, Struct, ToolModule, Trait, Type, TypeAlias, - TypeOrConstParam, Variant, + Variant, }; use base_db::CrateId; @@ -609,10 +609,7 @@ fn resolve_hir_path_( let res = match ty { TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), - TypeNs::GenericParam(id) => match (TypeOrConstParam { id }).split(db) { - either::Either::Left(x) => PathResolution::ConstParam(x), - either::Either::Right(x) => PathResolution::TypeParam(x), - }, + TypeNs::GenericParam(id) => PathResolution::TypeParam(id.into()), TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { PathResolution::Def(Adt::from(it).into()) } @@ -706,10 +703,7 @@ fn resolve_hir_path_qualifier( resolver.resolve_path_in_type_ns_fully(db.upcast(), path.mod_path()).map(|ty| match ty { TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), - TypeNs::GenericParam(id) => match (TypeOrConstParam { id }).split(db) { - either::Either::Left(x) => PathResolution::ConstParam(x), - either::Either::Right(x) => PathResolution::TypeParam(x), - }, + TypeNs::GenericParam(id) => PathResolution::TypeParam(id.into()), TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => PathResolution::Def(Adt::from(it).into()), TypeNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()), TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()), diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs index 341d444d6196..b5a11a1ba55e 100644 --- a/crates/hir_def/src/generics.rs +++ b/crates/hir_def/src/generics.rs @@ -365,6 +365,13 @@ impl GenericParams { where_predicates.shrink_to_fit(); } + pub fn find_type_by_name(&self, name: &Name) -> Option { + self.types + .iter() + .filter(|x| matches!(x.1, TypeOrConstParamData::TypeParamData(_))) + .find_map(|(id, p)| if p.name().as_ref() == Some(&name) { Some(id) } else { None }) + } + pub fn find_type_or_const_by_name(&self, name: &Name) -> Option { self.types .iter() diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index e19e8543b41d..d5e62f226a03 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs @@ -25,7 +25,7 @@ use crate::{ AdtId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, ExternBlockId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, ItemContainerId, LifetimeParamId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, - TypeOrConstParamId, VariantId, + TypeOrConstParamId, TypeParamId, VariantId, }; #[derive(Debug, Clone, Default)] @@ -68,7 +68,7 @@ enum Scope { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum TypeNs { SelfType(ImplId), - GenericParam(TypeOrConstParamId), + GenericParam(TypeParamId), AdtId(AdtId), AdtSelfType(AdtId), // Yup, enum variants are added to the types ns, but any usage of variant as @@ -192,7 +192,7 @@ impl Resolver { Scope::GenericParams { .. } | Scope::ImplDefScope(_) if skip_to_mod => continue, Scope::GenericParams { params, def } => { - if let Some(local_id) = params.find_type_or_const_by_name(first_name) { + if let Some(local_id) = params.find_type_by_name(first_name) { let idx = if path.segments().len() == 1 { None } else { Some(1) }; return Some(( TypeNs::GenericParam( diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 3444ffd2020e..3147b6f330bd 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -372,7 +372,7 @@ impl<'a> TyLoweringContext<'a> { _ => return None, }; match resolution { - TypeNs::GenericParam(param_id) => Some(param_id), + TypeNs::GenericParam(param_id) => Some(param_id.into()), _ => None, } } @@ -991,9 +991,9 @@ fn named_associated_type_shorthand_candidates( return res; } // Handle `Self::Type` referring to own associated type in trait definitions - if let GenericDefId::TraitId(trait_id) = param_id.parent { + if let GenericDefId::TraitId(trait_id) = param_id.parent() { let generics = generics(db.upcast(), trait_id.into()); - if generics.params.types[param_id.local_id].is_trait_self() { + if generics.params.types[param_id.local_id()].is_trait_self() { let trait_ref = TyBuilder::trait_ref(db, trait_id) .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0) .build();