mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-12 21:28:51 +00:00
Preserve order of generic args
This commit is contained in:
parent
9d473a0b9f
commit
4fa8749c44
39 changed files with 714 additions and 427 deletions
|
@ -139,9 +139,9 @@ fn resolve_doc_path(
|
||||||
AttrDefId::ImplId(it) => it.resolver(db.upcast()),
|
AttrDefId::ImplId(it) => it.resolver(db.upcast()),
|
||||||
AttrDefId::ExternBlockId(it) => it.resolver(db.upcast()),
|
AttrDefId::ExternBlockId(it) => it.resolver(db.upcast()),
|
||||||
AttrDefId::GenericParamId(it) => match it {
|
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::LifetimeParamId(it) => it.parent,
|
||||||
GenericParamId::ConstParamId(it) => it.parent,
|
|
||||||
}
|
}
|
||||||
.resolver(db.upcast()),
|
.resolver(db.upcast()),
|
||||||
// FIXME
|
// FIXME
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
//! HirDisplay implementations for various hir types.
|
//! HirDisplay implementations for various hir types.
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
adt::VariantData,
|
adt::VariantData,
|
||||||
generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget},
|
generics::{
|
||||||
|
TypeOrConstParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
|
||||||
|
},
|
||||||
type_ref::{TypeBound, TypeRef},
|
type_ref::{TypeBound, TypeRef},
|
||||||
AdtId, GenericDefId,
|
AdtId, GenericDefId,
|
||||||
};
|
};
|
||||||
|
@ -16,8 +18,8 @@ use syntax::SmolStr;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasCrate, HasVisibility,
|
Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasCrate, HasVisibility,
|
||||||
LifetimeParam, Module, Static, Struct, Trait, TyBuilder, Type, TypeAlias, TypeParam, Union,
|
LifetimeParam, Module, Static, Struct, Trait, TyBuilder, Type, TypeAlias, TypeOrConstParam,
|
||||||
Variant,
|
TypeParam, Union, Variant,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl HirDisplay for Function {
|
impl HirDisplay for Function {
|
||||||
|
@ -226,8 +228,17 @@ impl HirDisplay for GenericParam {
|
||||||
fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
|
fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
|
||||||
match self {
|
match self {
|
||||||
GenericParam::TypeParam(it) => it.hir_fmt(f),
|
GenericParam::TypeParam(it) => it.hir_fmt(f),
|
||||||
GenericParam::LifetimeParam(it) => it.hir_fmt(f),
|
|
||||||
GenericParam::ConstParam(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(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let bounds = f.db.generic_predicates_for_param(self.id.parent, self.id, None);
|
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 substs = TyBuilder::type_params_subst(f.db, self.id.parent());
|
||||||
let predicates: Vec<_> =
|
let predicates: Vec<_> =
|
||||||
bounds.iter().cloned().map(|b| b.substitute(Interner, &substs)).collect();
|
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 =
|
let sized_trait =
|
||||||
f.db.lang_item(krate, SmolStr::new_inline("sized"))
|
f.db.lang_item(krate, SmolStr::new_inline("sized"))
|
||||||
.and_then(|lang_item| lang_item.as_trait());
|
.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> {
|
fn write_generic_params(def: GenericDefId, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
|
||||||
let params = f.db.generic_params(def);
|
let params = f.db.generic_params(def);
|
||||||
if params.lifetimes.is_empty()
|
if params.lifetimes.is_empty()
|
||||||
&& params.consts.is_empty()
|
|
||||||
&& params
|
&& params
|
||||||
.types
|
.types
|
||||||
.iter()
|
.iter()
|
||||||
.all(|(_, param)| !matches!(param.provenance, TypeParamProvenance::TypeParamList))
|
.filter_map(|x| x.1.type_param())
|
||||||
|
.all(|param| !matches!(param.provenance, TypeParamProvenance::TypeParamList))
|
||||||
{
|
{
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -300,23 +311,27 @@ fn write_generic_params(def: GenericDefId, f: &mut HirFormatter) -> Result<(), H
|
||||||
write!(f, "{}", lifetime.name)?;
|
write!(f, "{}", lifetime.name)?;
|
||||||
}
|
}
|
||||||
for (_, ty) in params.types.iter() {
|
for (_, ty) in params.types.iter() {
|
||||||
if ty.provenance != TypeParamProvenance::TypeParamList {
|
if let Some(name) = &ty.name() {
|
||||||
continue;
|
match ty {
|
||||||
}
|
TypeOrConstParamData::TypeParamData(ty) => {
|
||||||
if let Some(name) = &ty.name {
|
if ty.provenance != TypeParamProvenance::TypeParamList {
|
||||||
delim(f)?;
|
continue;
|
||||||
write!(f, "{}", name)?;
|
}
|
||||||
if let Some(default) = &ty.default {
|
delim(f)?;
|
||||||
write!(f, " = ")?;
|
write!(f, "{}", name)?;
|
||||||
default.hir_fmt(f)?;
|
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, ">")?;
|
write!(f, ">")?;
|
||||||
Ok(())
|
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`.
|
// unnamed type targets are displayed inline with the argument itself, e.g. `f: impl Y`.
|
||||||
let is_unnamed_type_target = |target: &WherePredicateTypeTarget| match target {
|
let is_unnamed_type_target = |target: &WherePredicateTypeTarget| match target {
|
||||||
WherePredicateTypeTarget::TypeRef(_) => false,
|
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
|
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 {
|
let write_target = |target: &WherePredicateTypeTarget, f: &mut HirFormatter| match target {
|
||||||
WherePredicateTypeTarget::TypeRef(ty) => ty.hir_fmt(f),
|
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),
|
Some(name) => write!(f, "{}", name),
|
||||||
None => write!(f, "{{unnamed}}"),
|
None => write!(f, "{{unnamed}}"),
|
||||||
},
|
},
|
||||||
|
|
|
@ -41,9 +41,10 @@ from_id![
|
||||||
(hir_def::ConstId, crate::Const),
|
(hir_def::ConstId, crate::Const),
|
||||||
(hir_def::FunctionId, crate::Function),
|
(hir_def::FunctionId, crate::Function),
|
||||||
(hir_def::ImplId, crate::Impl),
|
(hir_def::ImplId, crate::Impl),
|
||||||
|
(hir_def::TypeOrConstParamId, crate::TypeOrConstParam),
|
||||||
(hir_def::TypeParamId, crate::TypeParam),
|
(hir_def::TypeParamId, crate::TypeParam),
|
||||||
(hir_def::LifetimeParamId, crate::LifetimeParam),
|
|
||||||
(hir_def::ConstParamId, crate::ConstParam),
|
(hir_def::ConstParamId, crate::ConstParam),
|
||||||
|
(hir_def::LifetimeParamId, crate::LifetimeParam),
|
||||||
(hir_expand::MacroDefId, crate::MacroDef)
|
(hir_expand::MacroDefId, crate::MacroDef)
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -71,8 +72,8 @@ impl From<GenericParamId> for GenericParam {
|
||||||
fn from(id: GenericParamId) -> Self {
|
fn from(id: GenericParamId) -> Self {
|
||||||
match id {
|
match id {
|
||||||
GenericParamId::TypeParamId(it) => GenericParam::TypeParam(it.into()),
|
GenericParamId::TypeParamId(it) => GenericParam::TypeParam(it.into()),
|
||||||
GenericParamId::LifetimeParamId(it) => GenericParam::LifetimeParam(it.into()),
|
|
||||||
GenericParamId::ConstParamId(it) => GenericParam::ConstParam(it.into()),
|
GenericParamId::ConstParamId(it) => GenericParam::ConstParam(it.into()),
|
||||||
|
GenericParamId::LifetimeParamId(it) => GenericParam::LifetimeParam(it.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,9 +81,9 @@ impl From<GenericParamId> for GenericParam {
|
||||||
impl From<GenericParam> for GenericParamId {
|
impl From<GenericParam> for GenericParamId {
|
||||||
fn from(id: GenericParam) -> Self {
|
fn from(id: GenericParam) -> Self {
|
||||||
match id {
|
match id {
|
||||||
GenericParam::TypeParam(it) => GenericParamId::TypeParamId(it.id),
|
|
||||||
GenericParam::LifetimeParam(it) => GenericParamId::LifetimeParamId(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()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,8 @@ use hir_expand::InFile;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::HirDatabase, Adt, Const, ConstParam, Enum, Field, FieldSource, Function, Impl,
|
db::HirDatabase, Adt, Const, Enum, Field, FieldSource, Function, Impl, LifetimeParam, MacroDef,
|
||||||
LifetimeParam, MacroDef, Module, Static, Struct, Trait, TypeAlias, TypeParam, Union, Variant,
|
Module, Static, Struct, Trait, TypeAlias, TypeOrConstParam, Union, Variant,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait HasSource {
|
pub trait HasSource {
|
||||||
|
@ -139,8 +139,8 @@ impl HasSource for Impl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasSource for TypeParam {
|
impl HasSource for TypeOrConstParam {
|
||||||
type Ast = Either<ast::TypeParam, ast::Trait>;
|
type Ast = Either<ast::TypeOrConstParam, ast::Trait>;
|
||||||
fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
|
fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
|
||||||
let child_source = self.id.parent.child_source(db.upcast());
|
let child_source = self.id.parent.child_source(db.upcast());
|
||||||
Some(child_source.map(|it| it[self.id.local_id].clone()))
|
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()))
|
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<InFile<Self::Ast>> {
|
|
||||||
let child_source = self.id.parent.child_source(db.upcast());
|
|
||||||
Some(child_source.map(|it| it[self.id.local_id].clone()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ use hir_def::{
|
||||||
AdtId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, DefWithBodyId, EnumId,
|
AdtId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, DefWithBodyId, EnumId,
|
||||||
FunctionId, GenericDefId, HasModule, ImplId, ItemContainerId, LifetimeParamId,
|
FunctionId, GenericDefId, HasModule, ImplId, ItemContainerId, LifetimeParamId,
|
||||||
LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId,
|
LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId,
|
||||||
TypeParamId, UnionId,
|
TypeOrConstParamId, TypeParamId, UnionId,
|
||||||
};
|
};
|
||||||
use hir_expand::{name::name, MacroCallKind, MacroDefId, MacroDefKind};
|
use hir_expand::{name::name, MacroCallKind, MacroDefId, MacroDefKind};
|
||||||
use hir_ty::{
|
use hir_ty::{
|
||||||
|
@ -71,7 +71,7 @@ use itertools::Itertools;
|
||||||
use nameres::diagnostics::DefDiagnosticKind;
|
use nameres::diagnostics::DefDiagnosticKind;
|
||||||
use once_cell::unsync::Lazy;
|
use once_cell::unsync::Lazy;
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use stdx::{format_to, impl_from};
|
use stdx::{format_to, impl_from, never};
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, HasAttrs as _, HasDocComments, HasName},
|
ast::{self, HasAttrs as _, HasDocComments, HasName},
|
||||||
AstNode, AstPtr, SmolStr, SyntaxNodePtr, T,
|
AstNode, AstPtr, SmolStr, SyntaxNodePtr, T,
|
||||||
|
@ -2007,11 +2007,13 @@ impl_from!(
|
||||||
impl GenericDef {
|
impl GenericDef {
|
||||||
pub fn params(self, db: &dyn HirDatabase) -> Vec<GenericParam> {
|
pub fn params(self, db: &dyn HirDatabase) -> Vec<GenericParam> {
|
||||||
let generics = db.generic_params(self.into());
|
let generics = db.generic_params(self.into());
|
||||||
let ty_params = generics
|
let ty_params = generics.types.iter().map(|(local_id, _)| {
|
||||||
.types
|
let toc = TypeOrConstParam { id: TypeOrConstParamId { parent: self.into(), local_id } };
|
||||||
.iter()
|
match toc.split(db) {
|
||||||
.map(|(local_id, _)| TypeParam { id: TypeParamId { parent: self.into(), local_id } })
|
Either::Left(x) => GenericParam::ConstParam(x),
|
||||||
.map(GenericParam::TypeParam);
|
Either::Right(x) => GenericParam::TypeParam(x),
|
||||||
|
}
|
||||||
|
});
|
||||||
let lt_params = generics
|
let lt_params = generics
|
||||||
.lifetimes
|
.lifetimes
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -2019,20 +2021,17 @@ impl GenericDef {
|
||||||
id: LifetimeParamId { parent: self.into(), local_id },
|
id: LifetimeParamId { parent: self.into(), local_id },
|
||||||
})
|
})
|
||||||
.map(GenericParam::LifetimeParam);
|
.map(GenericParam::LifetimeParam);
|
||||||
let const_params = generics
|
ty_params.chain(lt_params).collect()
|
||||||
.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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeParam> {
|
pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeOrConstParam> {
|
||||||
let generics = db.generic_params(self.into());
|
let generics = db.generic_params(self.into());
|
||||||
generics
|
generics
|
||||||
.types
|
.types
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(local_id, _)| TypeParam { id: TypeParamId { parent: self.into(), local_id } })
|
.map(|(local_id, _)| TypeOrConstParam {
|
||||||
|
id: TypeOrConstParamId { parent: self.into(), local_id },
|
||||||
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2221,25 +2220,25 @@ impl Label {
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum GenericParam {
|
pub enum GenericParam {
|
||||||
TypeParam(TypeParam),
|
TypeParam(TypeParam),
|
||||||
LifetimeParam(LifetimeParam),
|
|
||||||
ConstParam(ConstParam),
|
ConstParam(ConstParam),
|
||||||
|
LifetimeParam(LifetimeParam),
|
||||||
}
|
}
|
||||||
impl_from!(TypeParam, LifetimeParam, ConstParam for GenericParam);
|
impl_from!(TypeParam, ConstParam, LifetimeParam for GenericParam);
|
||||||
|
|
||||||
impl GenericParam {
|
impl GenericParam {
|
||||||
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
||||||
match self {
|
match self {
|
||||||
GenericParam::TypeParam(it) => it.module(db),
|
GenericParam::TypeParam(it) => it.module(db),
|
||||||
GenericParam::LifetimeParam(it) => it.module(db),
|
|
||||||
GenericParam::ConstParam(it) => it.module(db),
|
GenericParam::ConstParam(it) => it.module(db),
|
||||||
|
GenericParam::LifetimeParam(it) => it.module(db),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
||||||
match self {
|
match self {
|
||||||
GenericParam::TypeParam(it) => it.name(db),
|
GenericParam::TypeParam(it) => it.name(db),
|
||||||
GenericParam::LifetimeParam(it) => it.name(db),
|
|
||||||
GenericParam::ConstParam(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 {
|
impl TypeParam {
|
||||||
|
pub fn merge(self) -> TypeOrConstParam {
|
||||||
|
TypeOrConstParam { id: self.id.into() }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
||||||
let params = db.generic_params(self.id.parent);
|
self.merge().name(db)
|
||||||
params.types[self.id.local_id].name.clone().unwrap_or_else(Name::missing)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
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 {
|
pub fn ty(self, db: &dyn HirDatabase) -> Type {
|
||||||
let resolver = self.id.parent.resolver(db.upcast());
|
let resolver = self.id.parent().resolver(db.upcast());
|
||||||
let krate = self.id.parent.module(db.upcast()).krate();
|
let krate = self.id.parent().module(db.upcast()).krate();
|
||||||
let ty = TyKind::Placeholder(hir_ty::to_placeholder_idx(db, self.id)).intern(Interner);
|
let ty =
|
||||||
|
TyKind::Placeholder(hir_ty::to_placeholder_idx(db, self.id.into())).intern(Interner);
|
||||||
Type::new_with_resolver_inner(db, krate, &resolver, ty)
|
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
|
/// parameter, not additional bounds that might be added e.g. by a method if
|
||||||
/// the parameter comes from an impl!
|
/// the parameter comes from an impl!
|
||||||
pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> {
|
pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> {
|
||||||
db.generic_predicates_for_param(self.id.parent, self.id, None)
|
db.generic_predicates_for_param(self.id.parent(), self.id.into(), None)
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|pred| match &pred.skip_binders().skip_binders() {
|
.filter_map(|pred| match &pred.skip_binders().skip_binders() {
|
||||||
hir_ty::WhereClause::Implemented(trait_ref) => {
|
hir_ty::WhereClause::Implemented(trait_ref) => {
|
||||||
|
@ -2282,12 +2285,12 @@ impl TypeParam {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn default(self, db: &dyn HirDatabase) -> Option<Type> {
|
pub fn default(self, db: &dyn HirDatabase) -> Option<Type> {
|
||||||
let params = db.generic_defaults(self.id.parent);
|
let params = db.generic_defaults(self.id.parent());
|
||||||
let local_idx = hir_ty::param_idx(db, self.id)?;
|
let local_idx = hir_ty::param_idx(db, self.id.into())?;
|
||||||
let resolver = self.id.parent.resolver(db.upcast());
|
let resolver = self.id.parent().resolver(db.upcast());
|
||||||
let krate = self.id.parent.module(db.upcast()).krate();
|
let krate = self.id.parent().module(db.upcast()).krate();
|
||||||
let ty = params.get(local_idx)?.clone();
|
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));
|
let ty = ty.substitute(Interner, &subst_prefix(&subst, local_idx));
|
||||||
Some(Type::new_with_resolver_inner(db, krate, &resolver, ty))
|
Some(Type::new_with_resolver_inner(db, krate, &resolver, ty))
|
||||||
}
|
}
|
||||||
|
@ -2319,9 +2322,48 @@ pub struct ConstParam {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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 {
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
||||||
let params = db.generic_params(self.id.parent);
|
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 {
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
||||||
|
@ -2332,10 +2374,23 @@ impl ConstParam {
|
||||||
self.id.parent.into()
|
self.id.parent.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn split(self, db: &dyn HirDatabase) -> Either<ConstParam, TypeParam> {
|
||||||
|
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 {
|
pub fn ty(self, db: &dyn HirDatabase) -> Type {
|
||||||
let def = self.id.parent;
|
match self.split(db) {
|
||||||
let krate = def.module(db.upcast()).krate();
|
Either::Left(x) => x.ty(db),
|
||||||
Type::new(db, krate, def, db.const_param_ty(self.id))
|
Either::Right(x) => x.ty(db),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ impl PathResolution {
|
||||||
| PathResolution::Local(_)
|
| PathResolution::Local(_)
|
||||||
| PathResolution::Macro(_)
|
| PathResolution::Macro(_)
|
||||||
| PathResolution::ConstParam(_) => None,
|
| 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::SelfType(impl_def) => Some(TypeNs::SelfType((*impl_def).into())),
|
||||||
PathResolution::AssocItem(AssocItem::Const(_) | AssocItem::Function(_)) => None,
|
PathResolution::AssocItem(AssocItem::Const(_) | AssocItem::Function(_)) => None,
|
||||||
PathResolution::AssocItem(AssocItem::TypeAlias(alias)) => {
|
PathResolution::AssocItem(AssocItem::TypeAlias(alias)) => {
|
||||||
|
|
|
@ -282,7 +282,7 @@ impl SourceToDefCtx<'_, '_> {
|
||||||
pub(super) fn type_param_to_def(&mut self, src: InFile<ast::TypeParam>) -> Option<TypeParamId> {
|
pub(super) fn type_param_to_def(&mut self, src: InFile<ast::TypeParam>) -> Option<TypeParamId> {
|
||||||
let container: ChildContainer = self.find_generic_param_container(src.syntax())?.into();
|
let container: ChildContainer = self.find_generic_param_container(src.syntax())?.into();
|
||||||
let dyn_map = self.cache_for(container, src.file_id);
|
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(
|
pub(super) fn lifetime_param_to_def(
|
||||||
|
@ -300,7 +300,7 @@ impl SourceToDefCtx<'_, '_> {
|
||||||
) -> Option<ConstParamId> {
|
) -> Option<ConstParamId> {
|
||||||
let container: ChildContainer = self.find_generic_param_container(src.syntax())?.into();
|
let container: ChildContainer = self.find_generic_param_container(src.syntax())?.into();
|
||||||
let dyn_map = self.cache_for(container, src.file_id);
|
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(
|
pub(super) fn generic_param_to_def(
|
||||||
|
|
|
@ -34,7 +34,7 @@ use syntax::{
|
||||||
use crate::{
|
use crate::{
|
||||||
db::HirDatabase, semantics::PathResolution, Adt, BuiltinAttr, BuiltinType, Const, Field,
|
db::HirDatabase, semantics::PathResolution, Adt, BuiltinAttr, BuiltinType, Const, Field,
|
||||||
Function, Local, MacroDef, ModuleDef, Static, Struct, ToolModule, Trait, Type, TypeAlias,
|
Function, Local, MacroDef, ModuleDef, Static, Struct, ToolModule, Trait, Type, TypeAlias,
|
||||||
TypeParam, Variant,
|
TypeOrConstParam, Variant,
|
||||||
};
|
};
|
||||||
use base_db::CrateId;
|
use base_db::CrateId;
|
||||||
|
|
||||||
|
@ -609,7 +609,10 @@ fn resolve_hir_path_(
|
||||||
|
|
||||||
let res = match ty {
|
let res = match ty {
|
||||||
TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
|
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) => {
|
TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => {
|
||||||
PathResolution::Def(Adt::from(it).into())
|
PathResolution::Def(Adt::from(it).into())
|
||||||
}
|
}
|
||||||
|
@ -650,7 +653,7 @@ fn resolve_hir_path_(
|
||||||
ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()),
|
ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()),
|
||||||
ValueNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()),
|
ValueNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()),
|
||||||
ValueNs::ImplSelf(impl_id) => PathResolution::SelfType(impl_id.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)
|
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 {
|
resolver.resolve_path_in_type_ns_fully(db.upcast(), path.mod_path()).map(|ty| match ty {
|
||||||
TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
|
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::AdtSelfType(it) | TypeNs::AdtId(it) => PathResolution::Def(Adt::from(it).into()),
|
||||||
TypeNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()),
|
TypeNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()),
|
||||||
TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),
|
TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),
|
||||||
|
|
|
@ -367,23 +367,36 @@ impl AttrsWithOwner {
|
||||||
AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db),
|
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::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db),
|
||||||
AttrDefId::GenericParamId(it) => match it {
|
AttrDefId::GenericParamId(it) => match it {
|
||||||
GenericParamId::TypeParamId(it) => {
|
GenericParamId::ConstParamId(it) => {
|
||||||
let src = it.parent.child_source(db);
|
let src = it.parent().child_source(db);
|
||||||
RawAttrs::from_attrs_owner(
|
RawAttrs::from_attrs_owner(
|
||||||
db,
|
db,
|
||||||
src.with_value(
|
src.with_value(src.value[it.local_id()].as_ref().either(
|
||||||
src.value[it.local_id].as_ref().either(|it| it as _, |it| it as _),
|
|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);
|
||||||
|
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::LifetimeParamId(it) => {
|
GenericParamId::LifetimeParamId(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]))
|
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),
|
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::ImplId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new),
|
||||||
AttrDefId::GenericParamId(id) => match id {
|
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) => {
|
GenericParamId::TypeParamId(id) => {
|
||||||
id.parent.child_source(db).map(|source| match &source[id.local_id] {
|
id.parent().child_source(db).map(|source| match &source[id.local_id()] {
|
||||||
Either::Left(id) => ast::AnyHasAttrs::new(id.clone()),
|
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()),
|
Either::Right(id) => ast::AnyHasAttrs::new(id.clone()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -464,10 +493,6 @@ impl AttrsWithOwner {
|
||||||
.parent
|
.parent
|
||||||
.child_source(db)
|
.child_source(db)
|
||||||
.map(|source| ast::AnyHasAttrs::new(source[id.local_id].clone())),
|
.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),
|
AttrDefId::ExternBlockId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new),
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,9 +9,10 @@ use hir_expand::{
|
||||||
name::{AsName, Name},
|
name::{AsName, Name},
|
||||||
ExpandResult, HirFileId, InFile,
|
ExpandResult, HirFileId, InFile,
|
||||||
};
|
};
|
||||||
use la_arena::{Arena, ArenaMap};
|
use la_arena::{Arena, ArenaMap, Idx};
|
||||||
use once_cell::unsync::Lazy;
|
use once_cell::unsync::Lazy;
|
||||||
use std::ops::DerefMut;
|
use std::ops::DerefMut;
|
||||||
|
use stdx::impl_from;
|
||||||
use syntax::ast::{self, HasGenericParams, HasName, HasTypeBounds};
|
use syntax::ast::{self, HasGenericParams, HasName, HasTypeBounds};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -23,8 +24,8 @@ use crate::{
|
||||||
keys,
|
keys,
|
||||||
src::{HasChildSource, HasSource},
|
src::{HasChildSource, HasSource},
|
||||||
type_ref::{LifetimeRef, TypeBound, TypeRef},
|
type_ref::{LifetimeRef, TypeBound, TypeRef},
|
||||||
AdtId, ConstParamId, GenericDefId, HasModule, LifetimeParamId, LocalConstParamId,
|
AdtId, GenericDefId, HasModule, LifetimeParamId, LocalLifetimeParamId, LocalTypeOrConstParamId,
|
||||||
LocalLifetimeParamId, LocalTypeParamId, Lookup, TypeParamId,
|
Lookup, TypeOrConstParamId,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Data about a generic type parameter (to a function, struct, impl, ...).
|
/// Data about a generic type parameter (to a function, struct, impl, ...).
|
||||||
|
@ -55,12 +56,44 @@ pub enum TypeParamProvenance {
|
||||||
ArgumentImplTrait,
|
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.
|
/// Data about the generic parameters of a function, struct, impl, etc.
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Default, Hash)]
|
#[derive(Clone, PartialEq, Eq, Debug, Default, Hash)]
|
||||||
pub struct GenericParams {
|
pub struct GenericParams {
|
||||||
pub types: Arena<TypeParamData>,
|
pub types: Arena<TypeOrConstParamData>,
|
||||||
pub lifetimes: Arena<LifetimeParamData>,
|
pub lifetimes: Arena<LifetimeParamData>,
|
||||||
pub consts: Arena<ConstParamData>,
|
|
||||||
pub where_predicates: Vec<WherePredicate>,
|
pub where_predicates: Vec<WherePredicate>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,10 +122,18 @@ pub enum WherePredicate {
|
||||||
pub enum WherePredicateTypeTarget {
|
pub enum WherePredicateTypeTarget {
|
||||||
TypeRef(Interned<TypeRef>),
|
TypeRef(Interned<TypeRef>),
|
||||||
/// For desugared where predicates that can directly refer to a type param.
|
/// For desugared where predicates that can directly refer to a type param.
|
||||||
TypeParam(LocalTypeParamId),
|
TypeOrConstParam(LocalTypeOrConstParamId),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GenericParams {
|
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<Item = (Idx<TypeOrConstParamData>, &TypeParamData)> {
|
||||||
|
self.types.iter().filter_map(|x| x.1.type_param().map(|y| (x.0, y)))
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn generic_params_query(
|
pub(crate) fn generic_params_query(
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
def: GenericDefId,
|
def: GenericDefId,
|
||||||
|
@ -184,19 +225,32 @@ impl GenericParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill_params(&mut self, lower_ctx: &LowerCtx, params: ast::GenericParamList) {
|
fn fill_params(&mut self, lower_ctx: &LowerCtx, params: ast::GenericParamList) {
|
||||||
for type_param in params.type_params() {
|
for type_or_const_param in params.type_or_const_params() {
|
||||||
let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
|
match type_or_const_param {
|
||||||
// FIXME: Use `Path::from_src`
|
ast::TypeOrConstParam::Type(type_param) => {
|
||||||
let default =
|
let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
|
||||||
type_param.default_type().map(|it| Interned::new(TypeRef::from_ast(lower_ctx, it)));
|
// FIXME: Use `Path::from_src`
|
||||||
let param = TypeParamData {
|
let default = type_param
|
||||||
name: Some(name.clone()),
|
.default_type()
|
||||||
default,
|
.map(|it| Interned::new(TypeRef::from_ast(lower_ctx, it)));
|
||||||
provenance: TypeParamProvenance::TypeParamList,
|
let param = TypeParamData {
|
||||||
};
|
name: Some(name.clone()),
|
||||||
self.types.alloc(param);
|
default,
|
||||||
let type_ref = TypeRef::Path(name.into());
|
provenance: TypeParamProvenance::TypeParamList,
|
||||||
self.fill_bounds(lower_ctx, &type_param, Either::Left(type_ref));
|
};
|
||||||
|
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() {
|
for lifetime_param in params.lifetime_params() {
|
||||||
let name =
|
let name =
|
||||||
|
@ -206,12 +260,6 @@ impl GenericParams {
|
||||||
let lifetime_ref = LifetimeRef::new_name(name);
|
let lifetime_ref = LifetimeRef::new_name(name);
|
||||||
self.fill_bounds(lower_ctx, &lifetime_param, Either::Right(lifetime_ref));
|
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) {
|
fn fill_where_predicates(&mut self, lower_ctx: &LowerCtx, where_clause: ast::WhereClause) {
|
||||||
|
@ -287,10 +335,10 @@ impl GenericParams {
|
||||||
default: None,
|
default: None,
|
||||||
provenance: TypeParamProvenance::ArgumentImplTrait,
|
provenance: TypeParamProvenance::ArgumentImplTrait,
|
||||||
};
|
};
|
||||||
let param_id = self.types.alloc(param);
|
let param_id = self.types.alloc(param.into());
|
||||||
for bound in bounds {
|
for bound in bounds {
|
||||||
self.where_predicates.push(WherePredicate::TypeBound {
|
self.where_predicates.push(WherePredicate::TypeBound {
|
||||||
target: WherePredicateTypeTarget::TypeParam(param_id),
|
target: WherePredicateTypeTarget::TypeOrConstParam(param_id),
|
||||||
bound: bound.clone(),
|
bound: bound.clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -311,27 +359,26 @@ impl GenericParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn shrink_to_fit(&mut self) {
|
pub(crate) fn shrink_to_fit(&mut self) {
|
||||||
let Self { consts, lifetimes, types, where_predicates } = self;
|
let Self { lifetimes, types, where_predicates } = self;
|
||||||
consts.shrink_to_fit();
|
|
||||||
lifetimes.shrink_to_fit();
|
lifetimes.shrink_to_fit();
|
||||||
types.shrink_to_fit();
|
types.shrink_to_fit();
|
||||||
where_predicates.shrink_to_fit();
|
where_predicates.shrink_to_fit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_type_by_name(&self, name: &Name) -> Option<LocalTypeParamId> {
|
pub fn find_type_or_const_by_name(&self, name: &Name) -> Option<LocalTypeOrConstParamId> {
|
||||||
self.types
|
self.types
|
||||||
.iter()
|
.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<LocalConstParamId> {
|
pub fn find_trait_self_param(&self) -> Option<LocalTypeOrConstParamId> {
|
||||||
self.consts.iter().find_map(|(id, p)| if p.name == *name { Some(id) } else { None })
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find_trait_self_param(&self) -> Option<LocalTypeParamId> {
|
|
||||||
self.types.iter().find_map(|(id, p)| {
|
self.types.iter().find_map(|(id, p)| {
|
||||||
if p.provenance == TypeParamProvenance::TraitSelf {
|
if let TypeOrConstParamData::TypeParamData(p) = p {
|
||||||
Some(id)
|
if p.provenance == TypeParamProvenance::TraitSelf {
|
||||||
|
Some(id)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -377,12 +424,12 @@ fn file_id_and_params_of(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasChildSource<LocalTypeParamId> for GenericDefId {
|
impl HasChildSource<LocalTypeOrConstParamId> for GenericDefId {
|
||||||
type Value = Either<ast::TypeParam, ast::Trait>;
|
type Value = Either<ast::TypeOrConstParam, ast::Trait>;
|
||||||
fn child_source(
|
fn child_source(
|
||||||
&self,
|
&self,
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
) -> InFile<ArenaMap<LocalTypeParamId, Self::Value>> {
|
) -> InFile<ArenaMap<LocalTypeOrConstParamId, Self::Value>> {
|
||||||
let generic_params = db.generic_params(*self);
|
let generic_params = db.generic_params(*self);
|
||||||
let mut idx_iter = generic_params.types.iter().map(|(idx, _)| idx);
|
let mut idx_iter = generic_params.types.iter().map(|(idx, _)| idx);
|
||||||
|
|
||||||
|
@ -398,7 +445,7 @@ impl HasChildSource<LocalTypeParamId> for GenericDefId {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(generic_params_list) = generic_params_list {
|
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));
|
params.insert(idx, Either::Left(ast_param));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -430,29 +477,6 @@ impl HasChildSource<LocalLifetimeParamId> for GenericDefId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasChildSource<LocalConstParamId> for GenericDefId {
|
|
||||||
type Value = ast::ConstParam;
|
|
||||||
fn child_source(
|
|
||||||
&self,
|
|
||||||
db: &dyn DefDatabase,
|
|
||||||
) -> InFile<ArenaMap<LocalConstParamId, Self::Value>> {
|
|
||||||
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 {
|
impl ChildBySource for GenericDefId {
|
||||||
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
|
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);
|
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 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 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.
|
// For traits the first type index is `Self`, skip it.
|
||||||
if let GenericDefId::TraitId(_) = *self {
|
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 {
|
if let Some(generic_params_list) = generic_params_list {
|
||||||
for (local_id, ast_param) in types_idx_iter.zip(generic_params_list.type_params()) {
|
for (local_id, ast_param) in
|
||||||
let id = TypeParamId { parent: *self, local_id };
|
toc_idx_iter.zip(generic_params_list.type_or_const_params())
|
||||||
res[keys::TYPE_PARAM].insert(ast_param, id);
|
{
|
||||||
|
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()) {
|
for (local_id, ast_param) in lts_idx_iter.zip(generic_params_list.lifetime_params()) {
|
||||||
let id = LifetimeParamId { parent: *self, local_id };
|
let id = LifetimeParamId { parent: *self, local_id };
|
||||||
res[keys::LIFETIME_PARAM].insert(ast_param, 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -582,11 +582,14 @@ impl<'a> Ctx<'a> {
|
||||||
}
|
}
|
||||||
GenericsOwner::Trait(trait_def) => {
|
GenericsOwner::Trait(trait_def) => {
|
||||||
// traits get the Self type as an implicit first type parameter
|
// traits get the Self type as an implicit first type parameter
|
||||||
generics.types.alloc(TypeParamData {
|
generics.types.alloc(
|
||||||
name: Some(name![Self]),
|
TypeParamData {
|
||||||
default: None,
|
name: Some(name![Self]),
|
||||||
provenance: TypeParamProvenance::TraitSelf,
|
default: None,
|
||||||
});
|
provenance: TypeParamProvenance::TraitSelf,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
// add super traits as bounds on Self
|
// add super traits as bounds on Self
|
||||||
// i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
|
// i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
|
||||||
let self_param = TypeRef::Path(name![Self].into());
|
let self_param = TypeRef::Path(name![Self].into());
|
||||||
|
|
|
@ -6,7 +6,7 @@ use itertools::Itertools;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
attr::RawAttrs,
|
attr::RawAttrs,
|
||||||
generics::{WherePredicate, WherePredicateTypeTarget},
|
generics::{TypeOrConstParamData, WherePredicate, WherePredicateTypeTarget},
|
||||||
path::GenericArg,
|
path::GenericArg,
|
||||||
type_ref::TraitBoundModifier,
|
type_ref::TraitBoundModifier,
|
||||||
visibility::RawVisibility,
|
visibility::RawVisibility,
|
||||||
|
@ -626,7 +626,7 @@ impl<'a> Printer<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_generic_params(&mut self, params: &GenericParams) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,24 +639,22 @@ impl<'a> Printer<'a> {
|
||||||
first = false;
|
first = false;
|
||||||
w!(self, "{}", lt.name);
|
w!(self, "{}", lt.name);
|
||||||
}
|
}
|
||||||
for (idx, ty) in params.types.iter() {
|
for (idx, x) in params.types.iter() {
|
||||||
if !first {
|
if !first {
|
||||||
w!(self, ", ");
|
w!(self, ", ");
|
||||||
}
|
}
|
||||||
first = false;
|
first = false;
|
||||||
match &ty.name {
|
match x {
|
||||||
Some(name) => w!(self, "{}", name),
|
TypeOrConstParamData::TypeParamData(ty) => match &ty.name {
|
||||||
None => w!(self, "_anon_{}", idx.into_raw()),
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (_, konst) in params.consts.iter() {
|
|
||||||
if !first {
|
|
||||||
w!(self, ", ");
|
|
||||||
}
|
|
||||||
first = false;
|
|
||||||
w!(self, "const {}: ", konst.name);
|
|
||||||
self.print_type_ref(&konst.ty);
|
|
||||||
}
|
|
||||||
w!(self, ">");
|
w!(self, ">");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -702,10 +700,12 @@ impl<'a> Printer<'a> {
|
||||||
|
|
||||||
match target {
|
match target {
|
||||||
WherePredicateTypeTarget::TypeRef(ty) => this.print_type_ref(ty),
|
WherePredicateTypeTarget::TypeRef(ty) => this.print_type_ref(ty),
|
||||||
WherePredicateTypeTarget::TypeParam(id) => match ¶ms.types[*id].name {
|
WherePredicateTypeTarget::TypeOrConstParam(id) => {
|
||||||
Some(name) => w!(this, "{}", name),
|
match ¶ms.types[*id].name() {
|
||||||
None => w!(this, "_anon_{}", id.into_raw()),
|
Some(name) => w!(this, "{}", name),
|
||||||
},
|
None => w!(this, "_anon_{}", id.into_raw()),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
w!(this, ": ");
|
w!(this, ": ");
|
||||||
this.print_type_bounds(std::slice::from_ref(bound));
|
this.print_type_bounds(std::slice::from_ref(bound));
|
||||||
|
|
|
@ -9,8 +9,8 @@ use syntax::{ast, AstNode, AstPtr};
|
||||||
use crate::{
|
use crate::{
|
||||||
attr::AttrId,
|
attr::AttrId,
|
||||||
dyn_map::{DynMap, Policy},
|
dyn_map::{DynMap, Policy},
|
||||||
ConstId, ConstParamId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId,
|
ConstId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId, StaticId,
|
||||||
StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId,
|
StructId, TraitId, TypeAliasId, TypeOrConstParamId, UnionId,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type Key<K, V> = crate::dyn_map::Key<K, V, AstPtrPolicy<K, V>>;
|
pub type Key<K, V> = crate::dyn_map::Key<K, V, AstPtrPolicy<K, V>>;
|
||||||
|
@ -28,9 +28,9 @@ pub const ENUM: Key<ast::Enum, EnumId> = Key::new();
|
||||||
pub const VARIANT: Key<ast::Variant, EnumVariantId> = Key::new();
|
pub const VARIANT: Key<ast::Variant, EnumVariantId> = Key::new();
|
||||||
pub const TUPLE_FIELD: Key<ast::TupleField, FieldId> = Key::new();
|
pub const TUPLE_FIELD: Key<ast::TupleField, FieldId> = Key::new();
|
||||||
pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new();
|
pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new();
|
||||||
pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new();
|
pub const TYPE_PARAM: Key<ast::TypeParam, TypeOrConstParamId> = Key::new();
|
||||||
|
pub const CONST_PARAM: Key<ast::ConstParam, TypeOrConstParamId> = Key::new();
|
||||||
pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = Key::new();
|
pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = Key::new();
|
||||||
pub const CONST_PARAM: Key<ast::ConstParam, ConstParamId> = Key::new();
|
|
||||||
|
|
||||||
pub const MACRO: Key<ast::Macro, MacroDefId> = Key::new();
|
pub const MACRO: Key<ast::Macro, MacroDefId> = Key::new();
|
||||||
pub const ATTR_MACRO_CALL: Key<ast::Item, MacroCallId> = Key::new();
|
pub const ATTR_MACRO_CALL: Key<ast::Item, MacroCallId> = Key::new();
|
||||||
|
|
|
@ -279,12 +279,60 @@ pub struct BlockLoc {
|
||||||
impl_intern!(BlockId, BlockLoc, intern_block, lookup_intern_block);
|
impl_intern!(BlockId, BlockLoc, intern_block, lookup_intern_block);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct TypeParamId {
|
pub struct TypeOrConstParamId {
|
||||||
pub parent: GenericDefId,
|
pub parent: GenericDefId,
|
||||||
pub local_id: LocalTypeParamId,
|
pub local_id: LocalTypeOrConstParamId,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type LocalTypeParamId = Idx<generics::TypeParamData>;
|
#[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<TypeOrConstParamId> for TypeParamId {
|
||||||
|
fn from(x: TypeOrConstParamId) -> Self {
|
||||||
|
Self(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<TypeParamId> for TypeOrConstParamId {
|
||||||
|
fn from(x: TypeParamId) -> Self {
|
||||||
|
x.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
/// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<TypeOrConstParamId> for ConstParamId {
|
||||||
|
fn from(x: TypeOrConstParamId) -> Self {
|
||||||
|
Self(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<ConstParamId> for TypeOrConstParamId {
|
||||||
|
fn from(x: ConstParamId) -> Self {
|
||||||
|
x.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type LocalTypeOrConstParamId = Idx<generics::TypeOrConstParamData>;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct LifetimeParamId {
|
pub struct LifetimeParamId {
|
||||||
|
@ -293,13 +341,6 @@ pub struct LifetimeParamId {
|
||||||
}
|
}
|
||||||
pub type LocalLifetimeParamId = Idx<generics::LifetimeParamData>;
|
pub type LocalLifetimeParamId = Idx<generics::LifetimeParamData>;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
||||||
pub struct ConstParamId {
|
|
||||||
pub parent: GenericDefId,
|
|
||||||
pub local_id: LocalConstParamId,
|
|
||||||
}
|
|
||||||
pub type LocalConstParamId = Idx<generics::ConstParamData>;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum ItemContainerId {
|
pub enum ItemContainerId {
|
||||||
ExternBlockId(ExternBlockId),
|
ExternBlockId(ExternBlockId),
|
||||||
|
@ -322,8 +363,8 @@ impl_from!(StructId, UnionId, EnumId for AdtId);
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum GenericParamId {
|
pub enum GenericParamId {
|
||||||
TypeParamId(TypeParamId),
|
TypeParamId(TypeParamId),
|
||||||
LifetimeParamId(LifetimeParamId),
|
|
||||||
ConstParamId(ConstParamId),
|
ConstParamId(ConstParamId),
|
||||||
|
LifetimeParamId(LifetimeParamId),
|
||||||
}
|
}
|
||||||
impl_from!(TypeParamId, LifetimeParamId, ConstParamId for GenericParamId);
|
impl_from!(TypeParamId, LifetimeParamId, ConstParamId for GenericParamId);
|
||||||
|
|
||||||
|
@ -632,9 +673,9 @@ impl AttrDefId {
|
||||||
AttrDefId::ExternBlockId(it) => it.lookup(db).container.krate,
|
AttrDefId::ExternBlockId(it) => it.lookup(db).container.krate,
|
||||||
AttrDefId::GenericParamId(it) => {
|
AttrDefId::GenericParamId(it) => {
|
||||||
match it {
|
match it {
|
||||||
GenericParamId::TypeParamId(it) => it.parent,
|
GenericParamId::TypeParamId(it) => it.parent(),
|
||||||
|
GenericParamId::ConstParamId(it) => it.parent(),
|
||||||
GenericParamId::LifetimeParamId(it) => it.parent,
|
GenericParamId::LifetimeParamId(it) => it.parent,
|
||||||
GenericParamId::ConstParamId(it) => it.parent,
|
|
||||||
}
|
}
|
||||||
.module(db)
|
.module(db)
|
||||||
.krate
|
.krate
|
||||||
|
|
|
@ -15,7 +15,7 @@ use crate::{
|
||||||
builtin_type::BuiltinType,
|
builtin_type::BuiltinType,
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
expr::{ExprId, LabelId, PatId},
|
expr::{ExprId, LabelId, PatId},
|
||||||
generics::GenericParams,
|
generics::{GenericParams, TypeOrConstParamData},
|
||||||
intern::Interned,
|
intern::Interned,
|
||||||
item_scope::{BuiltinShadowMode, BUILTIN_SCOPE},
|
item_scope::{BuiltinShadowMode, BUILTIN_SCOPE},
|
||||||
nameres::DefMap,
|
nameres::DefMap,
|
||||||
|
@ -25,7 +25,7 @@ use crate::{
|
||||||
AdtId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, ExternBlockId,
|
AdtId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, ExternBlockId,
|
||||||
FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, ItemContainerId, LifetimeParamId,
|
FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, ItemContainerId, LifetimeParamId,
|
||||||
LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, StructId, TraitId, TypeAliasId,
|
LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, StructId, TraitId, TypeAliasId,
|
||||||
TypeParamId, VariantId,
|
TypeOrConstParamId, VariantId,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
|
@ -68,7 +68,7 @@ enum Scope {
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum TypeNs {
|
pub enum TypeNs {
|
||||||
SelfType(ImplId),
|
SelfType(ImplId),
|
||||||
GenericParam(TypeParamId),
|
GenericParam(TypeOrConstParamId),
|
||||||
AdtId(AdtId),
|
AdtId(AdtId),
|
||||||
AdtSelfType(AdtId),
|
AdtSelfType(AdtId),
|
||||||
// Yup, enum variants are added to the types ns, but any usage of variant as
|
// 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 { .. } | Scope::ImplDefScope(_) if skip_to_mod => continue,
|
||||||
|
|
||||||
Scope::GenericParams { params, def } => {
|
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) };
|
let idx = if path.segments().len() == 1 { None } else { Some(1) };
|
||||||
return Some((
|
return Some((
|
||||||
TypeNs::GenericParam(TypeParamId { local_id, parent: *def }),
|
TypeNs::GenericParam(
|
||||||
|
TypeOrConstParamId { local_id, parent: *def }.into(),
|
||||||
|
),
|
||||||
idx,
|
idx,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -285,14 +287,18 @@ impl Resolver {
|
||||||
Scope::ExprScope(_) => continue,
|
Scope::ExprScope(_) => continue,
|
||||||
|
|
||||||
Scope::GenericParams { params, def } if n_segments > 1 => {
|
Scope::GenericParams { params, def } if n_segments > 1 => {
|
||||||
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 ty = TypeNs::GenericParam(TypeParamId { local_id, parent: *def });
|
let ty = TypeNs::GenericParam(
|
||||||
|
TypeOrConstParamId { local_id, parent: *def }.into(),
|
||||||
|
);
|
||||||
return Some(ResolveValueResult::Partial(ty, 1));
|
return Some(ResolveValueResult::Partial(ty, 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Scope::GenericParams { params, def } if n_segments == 1 => {
|
Scope::GenericParams { params, def } if n_segments == 1 => {
|
||||||
if let Some(local_id) = params.find_const_by_name(first_name) {
|
if let Some(local_id) = params.find_type_or_const_by_name(first_name) {
|
||||||
let val = ValueNs::GenericParam(ConstParamId { local_id, parent: *def });
|
let val = ValueNs::GenericParam(
|
||||||
|
TypeOrConstParamId { local_id, parent: *def }.into(),
|
||||||
|
);
|
||||||
return Some(ResolveValueResult::ValueNs(val));
|
return Some(ResolveValueResult::ValueNs(val));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -521,15 +527,22 @@ impl Scope {
|
||||||
Scope::GenericParams { params, def: parent } => {
|
Scope::GenericParams { params, def: parent } => {
|
||||||
let parent = *parent;
|
let parent = *parent;
|
||||||
for (local_id, param) in params.types.iter() {
|
for (local_id, param) in params.types.iter() {
|
||||||
if let Some(name) = ¶m.name {
|
if let Some(name) = ¶m.name() {
|
||||||
let id = TypeParamId { parent, local_id };
|
let id = TypeOrConstParamId { parent, local_id };
|
||||||
acc.add(name, ScopeDef::GenericParam(id.into()))
|
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() {
|
for (local_id, param) in params.lifetimes.iter() {
|
||||||
let id = LifetimeParamId { parent, local_id };
|
let id = LifetimeParamId { parent, local_id };
|
||||||
acc.add(¶m.name, ScopeDef::GenericParam(id.into()))
|
acc.add(¶m.name, ScopeDef::GenericParam(id.into()))
|
||||||
|
|
|
@ -71,7 +71,7 @@ pub fn find_builtin_derive(
|
||||||
|
|
||||||
struct BasicAdtInfo {
|
struct BasicAdtInfo {
|
||||||
name: tt::Ident,
|
name: tt::Ident,
|
||||||
type_params: usize,
|
type_or_const_params: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_adt(tt: &tt::Subtree) -> Result<BasicAdtInfo, ExpandError> {
|
fn parse_adt(tt: &tt::Subtree) -> Result<BasicAdtInfo, ExpandError> {
|
||||||
|
@ -104,8 +104,9 @@ fn parse_adt(tt: &tt::Subtree) -> Result<BasicAdtInfo, ExpandError> {
|
||||||
.token_by_range(name.syntax().text_range())
|
.token_by_range(name.syntax().text_range())
|
||||||
.unwrap_or_else(|| TokenId::unspecified());
|
.unwrap_or_else(|| TokenId::unspecified());
|
||||||
let name_token = tt::Ident { id: name_token_id, text: name.text().into() };
|
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());
|
let type_or_const_params =
|
||||||
Ok(BasicAdtInfo { name: name_token, type_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<tt::TokenTree>) -> Vec<tt::TokenTree> {
|
fn make_type_args(n: usize, bound: Vec<tt::TokenTree>) -> Vec<tt::TokenTree> {
|
||||||
|
@ -157,8 +158,8 @@ fn expand_simple_derive(tt: &tt::Subtree, trait_path: tt::Subtree) -> ExpandResu
|
||||||
let name = info.name;
|
let name = info.name;
|
||||||
let trait_path_clone = trait_path.token_trees.clone();
|
let trait_path_clone = trait_path.token_trees.clone();
|
||||||
let bound = (quote! { : ##trait_path_clone }).token_trees;
|
let bound = (quote! { : ##trait_path_clone }).token_trees;
|
||||||
let type_params = make_type_args(info.type_params, bound);
|
let type_params = make_type_args(info.type_or_const_params, bound);
|
||||||
let type_args = make_type_args(info.type_params, Vec::new());
|
let type_args = make_type_args(info.type_or_const_params, Vec::new());
|
||||||
let trait_path = trait_path.token_trees;
|
let trait_path = trait_path.token_trees;
|
||||||
let expanded = quote! {
|
let expanded = quote! {
|
||||||
impl ##type_params ##trait_path for #name ##type_args {}
|
impl ##type_params ##trait_path for #name ##type_args {}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
use chalk_ir::{FloatTy, IntTy, Mutability, Scalar, UintTy};
|
use chalk_ir::{FloatTy, IntTy, Mutability, Scalar, UintTy};
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
builtin_type::{BuiltinFloat, BuiltinInt, BuiltinType, BuiltinUint},
|
builtin_type::{BuiltinFloat, BuiltinInt, BuiltinType, BuiltinUint},
|
||||||
|
generics::TypeOrConstParamData,
|
||||||
type_ref::Rawness,
|
type_ref::Rawness,
|
||||||
FunctionId, GenericDefId, HasModule, ItemContainerId, Lookup, TraitId,
|
FunctionId, GenericDefId, HasModule, ItemContainerId, Lookup, TraitId,
|
||||||
};
|
};
|
||||||
|
@ -237,27 +238,30 @@ impl TyExt for Ty {
|
||||||
let id = from_placeholder_idx(db, *idx);
|
let id = from_placeholder_idx(db, *idx);
|
||||||
let generic_params = db.generic_params(id.parent);
|
let generic_params = db.generic_params(id.parent);
|
||||||
let param_data = &generic_params.types[id.local_id];
|
let param_data = &generic_params.types[id.local_id];
|
||||||
match param_data.provenance {
|
match param_data {
|
||||||
hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
|
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
|
||||||
let substs = TyBuilder::type_params_subst(db, id.parent);
|
hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
|
||||||
let predicates = db
|
let substs = TyBuilder::type_params_subst(db, id.parent);
|
||||||
.generic_predicates(id.parent)
|
let predicates = db
|
||||||
.iter()
|
.generic_predicates(id.parent)
|
||||||
.map(|pred| pred.clone().substitute(Interner, &substs))
|
.iter()
|
||||||
.filter(|wc| match &wc.skip_binders() {
|
.map(|pred| pred.clone().substitute(Interner, &substs))
|
||||||
WhereClause::Implemented(tr) => {
|
.filter(|wc| match &wc.skip_binders() {
|
||||||
&tr.self_type_parameter(Interner) == self
|
WhereClause::Implemented(tr) => {
|
||||||
}
|
&tr.self_type_parameter(Interner) == self
|
||||||
WhereClause::AliasEq(AliasEq {
|
}
|
||||||
alias: AliasTy::Projection(proj),
|
WhereClause::AliasEq(AliasEq {
|
||||||
ty: _,
|
alias: AliasTy::Projection(proj),
|
||||||
}) => &proj.self_type_parameter(Interner) == self,
|
ty: _,
|
||||||
_ => false,
|
}) => &proj.self_type_parameter(Interner) == self,
|
||||||
})
|
_ => false,
|
||||||
.collect::<Vec<_>>();
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
Some(predicates)
|
Some(predicates)
|
||||||
}
|
}
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use std::sync::Arc;
|
||||||
use base_db::{impl_intern_key, salsa, CrateId, Upcast};
|
use base_db::{impl_intern_key, salsa, CrateId, Upcast};
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
db::DefDatabase, expr::ExprId, BlockId, ConstParamId, DefWithBodyId, FunctionId, GenericDefId,
|
db::DefDatabase, expr::ExprId, BlockId, ConstParamId, DefWithBodyId, FunctionId, GenericDefId,
|
||||||
ImplId, LifetimeParamId, LocalFieldId, TypeParamId, VariantId,
|
ImplId, LifetimeParamId, LocalFieldId, TypeOrConstParamId, VariantId,
|
||||||
};
|
};
|
||||||
use la_arena::ArenaMap;
|
use la_arena::ArenaMap;
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||||
fn generic_predicates_for_param(
|
fn generic_predicates_for_param(
|
||||||
&self,
|
&self,
|
||||||
def: GenericDefId,
|
def: GenericDefId,
|
||||||
param_id: TypeParamId,
|
param_id: TypeOrConstParamId,
|
||||||
assoc_name: Option<Name>,
|
assoc_name: Option<Name>,
|
||||||
) -> Arc<[Binders<QuantifiedWhereClause>]>;
|
) -> Arc<[Binders<QuantifiedWhereClause>]>;
|
||||||
|
|
||||||
|
@ -94,12 +94,13 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||||
#[salsa::interned]
|
#[salsa::interned]
|
||||||
fn intern_callable_def(&self, callable_def: CallableDefId) -> InternedCallableDefId;
|
fn intern_callable_def(&self, callable_def: CallableDefId) -> InternedCallableDefId;
|
||||||
#[salsa::interned]
|
#[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]
|
#[salsa::interned]
|
||||||
fn intern_lifetime_param_id(&self, param_id: LifetimeParamId) -> InternedLifetimeParamId;
|
fn intern_lifetime_param_id(&self, param_id: LifetimeParamId) -> InternedLifetimeParamId;
|
||||||
#[salsa::interned]
|
#[salsa::interned]
|
||||||
fn intern_const_param_id(&self, param_id: ConstParamId) -> InternedConstParamId;
|
|
||||||
#[salsa::interned]
|
|
||||||
fn intern_impl_trait_id(&self, id: ImplTraitId) -> InternedOpaqueTyId;
|
fn intern_impl_trait_id(&self, id: ImplTraitId) -> InternedOpaqueTyId;
|
||||||
#[salsa::interned]
|
#[salsa::interned]
|
||||||
fn intern_closure(&self, id: (DefWithBodyId, ExprId)) -> InternedClosureId;
|
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)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct InternedTypeParamId(salsa::InternId);
|
pub struct InternedTypeOrConstParamId(salsa::InternId);
|
||||||
impl_intern_key!(InternedTypeParamId);
|
impl_intern_key!(InternedTypeOrConstParamId);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct InternedLifetimeParamId(salsa::InternId);
|
pub struct InternedLifetimeParamId(salsa::InternId);
|
||||||
|
|
|
@ -10,7 +10,7 @@ use hir_def::{
|
||||||
body,
|
body,
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
find_path,
|
find_path,
|
||||||
generics::TypeParamProvenance,
|
generics::{TypeOrConstParamData, TypeParamProvenance},
|
||||||
intern::{Internable, Interned},
|
intern::{Internable, Interned},
|
||||||
item_scope::ItemInNs,
|
item_scope::ItemInNs,
|
||||||
path::{Path, PathKind},
|
path::{Path, PathKind},
|
||||||
|
@ -23,7 +23,6 @@ use itertools::Itertools;
|
||||||
use syntax::SmolStr;
|
use syntax::SmolStr;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
const_from_placeholder_idx,
|
|
||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, lt_from_placeholder_idx,
|
from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, lt_from_placeholder_idx,
|
||||||
mapping::from_chalk,
|
mapping::from_chalk,
|
||||||
|
@ -319,10 +318,10 @@ impl HirDisplay for Const {
|
||||||
ConstValue::BoundVar(idx) => idx.hir_fmt(f),
|
ConstValue::BoundVar(idx) => idx.hir_fmt(f),
|
||||||
ConstValue::InferenceVar(..) => write!(f, "_"),
|
ConstValue::InferenceVar(..) => write!(f, "_"),
|
||||||
ConstValue::Placeholder(idx) => {
|
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 generics = generics(f.db.upcast(), id.parent);
|
||||||
let param_data = &generics.params.consts[id.local_id];
|
let param_data = &generics.params.types[id.local_id];
|
||||||
write!(f, "{}", param_data.name)
|
write!(f, "{}", param_data.name().unwrap())
|
||||||
}
|
}
|
||||||
ConstValue::Concrete(c) => write!(f, "{}", c.interned),
|
ConstValue::Concrete(c) => write!(f, "{}", c.interned),
|
||||||
}
|
}
|
||||||
|
@ -682,34 +681,39 @@ impl HirDisplay for Ty {
|
||||||
let id = from_placeholder_idx(f.db, *idx);
|
let id = from_placeholder_idx(f.db, *idx);
|
||||||
let generics = generics(f.db.upcast(), id.parent);
|
let generics = generics(f.db.upcast(), id.parent);
|
||||||
let param_data = &generics.params.types[id.local_id];
|
let param_data = &generics.params.types[id.local_id];
|
||||||
match param_data.provenance {
|
match param_data {
|
||||||
TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {
|
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
|
||||||
write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))?
|
TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {
|
||||||
}
|
write!(f, "{}", p.name.clone().unwrap_or_else(Name::missing))?
|
||||||
TypeParamProvenance::ArgumentImplTrait => {
|
}
|
||||||
let substs = generics.type_params_subst(f.db);
|
TypeParamProvenance::ArgumentImplTrait => {
|
||||||
let bounds =
|
let substs = generics.type_params_subst(f.db);
|
||||||
f.db.generic_predicates(id.parent)
|
let bounds =
|
||||||
.iter()
|
f.db.generic_predicates(id.parent)
|
||||||
.map(|pred| pred.clone().substitute(Interner, &substs))
|
.iter()
|
||||||
.filter(|wc| match &wc.skip_binders() {
|
.map(|pred| pred.clone().substitute(Interner, &substs))
|
||||||
WhereClause::Implemented(tr) => {
|
.filter(|wc| match &wc.skip_binders() {
|
||||||
&tr.self_type_parameter(Interner) == self
|
WhereClause::Implemented(tr) => {
|
||||||
}
|
&tr.self_type_parameter(Interner) == self
|
||||||
WhereClause::AliasEq(AliasEq {
|
}
|
||||||
alias: AliasTy::Projection(proj),
|
WhereClause::AliasEq(AliasEq {
|
||||||
ty: _,
|
alias: AliasTy::Projection(proj),
|
||||||
}) => &proj.self_type_parameter(Interner) == self,
|
ty: _,
|
||||||
_ => false,
|
}) => &proj.self_type_parameter(Interner) == self,
|
||||||
})
|
_ => false,
|
||||||
.collect::<Vec<_>>();
|
})
|
||||||
let krate = id.parent.module(f.db.upcast()).krate();
|
.collect::<Vec<_>>();
|
||||||
write_bounds_like_dyn_trait_with_prefix(
|
let krate = id.parent.module(f.db.upcast()).krate();
|
||||||
"impl",
|
write_bounds_like_dyn_trait_with_prefix(
|
||||||
&bounds,
|
"impl",
|
||||||
SizedByDefault::Sized { anchor: krate },
|
&bounds,
|
||||||
f,
|
SizedByDefault::Sized { anchor: krate },
|
||||||
)?;
|
f,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
TypeOrConstParamData::ConstParamData(p) => {
|
||||||
|
write!(f, "{}", p.name)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ use std::{
|
||||||
use chalk_ir::{cast::Cast, fold::Shift, Mutability, TyVariableKind};
|
use chalk_ir::{cast::Cast, fold::Shift, Mutability, TyVariableKind};
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
expr::{ArithOp, Array, BinaryOp, CmpOp, Expr, ExprId, Literal, Ordering, Statement, UnaryOp},
|
expr::{ArithOp, Array, BinaryOp, CmpOp, Expr, ExprId, Literal, Ordering, Statement, UnaryOp},
|
||||||
|
generics::TypeOrConstParamData,
|
||||||
path::{GenericArg, GenericArgs},
|
path::{GenericArg, GenericArgs},
|
||||||
resolver::resolver_for_expr,
|
resolver::resolver_for_expr,
|
||||||
FieldId, FunctionId, ItemContainerId, Lookup,
|
FieldId, FunctionId, ItemContainerId, Lookup,
|
||||||
|
@ -1037,8 +1038,15 @@ impl<'a> InferenceContext<'a> {
|
||||||
let total_len = parent_params + type_params + impl_trait_params;
|
let total_len = parent_params + type_params + impl_trait_params;
|
||||||
let mut substs = Vec::with_capacity(total_len);
|
let mut substs = Vec::with_capacity(total_len);
|
||||||
// Parent arguments are unknown
|
// Parent arguments are unknown
|
||||||
for _ in def_generics.iter_parent() {
|
for (_id, param) in def_generics.iter_parent() {
|
||||||
substs.push(self.table.new_type_var());
|
match param {
|
||||||
|
TypeOrConstParamData::TypeParamData(_) => {
|
||||||
|
substs.push(self.table.new_type_var());
|
||||||
|
}
|
||||||
|
TypeOrConstParamData::ConstParamData(_) => {
|
||||||
|
// FIXME: here we should do something
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// handle provided type arguments
|
// handle provided type arguments
|
||||||
if let Some(generic_args) = generic_args {
|
if let Some(generic_args) = generic_args {
|
||||||
|
|
|
@ -40,7 +40,7 @@ use chalk_ir::{
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
expr::ExprId,
|
expr::ExprId,
|
||||||
type_ref::{ConstScalar, Rawness},
|
type_ref::{ConstScalar, Rawness},
|
||||||
TypeParamId,
|
TypeOrConstParamId,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{db::HirDatabase, utils::generics};
|
use crate::{db::HirDatabase, utils::generics};
|
||||||
|
@ -55,9 +55,9 @@ pub use lower::{
|
||||||
TyDefId, TyLoweringContext, ValueTyDefId,
|
TyDefId, TyLoweringContext, ValueTyDefId,
|
||||||
};
|
};
|
||||||
pub use mapping::{
|
pub use mapping::{
|
||||||
const_from_placeholder_idx, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
|
from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx,
|
||||||
from_placeholder_idx, lt_from_placeholder_idx, to_assoc_type_id, to_chalk_trait_id,
|
lt_from_placeholder_idx, to_assoc_type_id, to_chalk_trait_id, to_foreign_def_id,
|
||||||
to_foreign_def_id, to_placeholder_idx,
|
to_placeholder_idx,
|
||||||
};
|
};
|
||||||
pub use traits::TraitEnvironment;
|
pub use traits::TraitEnvironment;
|
||||||
pub use utils::all_super_traits;
|
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.
|
/// 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<usize> {
|
pub fn param_idx(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option<usize> {
|
||||||
generics(db.upcast(), id.parent).param_idx(id)
|
generics(db.upcast(), id.parent).param_idx(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ use std::{iter, sync::Arc};
|
||||||
|
|
||||||
use base_db::CrateId;
|
use base_db::CrateId;
|
||||||
use chalk_ir::{cast::Cast, fold::Shift, interner::HasInterner, Mutability, Safety};
|
use chalk_ir::{cast::Cast, fold::Shift, interner::HasInterner, Mutability, Safety};
|
||||||
|
use hir_def::generics::TypeOrConstParamData;
|
||||||
use hir_def::intern::Interned;
|
use hir_def::intern::Interned;
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
adt::StructKind,
|
adt::StructKind,
|
||||||
|
@ -19,15 +20,16 @@ use hir_def::{
|
||||||
path::{GenericArg, Path, PathSegment, PathSegments},
|
path::{GenericArg, Path, PathSegment, PathSegments},
|
||||||
resolver::{HasResolver, Resolver, TypeNs},
|
resolver::{HasResolver, Resolver, TypeNs},
|
||||||
type_ref::{TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef},
|
type_ref::{TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef},
|
||||||
AdtId, AssocItemId, ConstId, ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId,
|
AdtId, AssocItemId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule,
|
||||||
HasModule, ImplId, ItemContainerId, LocalFieldId, Lookup, StaticId, StructId, TraitId,
|
ImplId, ItemContainerId, LocalFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId,
|
||||||
TypeAliasId, TypeParamId, UnionId, VariantId,
|
UnionId, VariantId,
|
||||||
};
|
};
|
||||||
|
use hir_def::{ConstParamId, TypeOrConstParamId};
|
||||||
use hir_expand::{name::Name, ExpandResult};
|
use hir_expand::{name::Name, ExpandResult};
|
||||||
use la_arena::ArenaMap;
|
use la_arena::ArenaMap;
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use stdx::impl_from;
|
use stdx::{impl_from, never};
|
||||||
use syntax::{ast, SmolStr};
|
use syntax::{ast, SmolStr};
|
||||||
|
|
||||||
use crate::all_super_traits;
|
use crate::all_super_traits;
|
||||||
|
@ -267,7 +269,7 @@ impl<'a> TyLoweringContext<'a> {
|
||||||
if let Some(def) = self.resolver.generic_def() {
|
if let Some(def) = self.resolver.generic_def() {
|
||||||
let generics = generics(self.db.upcast(), def);
|
let generics = generics(self.db.upcast(), def);
|
||||||
let param = generics
|
let param = generics
|
||||||
.iter()
|
.type_iter()
|
||||||
.filter(|(_, data)| {
|
.filter(|(_, data)| {
|
||||||
data.provenance == TypeParamProvenance::ArgumentImplTrait
|
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
|
/// 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.
|
/// 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.
|
/// 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<TypeParamId> {
|
fn lower_ty_only_param(&self, type_ref: &TypeRef) -> Option<TypeOrConstParamId> {
|
||||||
let path = match type_ref {
|
let path = match type_ref {
|
||||||
TypeRef::Path(path) => path,
|
TypeRef::Path(path) => path,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
|
@ -469,10 +471,10 @@ impl<'a> TyLoweringContext<'a> {
|
||||||
);
|
);
|
||||||
match self.type_param_mode {
|
match self.type_param_mode {
|
||||||
TypeParamLoweringMode::Placeholder => {
|
TypeParamLoweringMode::Placeholder => {
|
||||||
TyKind::Placeholder(to_placeholder_idx(self.db, param_id))
|
TyKind::Placeholder(to_placeholder_idx(self.db, param_id.into()))
|
||||||
}
|
}
|
||||||
TypeParamLoweringMode::Variable => {
|
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))
|
TyKind::BoundVar(BoundVar::new(self.in_binders, idx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -758,11 +760,13 @@ impl<'a> TyLoweringContext<'a> {
|
||||||
| WherePredicate::TypeBound { target, bound } => {
|
| WherePredicate::TypeBound { target, bound } => {
|
||||||
let self_ty = match target {
|
let self_ty = match target {
|
||||||
WherePredicateTypeTarget::TypeRef(type_ref) => self.lower_ty(type_ref),
|
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 generic_def = self.resolver.generic_def().expect("generics in scope");
|
||||||
let generics = generics(self.db.upcast(), generic_def);
|
let generics = generics(self.db.upcast(), generic_def);
|
||||||
let param_id =
|
let param_id = hir_def::TypeOrConstParamId {
|
||||||
hir_def::TypeParamId { parent: generic_def, local_id: *param_id };
|
parent: generic_def,
|
||||||
|
local_id: *param_id,
|
||||||
|
};
|
||||||
let placeholder = to_placeholder_idx(self.db, param_id);
|
let placeholder = to_placeholder_idx(self.db, param_id);
|
||||||
match self.type_param_mode {
|
match self.type_param_mode {
|
||||||
TypeParamLoweringMode::Placeholder => TyKind::Placeholder(placeholder),
|
TypeParamLoweringMode::Placeholder => TyKind::Placeholder(placeholder),
|
||||||
|
@ -973,7 +977,7 @@ fn named_associated_type_shorthand_candidates<R>(
|
||||||
db.impl_trait(impl_id)?.into_value_and_skipped_binders().0,
|
db.impl_trait(impl_id)?.into_value_and_skipped_binders().0,
|
||||||
),
|
),
|
||||||
TypeNs::GenericParam(param_id) => {
|
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() {
|
let res = predicates.iter().find_map(|pred| match pred.skip_binders().skip_binders() {
|
||||||
// FIXME: how to correctly handle higher-ranked bounds here?
|
// FIXME: how to correctly handle higher-ranked bounds here?
|
||||||
WhereClause::Implemented(tr) => search(
|
WhereClause::Implemented(tr) => search(
|
||||||
|
@ -989,9 +993,7 @@ fn named_associated_type_shorthand_candidates<R>(
|
||||||
// Handle `Self::Type` referring to own associated type in trait definitions
|
// 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());
|
let generics = generics(db.upcast(), trait_id.into());
|
||||||
if generics.params.types[param_id.local_id].provenance
|
if generics.params.types[param_id.local_id].is_trait_self() {
|
||||||
== TypeParamProvenance::TraitSelf
|
|
||||||
{
|
|
||||||
let trait_ref = TyBuilder::trait_ref(db, trait_id)
|
let trait_ref = TyBuilder::trait_ref(db, trait_id)
|
||||||
.fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
|
.fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
|
||||||
.build();
|
.build();
|
||||||
|
@ -1036,7 +1038,7 @@ pub(crate) fn field_types_query(
|
||||||
pub(crate) fn generic_predicates_for_param_query(
|
pub(crate) fn generic_predicates_for_param_query(
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
def: GenericDefId,
|
def: GenericDefId,
|
||||||
param_id: TypeParamId,
|
param_id: TypeOrConstParamId,
|
||||||
assoc_name: Option<Name>,
|
assoc_name: Option<Name>,
|
||||||
) -> Arc<[Binders<QuantifiedWhereClause>]> {
|
) -> Arc<[Binders<QuantifiedWhereClause>]> {
|
||||||
let resolver = def.resolver(db.upcast());
|
let resolver = def.resolver(db.upcast());
|
||||||
|
@ -1051,11 +1053,11 @@ pub(crate) fn generic_predicates_for_param_query(
|
||||||
| WherePredicate::TypeBound { target, bound, .. } => {
|
| WherePredicate::TypeBound { target, bound, .. } => {
|
||||||
match target {
|
match target {
|
||||||
WherePredicateTypeTarget::TypeRef(type_ref) => {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WherePredicateTypeTarget::TypeParam(local_id) => {
|
WherePredicateTypeTarget::TypeOrConstParam(local_id) => {
|
||||||
if *local_id != param_id.local_id {
|
if *local_id != param_id.local_id {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1105,7 +1107,7 @@ pub(crate) fn generic_predicates_for_param_recover(
|
||||||
_db: &dyn HirDatabase,
|
_db: &dyn HirDatabase,
|
||||||
_cycle: &[String],
|
_cycle: &[String],
|
||||||
_def: &GenericDefId,
|
_def: &GenericDefId,
|
||||||
_param_id: &TypeParamId,
|
_param_id: &TypeOrConstParamId,
|
||||||
_assoc_name: &Option<Name>,
|
_assoc_name: &Option<Name>,
|
||||||
) -> Arc<[Binders<QuantifiedWhereClause>]> {
|
) -> Arc<[Binders<QuantifiedWhereClause>]> {
|
||||||
Arc::new([])
|
Arc::new([])
|
||||||
|
@ -1233,7 +1235,7 @@ pub(crate) fn generic_defaults_query(
|
||||||
let generic_params = generics(db.upcast(), def);
|
let generic_params = generics(db.upcast(), def);
|
||||||
|
|
||||||
let defaults = generic_params
|
let defaults = generic_params
|
||||||
.iter()
|
.type_iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(idx, (_, p))| {
|
.map(|(idx, (_, p))| {
|
||||||
let mut ty =
|
let mut ty =
|
||||||
|
@ -1267,7 +1269,7 @@ pub(crate) fn generic_defaults_recover(
|
||||||
|
|
||||||
// we still need one default per parameter
|
// we still need one default per parameter
|
||||||
let defaults = generic_params
|
let defaults = generic_params
|
||||||
.iter()
|
.type_iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(idx, _)| {
|
.map(|(idx, _)| {
|
||||||
let ty = TyKind::Error.intern(Interner);
|
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))
|
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 {
|
pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty {
|
||||||
let parent_data = db.generic_params(def.parent);
|
let parent_data = db.generic_params(def.parent());
|
||||||
let data = &parent_data.consts[def.local_id];
|
let data = &parent_data.types[def.local_id()];
|
||||||
let resolver = def.parent.resolver(db.upcast());
|
let resolver = def.parent().resolver(db.upcast());
|
||||||
let ctx = TyLoweringContext::new(db, &resolver);
|
let ctx = TyLoweringContext::new(db, &resolver);
|
||||||
|
match data {
|
||||||
ctx.lower_ty(&data.ty)
|
TypeOrConstParamData::TypeParamData(_) => {
|
||||||
|
never!();
|
||||||
|
Ty::new(Interner, TyKind::Error)
|
||||||
|
}
|
||||||
|
TypeOrConstParamData::ConstParamData(d) => ctx.lower_ty(&d.ty),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn impl_self_ty_recover(
|
pub(crate) fn impl_self_ty_recover(
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
use chalk_solve::rust_ir;
|
use chalk_solve::rust_ir;
|
||||||
|
|
||||||
use base_db::salsa::{self, InternKey};
|
use base_db::salsa::{self, InternKey};
|
||||||
use hir_def::{ConstParamId, LifetimeParamId, TraitId, TypeAliasId, TypeParamId};
|
use hir_def::{LifetimeParamId, TraitId, TypeAliasId, TypeOrConstParamId};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
chalk_db, db::HirDatabase, AssocTypeId, CallableDefId, ChalkTraitId, FnDefId, ForeignDefId,
|
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)
|
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);
|
assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
|
||||||
let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx));
|
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 {
|
pub fn to_placeholder_idx(db: &dyn HirDatabase, id: TypeOrConstParamId) -> PlaceholderIndex {
|
||||||
let interned_id = db.intern_type_param_id(id);
|
let interned_id = db.intern_type_or_const_param_id(id);
|
||||||
PlaceholderIndex {
|
PlaceholderIndex {
|
||||||
ui: chalk_ir::UniverseIndex::ROOT,
|
ui: chalk_ir::UniverseIndex::ROOT,
|
||||||
idx: salsa::InternKey::as_intern_id(&interned_id).as_usize(),
|
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)
|
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 {
|
pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId {
|
||||||
chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id))
|
chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id))
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,13 +8,14 @@ use chalk_ir::{fold::Shift, BoundVar, DebruijnIndex};
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
generics::{
|
generics::{
|
||||||
GenericParams, TypeParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
|
GenericParams, TypeOrConstParamData, TypeParamData, TypeParamProvenance, WherePredicate,
|
||||||
|
WherePredicateTypeTarget,
|
||||||
},
|
},
|
||||||
intern::Interned,
|
intern::Interned,
|
||||||
path::Path,
|
path::Path,
|
||||||
resolver::{HasResolver, TypeNs},
|
resolver::{HasResolver, TypeNs},
|
||||||
type_ref::{TraitBoundModifier, TypeRef},
|
type_ref::{TraitBoundModifier, TypeRef},
|
||||||
GenericDefId, ItemContainerId, Lookup, TraitId, TypeAliasId, TypeParamId,
|
GenericDefId, ItemContainerId, Lookup, TraitId, TypeAliasId, TypeOrConstParamId,
|
||||||
};
|
};
|
||||||
use hir_expand::name::{name, Name};
|
use hir_expand::name::{name, Name};
|
||||||
use rustc_hash::FxHashSet;
|
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(),
|
TypeRef::Path(p) if p == &Path::from(name![Self]) => bound.as_path(),
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
WherePredicateTypeTarget::TypeParam(local_id) if Some(*local_id) == trait_self => {
|
WherePredicateTypeTarget::TypeOrConstParam(local_id)
|
||||||
|
if Some(*local_id) == trait_self =>
|
||||||
|
{
|
||||||
bound.as_path()
|
bound.as_path()
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -80,7 +83,7 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr
|
||||||
// SmallVec if performance is a concern)
|
// SmallVec if performance is a concern)
|
||||||
let generic_params = db.generic_params(trait_ref.hir_trait_id().into());
|
let generic_params = db.generic_params(trait_ref.hir_trait_id().into());
|
||||||
let trait_self = match generic_params.find_trait_self_param() {
|
let trait_self = match generic_params.find_trait_self_param() {
|
||||||
Some(p) => 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(),
|
None => return Vec::new(),
|
||||||
};
|
};
|
||||||
db.generic_predicates_for_param(trait_self.parent, trait_self, None)
|
db.generic_predicates_for_param(trait_self.parent, trait_self, None)
|
||||||
|
@ -181,34 +184,33 @@ pub(crate) struct Generics {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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,
|
&'a self,
|
||||||
) -> impl Iterator<Item = (TypeParamId, &'a TypeParamData)> + 'a {
|
) -> impl Iterator<Item = (TypeOrConstParamId, &'a TypeParamData)> + 'a {
|
||||||
self.parent_generics
|
self.parent_generics
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map(|it| {
|
.flat_map(|it| {
|
||||||
it.params
|
it.params
|
||||||
.types
|
.type_iter()
|
||||||
.iter()
|
.map(move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p))
|
||||||
.map(move |(local_id, p)| (TypeParamId { parent: it.def, local_id }, p))
|
|
||||||
})
|
})
|
||||||
.chain(
|
.chain(
|
||||||
self.params
|
self.params.type_iter().map(move |(local_id, p)| {
|
||||||
.types
|
(TypeOrConstParamId { parent: self.def, local_id }, p)
|
||||||
.iter()
|
}),
|
||||||
.map(move |(local_id, p)| (TypeParamId { parent: self.def, local_id }, p)),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn iter_parent<'a>(
|
pub(crate) fn iter_parent<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
) -> impl Iterator<Item = (TypeParamId, &'a TypeParamData)> + 'a {
|
) -> impl Iterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
|
||||||
self.parent_generics.as_ref().into_iter().flat_map(|it| {
|
self.parent_generics.as_ref().into_iter().flat_map(|it| {
|
||||||
it.params
|
it.params
|
||||||
.types
|
.types
|
||||||
.iter()
|
.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)
|
/// (total, parents, child)
|
||||||
pub(crate) fn len_split(&self) -> (usize, usize, usize) {
|
pub(crate) fn len_split(&self) -> (usize, usize, usize) {
|
||||||
let parent = self.parent_generics.as_ref().map_or(0, |p| p.len());
|
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)
|
(parent + child, parent, child)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,28 +233,31 @@ impl Generics {
|
||||||
.params
|
.params
|
||||||
.types
|
.types
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, p)| p.provenance == TypeParamProvenance::TraitSelf)
|
.filter_map(|x| x.1.type_param())
|
||||||
|
.filter(|p| p.provenance == TypeParamProvenance::TraitSelf)
|
||||||
.count();
|
.count();
|
||||||
let list_params = self
|
let list_params = self
|
||||||
.params
|
.params
|
||||||
.types
|
.types
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, p)| p.provenance == TypeParamProvenance::TypeParamList)
|
.filter_map(|x| x.1.type_param())
|
||||||
|
.filter(|p| p.provenance == TypeParamProvenance::TypeParamList)
|
||||||
.count();
|
.count();
|
||||||
let impl_trait_params = self
|
let impl_trait_params = self
|
||||||
.params
|
.params
|
||||||
.types
|
.types
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, p)| p.provenance == TypeParamProvenance::ArgumentImplTrait)
|
.filter_map(|x| x.1.type_param())
|
||||||
|
.filter(|p| p.provenance == TypeParamProvenance::ArgumentImplTrait)
|
||||||
.count();
|
.count();
|
||||||
(parent, self_params, list_params, impl_trait_params)
|
(parent, self_params, list_params, impl_trait_params)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn param_idx(&self, param: TypeParamId) -> Option<usize> {
|
pub(crate) fn param_idx(&self, param: TypeOrConstParamId) -> Option<usize> {
|
||||||
Some(self.find_param(param)?.0)
|
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 {
|
if param.parent == self.def {
|
||||||
let (idx, (_local_id, data)) = self
|
let (idx, (_local_id, data)) = self
|
||||||
.params
|
.params
|
||||||
|
@ -271,7 +277,7 @@ impl Generics {
|
||||||
pub(crate) fn bound_vars_subst(&self, debruijn: DebruijnIndex) -> Substitution {
|
pub(crate) fn bound_vars_subst(&self, debruijn: DebruijnIndex) -> Substitution {
|
||||||
Substitution::from_iter(
|
Substitution::from_iter(
|
||||||
Interner,
|
Interner,
|
||||||
self.iter()
|
self.type_iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(idx, _)| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(Interner)),
|
.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 {
|
pub(crate) fn type_params_subst(&self, db: &dyn HirDatabase) -> Substitution {
|
||||||
Substitution::from_iter(
|
Substitution::from_iter(
|
||||||
Interner,
|
Interner,
|
||||||
self.iter().map(|(id, _)| {
|
self.type_iter().map(|(id, _)| {
|
||||||
TyKind::Placeholder(crate::to_placeholder_idx(db, id)).intern(Interner)
|
TyKind::Placeholder(crate::to_placeholder_idx(db, id)).intern(Interner)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
|
@ -2913,6 +2913,27 @@ fn main() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn const_generic_order() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
struct Foo;
|
||||||
|
struct S$0T<const C: usize = 1, T = Foo>(T);
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
*ST*
|
||||||
|
|
||||||
|
```rust
|
||||||
|
test
|
||||||
|
```
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct ST<const C: usize, T = Foo>
|
||||||
|
```
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn hover_self_param_shows_type() {
|
fn hover_self_param_shows_type() {
|
||||||
check(
|
check(
|
||||||
|
|
|
@ -12,6 +12,7 @@ use ide_db::{
|
||||||
SymbolKind,
|
SymbolKind,
|
||||||
};
|
};
|
||||||
use ide_db::{defs::Definition, RootDatabase};
|
use ide_db::{defs::Definition, RootDatabase};
|
||||||
|
use stdx::never;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, HasName},
|
ast::{self, HasName},
|
||||||
match_ast, AstNode, SmolStr, SyntaxNode, TextRange,
|
match_ast, AstNode, SmolStr, SyntaxNode, TextRange,
|
||||||
|
@ -435,9 +436,18 @@ impl ToNav for hir::Label {
|
||||||
|
|
||||||
impl TryToNav for hir::TypeParam {
|
impl TryToNav for hir::TypeParam {
|
||||||
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
||||||
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 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 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 focus_range = |syntax: &_| InFile::new(file_id, syntax).original_file_range_opt(db);
|
||||||
let FileRange { file_id, range: full_range } = match &value {
|
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<NavigationTarget> {
|
||||||
|
self.split(db).try_to_nav(db)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TryToNav for hir::LifetimeParam {
|
impl TryToNav for hir::LifetimeParam {
|
||||||
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
||||||
let InFile { file_id, value } = self.source(db)?;
|
let InFile { file_id, value } = self.source(db)?;
|
||||||
|
@ -486,9 +502,17 @@ impl TryToNav for hir::LifetimeParam {
|
||||||
|
|
||||||
impl TryToNav for hir::ConstParam {
|
impl TryToNav for hir::ConstParam {
|
||||||
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
||||||
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 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 focus_range = value.name().and_then(|it| orig_focus_range(db, file_id, it.syntax()));
|
||||||
let FileRange { file_id, range: full_range } =
|
let FileRange { file_id, range: full_range } =
|
||||||
InFile::new(file_id, value.syntax()).original_file_range(db);
|
InFile::new(file_id, value.syntax()).original_file_range(db);
|
||||||
|
|
|
@ -259,8 +259,8 @@ fn module_def_to_hl_tag(def: Definition) -> HlTag {
|
||||||
Definition::Local(_) => SymbolKind::Local,
|
Definition::Local(_) => SymbolKind::Local,
|
||||||
Definition::GenericParam(gp) => match gp {
|
Definition::GenericParam(gp) => match gp {
|
||||||
hir::GenericParam::TypeParam(_) => SymbolKind::TypeParam,
|
hir::GenericParam::TypeParam(_) => SymbolKind::TypeParam,
|
||||||
hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam,
|
|
||||||
hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam,
|
hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam,
|
||||||
|
hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam,
|
||||||
},
|
},
|
||||||
Definition::Label(_) => SymbolKind::Label,
|
Definition::Label(_) => SymbolKind::Label,
|
||||||
Definition::BuiltinAttr(_) => SymbolKind::BuiltinAttr,
|
Definition::BuiltinAttr(_) => SymbolKind::BuiltinAttr,
|
||||||
|
|
|
@ -109,6 +109,13 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
<span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="variable declaration injected">foobar</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="operator injected">.</span><span class="function injected">bar</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span>
|
<span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="variable declaration injected">foobar</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="operator injected">.</span><span class="function injected">bar</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span>
|
||||||
<span class="comment documentation">/// ```</span>
|
<span class="comment documentation">/// ```</span>
|
||||||
<span class="comment documentation">///</span>
|
<span class="comment documentation">///</span>
|
||||||
|
<span class="comment documentation">/// ```</span>
|
||||||
|
<span class="comment documentation">/// </span><span class="comment injected">// functions</span>
|
||||||
|
<span class="comment documentation">/// </span><span class="keyword injected">fn</span><span class="none injected"> </span><span class="function declaration injected">foo</span><span class="angle injected"><</span><span class="type_param declaration injected">T</span><span class="comma injected">,</span><span class="none injected"> </span><span class="keyword injected">const</span><span class="none injected"> </span><span class="const_param declaration injected">X</span><span class="colon injected">:</span><span class="none injected"> </span><span class="builtin_type injected">usize</span><span class="angle injected">></span><span class="parenthesis injected">(</span><span class="value_param declaration injected">arg</span><span class="colon injected">:</span><span class="none injected"> </span><span class="builtin_type injected">i32</span><span class="parenthesis injected">)</span><span class="none injected"> </span><span class="brace injected">{</span>
|
||||||
|
<span class="comment documentation">/// </span><span class="none injected"> </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="variable declaration injected">x</span><span class="colon injected">:</span><span class="none injected"> </span><span class="type_param injected">T</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="const_param injected">X</span><span class="semicolon injected">;</span>
|
||||||
|
<span class="comment documentation">/// </span><span class="brace injected">}</span>
|
||||||
|
<span class="comment documentation">/// ```</span>
|
||||||
|
<span class="comment documentation">///</span>
|
||||||
<span class="comment documentation">/// ```sh</span>
|
<span class="comment documentation">/// ```sh</span>
|
||||||
<span class="comment documentation">/// echo 1</span>
|
<span class="comment documentation">/// echo 1</span>
|
||||||
<span class="comment documentation">/// ```</span>
|
<span class="comment documentation">/// ```</span>
|
||||||
|
|
|
@ -599,6 +599,13 @@ impl Foo {
|
||||||
/// let foobar = Foo::new().bar();
|
/// let foobar = Foo::new().bar();
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
/// ```
|
||||||
|
/// // functions
|
||||||
|
/// fn foo<T, const X: usize>(arg: i32) {
|
||||||
|
/// let x: T = X;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
/// ```sh
|
/// ```sh
|
||||||
/// echo 1
|
/// echo 1
|
||||||
/// ```
|
/// ```
|
||||||
|
|
|
@ -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 {
|
if let Some(generic_params) = &generic_params {
|
||||||
let lifetimes = generic_params.lifetime_params().map(|lt| format!("{}", lt.syntax()));
|
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| match toc_param {
|
||||||
let mut buf = String::new();
|
ast::TypeOrConstParam::Type(type_param) => {
|
||||||
if let Some(it) = type_param.name() {
|
let mut buf = String::new();
|
||||||
format_to!(buf, "{}", it.syntax());
|
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() {
|
ast::TypeOrConstParam::Const(const_param) => const_param.syntax().to_string(),
|
||||||
format_to!(buf, "{} ", it);
|
|
||||||
}
|
|
||||||
if let Some(it) = type_param.type_bound_list() {
|
|
||||||
format_to!(buf, "{}", it.syntax());
|
|
||||||
}
|
|
||||||
buf
|
|
||||||
});
|
});
|
||||||
let const_params = generic_params.const_params().map(|t| t.syntax().to_string());
|
let generics = lifetimes.chain(toc_params).format(", ");
|
||||||
let generics = lifetimes.chain(type_params).chain(const_params).format(", ");
|
|
||||||
format_to!(buf, "<{}>", generics);
|
format_to!(buf, "<{}>", generics);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,11 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
|
||||||
pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
||||||
let type_param_list = ctx.find_node_at_offset::<ast::GenericParamList>()?;
|
let type_param_list = ctx.find_node_at_offset::<ast::GenericParamList>()?;
|
||||||
|
|
||||||
let mut type_params = type_param_list.type_params();
|
let mut type_params = type_param_list.type_or_const_params();
|
||||||
if type_params.all(|p| p.type_bound_list().is_none()) {
|
if type_params.all(|p| match p {
|
||||||
|
ast::TypeOrConstParam::Type(t) => t.type_bound_list().is_none(),
|
||||||
|
ast::TypeOrConstParam::Const(_) => true,
|
||||||
|
}) {
|
||||||
return None;
|
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(tbl) = type_param.type_bound_list() {
|
||||||
if let Some(predicate) = build_predicate(type_param) {
|
if let Some(predicate) = build_predicate(type_param) {
|
||||||
where_clause.add_predicate(predicate)
|
where_clause.add_predicate(predicate)
|
||||||
|
|
|
@ -435,7 +435,11 @@ fn generate_impl_text_inner(adt: &ast::Adt, trait_text: Option<&str>, code: &str
|
||||||
buf.push_str("impl");
|
buf.push_str("impl");
|
||||||
if let Some(generic_params) = &generic_params {
|
if let Some(generic_params) = &generic_params {
|
||||||
let lifetimes = generic_params.lifetime_params().map(|lt| format!("{}", lt.syntax()));
|
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();
|
let mut buf = String::new();
|
||||||
if let Some(it) = type_param.name() {
|
if let Some(it) = type_param.name() {
|
||||||
format_to!(buf, "{}", it.syntax());
|
format_to!(buf, "{}", it.syntax());
|
||||||
|
@ -448,8 +452,7 @@ fn generate_impl_text_inner(adt: &ast::Adt, trait_text: Option<&str>, code: &str
|
||||||
}
|
}
|
||||||
buf
|
buf
|
||||||
});
|
});
|
||||||
let const_params = generic_params.const_params().map(|t| t.syntax().to_string());
|
let generics = lifetimes.chain(toc_params).format(", ");
|
||||||
let generics = lifetimes.chain(type_params).chain(const_params).format(", ");
|
|
||||||
format_to!(buf, "<{}>", generics);
|
format_to!(buf, "<{}>", generics);
|
||||||
}
|
}
|
||||||
buf.push(' ');
|
buf.push(' ');
|
||||||
|
@ -463,15 +466,11 @@ fn generate_impl_text_inner(adt: &ast::Adt, trait_text: Option<&str>, code: &str
|
||||||
.lifetime_params()
|
.lifetime_params()
|
||||||
.filter_map(|it| it.lifetime())
|
.filter_map(|it| it.lifetime())
|
||||||
.map(|it| SmolStr::from(it.text()));
|
.map(|it| SmolStr::from(it.text()));
|
||||||
let type_params = generic_params
|
let toc_params = generic_params
|
||||||
.type_params()
|
.type_or_const_params()
|
||||||
.filter_map(|it| it.name())
|
.filter_map(|it| it.name())
|
||||||
.map(|it| SmolStr::from(it.text()));
|
.map(|it| SmolStr::from(it.text()));
|
||||||
let const_params = generic_params
|
format_to!(buf, "<{}>", lifetime_params.chain(toc_params).format(", "))
|
||||||
.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(", "))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match adt.where_clause() {
|
match adt.where_clause() {
|
||||||
|
|
|
@ -201,8 +201,8 @@ fn render_resolution_(
|
||||||
ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType,
|
ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType,
|
||||||
ScopeDef::GenericParam(param) => CompletionItemKind::SymbolKind(match param {
|
ScopeDef::GenericParam(param) => CompletionItemKind::SymbolKind(match param {
|
||||||
hir::GenericParam::TypeParam(_) => SymbolKind::TypeParam,
|
hir::GenericParam::TypeParam(_) => SymbolKind::TypeParam,
|
||||||
hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam,
|
|
||||||
hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam,
|
hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam,
|
||||||
|
hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam,
|
||||||
}),
|
}),
|
||||||
ScopeDef::Local(..) => CompletionItemKind::SymbolKind(SymbolKind::Local),
|
ScopeDef::Local(..) => CompletionItemKind::SymbolKind(SymbolKind::Local),
|
||||||
ScopeDef::Label(..) => CompletionItemKind::SymbolKind(SymbolKind::Label),
|
ScopeDef::Label(..) => CompletionItemKind::SymbolKind(SymbolKind::Label),
|
||||||
|
|
|
@ -129,12 +129,12 @@ impl RootDatabase {
|
||||||
hir::db::FnDefDatumQuery
|
hir::db::FnDefDatumQuery
|
||||||
hir::db::ReturnTypeImplTraitsQuery
|
hir::db::ReturnTypeImplTraitsQuery
|
||||||
hir::db::InternCallableDefQuery
|
hir::db::InternCallableDefQuery
|
||||||
hir::db::InternTypeParamIdQuery
|
hir::db::InternTypeOrConstParamIdQuery
|
||||||
hir::db::InternImplTraitIdQuery
|
hir::db::InternImplTraitIdQuery
|
||||||
hir::db::InternClosureQuery
|
hir::db::InternClosureQuery
|
||||||
hir::db::AssociatedTyValueQuery
|
hir::db::AssociatedTyValueQuery
|
||||||
hir::db::TraitSolveQueryQuery
|
hir::db::TraitSolveQueryQuery
|
||||||
hir::db::InternTypeParamIdQuery
|
hir::db::InternTypeOrConstParamIdQuery
|
||||||
|
|
||||||
// SymbolsDatabase
|
// SymbolsDatabase
|
||||||
crate::symbol_index::ModuleSymbolsQuery
|
crate::symbol_index::ModuleSymbolsQuery
|
||||||
|
|
|
@ -482,9 +482,9 @@ impl From<PathResolution> for Definition {
|
||||||
}
|
}
|
||||||
PathResolution::Local(local) => Definition::Local(local),
|
PathResolution::Local(local) => Definition::Local(local),
|
||||||
PathResolution::TypeParam(par) => Definition::GenericParam(par.into()),
|
PathResolution::TypeParam(par) => Definition::GenericParam(par.into()),
|
||||||
|
PathResolution::ConstParam(par) => Definition::GenericParam(par.into()),
|
||||||
PathResolution::Macro(def) => Definition::Macro(def),
|
PathResolution::Macro(def) => Definition::Macro(def),
|
||||||
PathResolution::SelfType(impl_def) => Definition::SelfType(impl_def),
|
PathResolution::SelfType(impl_def) => Definition::SelfType(impl_def),
|
||||||
PathResolution::ConstParam(par) => Definition::GenericParam(par.into()),
|
|
||||||
PathResolution::BuiltinAttr(attr) => Definition::BuiltinAttr(attr),
|
PathResolution::BuiltinAttr(attr) => Definition::BuiltinAttr(attr),
|
||||||
PathResolution::ToolModule(tool) => Definition::ToolModule(tool),
|
PathResolution::ToolModule(tool) => Definition::ToolModule(tool),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//! See [`PathTransform`].
|
//! See [`PathTransform`].
|
||||||
|
|
||||||
use crate::helpers::mod_path_to_ast;
|
use crate::helpers::mod_path_to_ast;
|
||||||
|
use either::Either;
|
||||||
use hir::{HirDisplay, SemanticsScope};
|
use hir::{HirDisplay, SemanticsScope};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use syntax::{
|
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
|
// a default type. If they do, go for that type from `hir` to `ast` so
|
||||||
// the resulting change can be applied correctly.
|
// the resulting change can be applied correctly.
|
||||||
.zip(self.substs.iter().map(Some).chain(std::iter::repeat(None)))
|
.zip(self.substs.iter().map(Some).chain(std::iter::repeat(None)))
|
||||||
.filter_map(|(k, v)| match v {
|
.filter_map(|(k, v)| match k.split(db) {
|
||||||
Some(v) => Some((k, v.clone())),
|
Either::Left(_) => None,
|
||||||
None => {
|
Either::Right(t) => match v {
|
||||||
let default = k.default(db)?;
|
Some(v) => Some((k, v.clone())),
|
||||||
Some((
|
None => {
|
||||||
k,
|
let default = t.default(db)?;
|
||||||
ast::make::ty(&default.display_source_code(db, source_module.into()).ok()?),
|
Some((
|
||||||
))
|
k,
|
||||||
}
|
ast::make::ty(
|
||||||
|
&default.display_source_code(db, source_module.into()).ok()?,
|
||||||
|
),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
},
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let res = Ctx { substs: substs_by_param, target_module, source_scope: self.source_scope };
|
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> {
|
struct Ctx<'a> {
|
||||||
substs: FxHashMap<hir::TypeParam, ast::Type>,
|
substs: FxHashMap<hir::TypeOrConstParam, ast::Type>,
|
||||||
target_module: hir::Module,
|
target_module: hir::Module,
|
||||||
source_scope: &'a SemanticsScope<'a>,
|
source_scope: &'a SemanticsScope<'a>,
|
||||||
}
|
}
|
||||||
|
@ -150,7 +156,7 @@ impl<'a> Ctx<'a> {
|
||||||
|
|
||||||
match resolution {
|
match resolution {
|
||||||
hir::PathResolution::TypeParam(tp) => {
|
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()?;
|
let parent = path.syntax().parent()?;
|
||||||
if let Some(parent) = ast::Path::cast(parent.clone()) {
|
if let Some(parent) = ast::Path::cast(parent.clone()) {
|
||||||
// Path inside path means that there is an associated
|
// Path inside path means that there is an associated
|
||||||
|
|
|
@ -124,20 +124,23 @@ impl Definition {
|
||||||
src.with_value(name.syntax()).original_file_range_opt(sema.db)
|
src.with_value(name.syntax()).original_file_range_opt(sema.db)
|
||||||
}
|
}
|
||||||
Definition::GenericParam(generic_param) => match generic_param {
|
Definition::GenericParam(generic_param) => match generic_param {
|
||||||
hir::GenericParam::TypeParam(type_param) => {
|
hir::GenericParam::LifetimeParam(lifetime_param) => {
|
||||||
let src = type_param.source(sema.db)?;
|
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 {
|
let name = match &src.value {
|
||||||
Either::Left(type_param) => type_param.name()?,
|
Either::Left(x) => x.name()?,
|
||||||
Either::Right(_trait) => return None,
|
Either::Right(_) => return None,
|
||||||
};
|
};
|
||||||
src.with_value(name.syntax()).original_file_range_opt(sema.db)
|
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) => {
|
Definition::Label(label) => {
|
||||||
let src = label.source(sema.db);
|
let src = label.source(sema.db);
|
||||||
|
|
|
@ -22,7 +22,7 @@ pub use self::{
|
||||||
generated::{nodes::*, tokens::*},
|
generated::{nodes::*, tokens::*},
|
||||||
node_ext::{
|
node_ext::{
|
||||||
AttrKind, FieldKind, Macro, NameLike, NameOrNameRef, PathSegmentKind, SelfParamKind,
|
AttrKind, FieldKind, Macro, NameLike, NameOrNameRef, PathSegmentKind, SelfParamKind,
|
||||||
SlicePatComponents, StructKind, TypeBoundKind, VisibilityKind,
|
SlicePatComponents, StructKind, TypeBoundKind, TypeOrConstParam, VisibilityKind,
|
||||||
},
|
},
|
||||||
operators::{ArithOp, BinaryOp, CmpOp, LogicOp, Ordering, RangeOp, UnaryOp},
|
operators::{ArithOp, BinaryOp, CmpOp, LogicOp, Ordering, RangeOp, UnaryOp},
|
||||||
token_ext::{CommentKind, CommentPlacement, CommentShape, IsString, QuoteOffsets, Radix},
|
token_ext::{CommentKind, CommentPlacement, CommentShape, IsString, QuoteOffsets, Radix},
|
||||||
|
|
|
@ -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<ast::Name> {
|
||||||
|
match self {
|
||||||
|
TypeOrConstParam::Type(x) => x.name(),
|
||||||
|
TypeOrConstParam::Const(x) => x.name(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub enum VisibilityKind {
|
pub enum VisibilityKind {
|
||||||
In(ast::Path),
|
In(ast::Path),
|
||||||
PubCrate,
|
PubCrate,
|
||||||
|
@ -746,16 +761,11 @@ impl ast::GenericParamList {
|
||||||
ast::GenericParam::TypeParam(_) | ast::GenericParam::ConstParam(_) => None,
|
ast::GenericParam::TypeParam(_) | ast::GenericParam::ConstParam(_) => None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn type_params(&self) -> impl Iterator<Item = ast::TypeParam> {
|
pub fn type_or_const_params(&self) -> impl Iterator<Item = ast::TypeOrConstParam> {
|
||||||
self.generic_params().filter_map(|param| match param {
|
self.generic_params().filter_map(|param| match param {
|
||||||
ast::GenericParam::TypeParam(it) => Some(it),
|
ast::GenericParam::TypeParam(it) => Some(ast::TypeOrConstParam::Type(it)),
|
||||||
ast::GenericParam::LifetimeParam(_) | ast::GenericParam::ConstParam(_) => None,
|
ast::GenericParam::LifetimeParam(_) => None,
|
||||||
})
|
ast::GenericParam::ConstParam(it) => Some(ast::TypeOrConstParam::Const(it)),
|
||||||
}
|
|
||||||
pub fn const_params(&self) -> impl Iterator<Item = ast::ConstParam> {
|
|
||||||
self.generic_params().filter_map(|param| match param {
|
|
||||||
ast::GenericParam::ConstParam(it) => Some(it),
|
|
||||||
ast::GenericParam::TypeParam(_) | ast::GenericParam::LifetimeParam(_) => None,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue