mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
Merge #11140
11140: Preserve order of generic args r=HKalbasi a=HKalbasi https://github.com/rust-lang/rust/pull/90207 removed order restriction of generic args, i.e. const generics can now become before of type generics. We need to preserve this order to analyze correctly, and this PR does that. It also simplifies implementation of const generics a bit IMO. Implementing default generics the same problem of #7434, we need lower them to body and then evaluate them. Co-authored-by: hkalbasi <hamidrezakalbasi@protonmail.com>
This commit is contained in:
commit
f8329ba987
@ -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,10 +311,12 @@ 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 let Some(name) = &ty.name() {
|
||||||
|
match ty {
|
||||||
|
TypeOrConstParamData::TypeParamData(ty) => {
|
||||||
if ty.provenance != TypeParamProvenance::TypeParamList {
|
if ty.provenance != TypeParamProvenance::TypeParamList {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Some(name) = &ty.name {
|
|
||||||
delim(f)?;
|
delim(f)?;
|
||||||
write!(f, "{}", name)?;
|
write!(f, "{}", name)?;
|
||||||
if let Some(default) = &ty.default {
|
if let Some(default) = &ty.default {
|
||||||
@ -311,11 +324,13 @@ fn write_generic_params(def: GenericDefId, f: &mut HirFormatter) -> Result<(), H
|
|||||||
default.hir_fmt(f)?;
|
default.hir_fmt(f)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
TypeOrConstParamData::ConstParamData(c) => {
|
||||||
for (_, konst) in params.consts.iter() {
|
|
||||||
delim(f)?;
|
delim(f)?;
|
||||||
write!(f, "const {}: ", konst.name)?;
|
write!(f, "const {}: ", name)?;
|
||||||
konst.ty.hir_fmt(f)?;
|
c.ty.hir_fmt(f)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(f, ">")?;
|
write!(f, ">")?;
|
||||||
@ -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),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
Variant,
|
||||||
};
|
};
|
||||||
use base_db::CrateId;
|
use base_db::CrateId;
|
||||||
|
|
||||||
@ -609,7 +609,7 @@ 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) => PathResolution::TypeParam(id.into()),
|
||||||
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 +650,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 +703,7 @@ 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) => PathResolution::TypeParam(id.into()),
|
||||||
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,20 +225,33 @@ 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() {
|
||||||
|
match type_or_const_param {
|
||||||
|
ast::TypeOrConstParam::Type(type_param) => {
|
||||||
let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
|
let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
|
||||||
// FIXME: Use `Path::from_src`
|
// FIXME: Use `Path::from_src`
|
||||||
let default =
|
let default = type_param
|
||||||
type_param.default_type().map(|it| Interned::new(TypeRef::from_ast(lower_ctx, it)));
|
.default_type()
|
||||||
|
.map(|it| Interned::new(TypeRef::from_ast(lower_ctx, it)));
|
||||||
let param = TypeParamData {
|
let param = TypeParamData {
|
||||||
name: Some(name.clone()),
|
name: Some(name.clone()),
|
||||||
default,
|
default,
|
||||||
provenance: TypeParamProvenance::TypeParamList,
|
provenance: TypeParamProvenance::TypeParamList,
|
||||||
};
|
};
|
||||||
self.types.alloc(param);
|
self.types.alloc(param.into());
|
||||||
let type_ref = TypeRef::Path(name.into());
|
let type_ref = TypeRef::Path(name.into());
|
||||||
self.fill_bounds(lower_ctx, &type_param, Either::Left(type_ref));
|
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 =
|
||||||
lifetime_param.lifetime().map_or_else(Name::missing, |lt| Name::new_lifetime(<));
|
lifetime_param.lifetime().map_or_else(Name::missing, |lt| Name::new_lifetime(<));
|
||||||
@ -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,30 +359,36 @@ 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_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 })
|
.filter(|x| matches!(x.1, TypeOrConstParamData::TypeParamData(_)))
|
||||||
|
.find_map(|(id, p)| if p.name().as_ref() == Some(&name) { Some(id) } else { None })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_const_by_name(&self, name: &Name) -> Option<LocalConstParamId> {
|
pub fn find_type_or_const_by_name(&self, name: &Name) -> Option<LocalTypeOrConstParamId> {
|
||||||
self.consts.iter().find_map(|(id, p)| if p.name == *name { Some(id) } else { None })
|
self.types
|
||||||
|
.iter()
|
||||||
|
.find_map(|(id, p)| if p.name().as_ref() == Some(&name) { Some(id) } else { None })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_trait_self_param(&self) -> Option<LocalTypeParamId> {
|
pub fn find_trait_self_param(&self) -> Option<LocalTypeOrConstParamId> {
|
||||||
self.types.iter().find_map(|(id, p)| {
|
self.types.iter().find_map(|(id, p)| {
|
||||||
|
if let TypeOrConstParamData::TypeParamData(p) = p {
|
||||||
if p.provenance == TypeParamProvenance::TraitSelf {
|
if p.provenance == TypeParamProvenance::TraitSelf {
|
||||||
Some(id)
|
Some(id)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -377,12 +431,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 +452,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 +484,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 +492,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(
|
||||||
|
TypeParamData {
|
||||||
name: Some(name![Self]),
|
name: Some(name![Self]),
|
||||||
default: None,
|
default: None,
|
||||||
provenance: TypeParamProvenance::TraitSelf,
|
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 {
|
||||||
|
TypeOrConstParamData::TypeParamData(ty) => match &ty.name {
|
||||||
Some(name) => w!(self, "{}", name),
|
Some(name) => w!(self, "{}", name),
|
||||||
None => w!(self, "_anon_{}", idx.into_raw()),
|
None => w!(self, "_anon_{}", idx.into_raw()),
|
||||||
}
|
},
|
||||||
}
|
TypeOrConstParamData::ConstParamData(konst) => {
|
||||||
for (_, konst) in params.consts.iter() {
|
|
||||||
if !first {
|
|
||||||
w!(self, ", ");
|
|
||||||
}
|
|
||||||
first = false;
|
|
||||||
w!(self, "const {}: ", konst.name);
|
w!(self, "const {}: ", konst.name);
|
||||||
self.print_type_ref(&konst.ty);
|
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) => {
|
||||||
|
match ¶ms.types[*id].name() {
|
||||||
Some(name) => w!(this, "{}", name),
|
Some(name) => w!(this, "{}", name),
|
||||||
None => w!(this, "_anon_{}", id.into_raw()),
|
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, TypeParamId, VariantId,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
@ -195,7 +195,9 @@ impl Resolver {
|
|||||||
if let Some(local_id) = params.find_type_by_name(first_name) {
|
if let Some(local_id) = params.find_type_by_name(first_name) {
|
||||||
let idx = if path.segments().len() == 1 { None } else { Some(1) };
|
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,14 +527,21 @@ 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 };
|
||||||
|
@ -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,7 +238,8 @@ 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 {
|
||||||
|
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
|
||||||
hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
|
hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
|
||||||
let substs = TyBuilder::type_params_subst(db, id.parent);
|
let substs = TyBuilder::type_params_subst(db, id.parent);
|
||||||
let predicates = db
|
let predicates = db
|
||||||
@ -259,6 +261,8 @@ impl TyExt for Ty {
|
|||||||
Some(predicates)
|
Some(predicates)
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
},
|
||||||
|
_ => 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,9 +681,10 @@ 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 {
|
||||||
|
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
|
||||||
TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {
|
TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {
|
||||||
write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))?
|
write!(f, "{}", p.name.clone().unwrap_or_else(Name::missing))?
|
||||||
}
|
}
|
||||||
TypeParamProvenance::ArgumentImplTrait => {
|
TypeParamProvenance::ArgumentImplTrait => {
|
||||||
let substs = generics.type_params_subst(f.db);
|
let substs = generics.type_params_subst(f.db);
|
||||||
@ -711,6 +711,10 @@ impl HirDisplay for Ty {
|
|||||||
f,
|
f,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
TypeOrConstParamData::ConstParamData(p) => {
|
||||||
|
write!(f, "{}", p.name)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TyKind::BoundVar(idx) => idx.hir_fmt(f)?,
|
TyKind::BoundVar(idx) => idx.hir_fmt(f)?,
|
||||||
|
@ -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,9 +1038,16 @@ 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() {
|
||||||
|
match param {
|
||||||
|
TypeOrConstParamData::TypeParamData(_) => {
|
||||||
substs.push(self.table.new_type_var());
|
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 {
|
||||||
// if args are provided, it should be all of them, but we can't rely on that
|
// if args are provided, it should be all of them, but we can't rely on that
|
||||||
|
@ -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,
|
||||||
@ -370,7 +372,7 @@ impl<'a> TyLoweringContext<'a> {
|
|||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
match resolution {
|
match resolution {
|
||||||
TypeNs::GenericParam(param_id) => Some(param_id),
|
TypeNs::GenericParam(param_id) => Some(param_id.into()),
|
||||||
_ => None,
|
_ => 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(
|
||||||
@ -987,11 +991,9 @@ fn named_associated_type_shorthand_candidates<R>(
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
// 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,7 +85,8 @@ 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 {
|
||||||
|
ast::TypeOrConstParam::Type(type_param) => {
|
||||||
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());
|
||||||
@ -97,9 +98,10 @@ fn generate_trait_impl_text_from_impl(impl_: &ast::Impl, trait_text: &str, code:
|
|||||||
format_to!(buf, "{}", it.syntax());
|
format_to!(buf, "{}", it.syntax());
|
||||||
}
|
}
|
||||||
buf
|
buf
|
||||||
|
}
|
||||||
|
ast::TypeOrConstParam::Const(const_param) => const_param.syntax().to_string(),
|
||||||
});
|
});
|
||||||
let const_params = generic_params.const_params().map(|t| t.syntax().to_string());
|
let generics = lifetimes.chain(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) {
|
||||||
|
Either::Left(_) => None,
|
||||||
|
Either::Right(t) => match v {
|
||||||
Some(v) => Some((k, v.clone())),
|
Some(v) => Some((k, v.clone())),
|
||||||
None => {
|
None => {
|
||||||
let default = k.default(db)?;
|
let default = t.default(db)?;
|
||||||
Some((
|
Some((
|
||||||
k,
|
k,
|
||||||
ast::make::ty(&default.display_source_code(db, source_module.into()).ok()?),
|
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…
x
Reference in New Issue
Block a user