Auto merge of #17487 - Veykril:ty-perf-stuff, r=Veykril

internal: Some more small memory optimizations

Not a big impact on metrics, though there are some more savings in queries mainly used by the IDE layer from this
This commit is contained in:
bors 2024-06-24 09:50:35 +00:00
commit 0cb22db658
39 changed files with 340 additions and 260 deletions

1
Cargo.lock generated
View File

@ -1046,6 +1046,7 @@ checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5"
name = "mbe" name = "mbe"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"arrayvec",
"cov-mark", "cov-mark",
"parser", "parser",
"rustc-hash", "rustc-hash",

View File

@ -323,7 +323,7 @@ impl TraitAliasData {
pub struct ImplData { pub struct ImplData {
pub target_trait: Option<Interned<TraitRef>>, pub target_trait: Option<Interned<TraitRef>>,
pub self_ty: Interned<TypeRef>, pub self_ty: Interned<TypeRef>,
pub items: Vec<AssocItemId>, pub items: Box<[AssocItemId]>,
pub is_negative: bool, pub is_negative: bool,
pub is_unsafe: bool, pub is_unsafe: bool,
// box it as the vec is usually empty anyways // box it as the vec is usually empty anyways

View File

@ -80,9 +80,11 @@ pub trait InternDatabase: SourceDatabase {
#[salsa::query_group(DefDatabaseStorage)] #[salsa::query_group(DefDatabaseStorage)]
pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDatabase> { pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDatabase> {
/// Whether to expand procedural macros during name resolution.
#[salsa::input] #[salsa::input]
fn expand_proc_attr_macros(&self) -> bool; fn expand_proc_attr_macros(&self) -> bool;
/// Computes an [`ItemTree`] for the given file or macro expansion.
#[salsa::invoke(ItemTree::file_item_tree_query)] #[salsa::invoke(ItemTree::file_item_tree_query)]
fn file_item_tree(&self, file_id: HirFileId) -> Arc<ItemTree>; fn file_item_tree(&self, file_id: HirFileId) -> Arc<ItemTree>;
@ -96,6 +98,7 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
#[salsa::invoke(DefMap::block_def_map_query)] #[salsa::invoke(DefMap::block_def_map_query)]
fn block_def_map(&self, block: BlockId) -> Arc<DefMap>; fn block_def_map(&self, block: BlockId) -> Arc<DefMap>;
/// Turns a MacroId into a MacroDefId, describing the macro's definition post name resolution.
fn macro_def(&self, m: MacroId) -> MacroDefId; fn macro_def(&self, m: MacroId) -> MacroDefId;
// region:data // region:data
@ -190,6 +193,7 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
#[salsa::invoke(Attrs::fields_attrs_query)] #[salsa::invoke(Attrs::fields_attrs_query)]
fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>; fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>;
// should this really be a query?
#[salsa::invoke(crate::attr::fields_attrs_source_map)] #[salsa::invoke(crate::attr::fields_attrs_source_map)]
fn fields_attrs_source_map( fn fields_attrs_source_map(
&self, &self,

View File

@ -582,13 +582,11 @@ impl GenericParams {
GenericDefId::TraitAliasId(id) => id_to_generics(db, id, enabled_params), GenericDefId::TraitAliasId(id) => id_to_generics(db, id, enabled_params),
GenericDefId::TypeAliasId(id) => id_to_generics(db, id, enabled_params), GenericDefId::TypeAliasId(id) => id_to_generics(db, id, enabled_params),
GenericDefId::ImplId(id) => id_to_generics(db, id, enabled_params), GenericDefId::ImplId(id) => id_to_generics(db, id, enabled_params),
GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => { GenericDefId::ConstId(_) => Interned::new(GenericParams {
Interned::new(GenericParams {
type_or_consts: Default::default(), type_or_consts: Default::default(),
lifetimes: Default::default(), lifetimes: Default::default(),
where_predicates: Default::default(), where_predicates: Default::default(),
}) }),
}
} }
} }

View File

@ -48,6 +48,7 @@ use either::Either;
use hir_expand::{attrs::RawAttrs, name::Name, ExpandTo, HirFileId, InFile}; use hir_expand::{attrs::RawAttrs, name::Name, ExpandTo, HirFileId, InFile};
use intern::Interned; use intern::Interned;
use la_arena::{Arena, Idx, IdxRange, RawIdx}; use la_arena::{Arena, Idx, IdxRange, RawIdx};
use once_cell::sync::OnceCell;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use smallvec::SmallVec; use smallvec::SmallVec;
use span::{AstIdNode, FileAstId, SyntaxContextId}; use span::{AstIdNode, FileAstId, SyntaxContextId};
@ -100,6 +101,7 @@ pub struct ItemTree {
impl ItemTree { impl ItemTree {
pub(crate) fn file_item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> { pub(crate) fn file_item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> {
let _p = tracing::info_span!("file_item_tree_query", ?file_id).entered(); let _p = tracing::info_span!("file_item_tree_query", ?file_id).entered();
static EMPTY: OnceCell<Arc<ItemTree>> = OnceCell::new();
let syntax = db.parse_or_expand(file_id); let syntax = db.parse_or_expand(file_id);
@ -131,19 +133,48 @@ impl ItemTree {
if let Some(attrs) = top_attrs { if let Some(attrs) = top_attrs {
item_tree.attrs.insert(AttrOwner::TopLevel, attrs); item_tree.attrs.insert(AttrOwner::TopLevel, attrs);
} }
if item_tree.data.is_none() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty()
{
EMPTY
.get_or_init(|| {
Arc::new(ItemTree {
top_level: SmallVec::new_const(),
attrs: FxHashMap::default(),
data: None,
})
})
.clone()
} else {
item_tree.shrink_to_fit(); item_tree.shrink_to_fit();
Arc::new(item_tree) Arc::new(item_tree)
} }
}
pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc<ItemTree> { pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc<ItemTree> {
let _p = tracing::info_span!("block_item_tree_query", ?block).entered();
static EMPTY: OnceCell<Arc<ItemTree>> = OnceCell::new();
let loc = block.lookup(db); let loc = block.lookup(db);
let block = loc.ast_id.to_node(db.upcast()); let block = loc.ast_id.to_node(db.upcast());
let ctx = lower::Ctx::new(db, loc.ast_id.file_id); let ctx = lower::Ctx::new(db, loc.ast_id.file_id);
let mut item_tree = ctx.lower_block(&block); let mut item_tree = ctx.lower_block(&block);
if item_tree.data.is_none() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty()
{
EMPTY
.get_or_init(|| {
Arc::new(ItemTree {
top_level: SmallVec::new_const(),
attrs: FxHashMap::default(),
data: None,
})
})
.clone()
} else {
item_tree.shrink_to_fit(); item_tree.shrink_to_fit();
Arc::new(item_tree) Arc::new(item_tree)
} }
}
/// Returns an iterator over all items located at the top level of the `HirFileId` this /// Returns an iterator over all items located at the top level of the `HirFileId` this
/// `ItemTree` was created from. /// `ItemTree` was created from.
@ -585,24 +616,30 @@ impl Index<RawVisibilityId> for ItemTree {
type Output = RawVisibility; type Output = RawVisibility;
fn index(&self, index: RawVisibilityId) -> &Self::Output { fn index(&self, index: RawVisibilityId) -> &Self::Output {
static VIS_PUB: RawVisibility = RawVisibility::Public; static VIS_PUB: RawVisibility = RawVisibility::Public;
static VIS_PRIV_IMPLICIT: RawVisibility = RawVisibility::Module( static VIS_PRIV_IMPLICIT: OnceCell<RawVisibility> = OnceCell::new();
ModPath::from_kind(PathKind::SELF), static VIS_PRIV_EXPLICIT: OnceCell<RawVisibility> = OnceCell::new();
VisibilityExplicitness::Implicit, static VIS_PUB_CRATE: OnceCell<RawVisibility> = OnceCell::new();
);
static VIS_PRIV_EXPLICIT: RawVisibility = RawVisibility::Module(
ModPath::from_kind(PathKind::SELF),
VisibilityExplicitness::Explicit,
);
static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module(
ModPath::from_kind(PathKind::Crate),
VisibilityExplicitness::Explicit,
);
match index { match index {
RawVisibilityId::PRIV_IMPLICIT => &VIS_PRIV_IMPLICIT, RawVisibilityId::PRIV_IMPLICIT => VIS_PRIV_IMPLICIT.get_or_init(|| {
RawVisibilityId::PRIV_EXPLICIT => &VIS_PRIV_EXPLICIT, RawVisibility::Module(
Interned::new(ModPath::from_kind(PathKind::SELF)),
VisibilityExplicitness::Implicit,
)
}),
RawVisibilityId::PRIV_EXPLICIT => VIS_PRIV_EXPLICIT.get_or_init(|| {
RawVisibility::Module(
Interned::new(ModPath::from_kind(PathKind::SELF)),
VisibilityExplicitness::Explicit,
)
}),
RawVisibilityId::PUB => &VIS_PUB, RawVisibilityId::PUB => &VIS_PUB,
RawVisibilityId::PUB_CRATE => &VIS_PUB_CRATE, RawVisibilityId::PUB_CRATE => VIS_PUB_CRATE.get_or_init(|| {
RawVisibility::Module(
Interned::new(ModPath::from_kind(PathKind::Crate)),
VisibilityExplicitness::Explicit,
)
}),
_ => &self.data().vis.arena[Idx::from_raw(index.0.into())], _ => &self.data().vis.arena[Idx::from_raw(index.0.into())],
} }
} }

View File

@ -689,7 +689,7 @@ pub enum TypeOwnerId {
} }
impl TypeOwnerId { impl TypeOwnerId {
fn as_generic_def_id(self) -> Option<GenericDefId> { fn as_generic_def_id(self, db: &dyn DefDatabase) -> Option<GenericDefId> {
Some(match self { Some(match self {
TypeOwnerId::FunctionId(it) => GenericDefId::FunctionId(it), TypeOwnerId::FunctionId(it) => GenericDefId::FunctionId(it),
TypeOwnerId::ConstId(it) => GenericDefId::ConstId(it), TypeOwnerId::ConstId(it) => GenericDefId::ConstId(it),
@ -698,7 +698,9 @@ impl TypeOwnerId {
TypeOwnerId::TraitAliasId(it) => GenericDefId::TraitAliasId(it), TypeOwnerId::TraitAliasId(it) => GenericDefId::TraitAliasId(it),
TypeOwnerId::TypeAliasId(it) => GenericDefId::TypeAliasId(it), TypeOwnerId::TypeAliasId(it) => GenericDefId::TypeAliasId(it),
TypeOwnerId::ImplId(it) => GenericDefId::ImplId(it), TypeOwnerId::ImplId(it) => GenericDefId::ImplId(it),
TypeOwnerId::EnumVariantId(it) => GenericDefId::EnumVariantId(it), TypeOwnerId::EnumVariantId(it) => {
GenericDefId::AdtId(AdtId::EnumId(it.lookup(db).parent))
}
TypeOwnerId::InTypeConstId(_) | TypeOwnerId::StaticId(_) => return None, TypeOwnerId::InTypeConstId(_) | TypeOwnerId::StaticId(_) => return None,
}) })
} }
@ -740,7 +742,6 @@ impl From<GenericDefId> for TypeOwnerId {
GenericDefId::TraitAliasId(it) => it.into(), GenericDefId::TraitAliasId(it) => it.into(),
GenericDefId::TypeAliasId(it) => it.into(), GenericDefId::TypeAliasId(it) => it.into(),
GenericDefId::ImplId(it) => it.into(), GenericDefId::ImplId(it) => it.into(),
GenericDefId::EnumVariantId(it) => it.into(),
GenericDefId::ConstId(it) => it.into(), GenericDefId::ConstId(it) => it.into(),
} }
} }
@ -849,8 +850,8 @@ impl GeneralConstId {
pub fn generic_def(self, db: &dyn DefDatabase) -> Option<GenericDefId> { pub fn generic_def(self, db: &dyn DefDatabase) -> Option<GenericDefId> {
match self { match self {
GeneralConstId::ConstId(it) => Some(it.into()), GeneralConstId::ConstId(it) => Some(it.into()),
GeneralConstId::ConstBlockId(it) => it.lookup(db).parent.as_generic_def_id(), GeneralConstId::ConstBlockId(it) => it.lookup(db).parent.as_generic_def_id(db),
GeneralConstId::InTypeConstId(it) => it.lookup(db).owner.as_generic_def_id(), GeneralConstId::InTypeConstId(it) => it.lookup(db).owner.as_generic_def_id(db),
} }
} }
@ -888,12 +889,12 @@ impl From<EnumVariantId> for DefWithBodyId {
} }
impl DefWithBodyId { impl DefWithBodyId {
pub fn as_generic_def_id(self) -> Option<GenericDefId> { pub fn as_generic_def_id(self, db: &dyn DefDatabase) -> Option<GenericDefId> {
match self { match self {
DefWithBodyId::FunctionId(f) => Some(f.into()), DefWithBodyId::FunctionId(f) => Some(f.into()),
DefWithBodyId::StaticId(_) => None, DefWithBodyId::StaticId(_) => None,
DefWithBodyId::ConstId(c) => Some(c.into()), DefWithBodyId::ConstId(c) => Some(c.into()),
DefWithBodyId::VariantId(c) => Some(c.into()), DefWithBodyId::VariantId(c) => Some(c.lookup(db).parent.into()),
// FIXME: stable rust doesn't allow generics in constants, but we should // FIXME: stable rust doesn't allow generics in constants, but we should
// use `TypeOwnerId::as_generic_def_id` when it does. // use `TypeOwnerId::as_generic_def_id` when it does.
DefWithBodyId::InTypeConstId(_) => None, DefWithBodyId::InTypeConstId(_) => None,
@ -921,10 +922,6 @@ pub enum GenericDefId {
TraitAliasId(TraitAliasId), TraitAliasId(TraitAliasId),
TypeAliasId(TypeAliasId), TypeAliasId(TypeAliasId),
ImplId(ImplId), ImplId(ImplId),
// enum variants cannot have generics themselves, but their parent enums
// can, and this makes some code easier to write
// FIXME: Try to remove this as that will reduce the amount of query slots generated per enum?
EnumVariantId(EnumVariantId),
// consts can have type parameters from their parents (i.e. associated consts of traits) // consts can have type parameters from their parents (i.e. associated consts of traits)
ConstId(ConstId), ConstId(ConstId),
} }
@ -935,7 +932,6 @@ impl_from!(
TraitAliasId, TraitAliasId,
TypeAliasId, TypeAliasId,
ImplId, ImplId,
EnumVariantId,
ConstId ConstId
for GenericDefId for GenericDefId
); );
@ -967,7 +963,6 @@ impl GenericDefId {
GenericDefId::TraitAliasId(it) => file_id_and_params_of_item_loc(db, it), GenericDefId::TraitAliasId(it) => file_id_and_params_of_item_loc(db, it),
GenericDefId::ImplId(it) => file_id_and_params_of_item_loc(db, it), GenericDefId::ImplId(it) => file_id_and_params_of_item_loc(db, it),
GenericDefId::ConstId(it) => (it.lookup(db).id.file_id(), None), GenericDefId::ConstId(it) => (it.lookup(db).id.file_id(), None),
GenericDefId::EnumVariantId(it) => (it.lookup(db).id.file_id(), None),
} }
} }
@ -982,6 +977,14 @@ impl GenericDefId {
_ => None, _ => None,
} }
} }
pub fn from_callable(db: &dyn DefDatabase, def: CallableDefId) -> GenericDefId {
match def {
CallableDefId::FunctionId(f) => f.into(),
CallableDefId::StructId(s) => s.into(),
CallableDefId::EnumVariantId(e) => e.lookup(db).parent.into(),
}
}
} }
impl From<AssocItemId> for GenericDefId { impl From<AssocItemId> for GenericDefId {
@ -994,6 +997,36 @@ impl From<AssocItemId> for GenericDefId {
} }
} }
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum CallableDefId {
FunctionId(FunctionId),
StructId(StructId),
EnumVariantId(EnumVariantId),
}
impl InternValueTrivial for CallableDefId {}
impl_from!(FunctionId, StructId, EnumVariantId for CallableDefId);
impl From<CallableDefId> for ModuleDefId {
fn from(def: CallableDefId) -> ModuleDefId {
match def {
CallableDefId::FunctionId(f) => ModuleDefId::FunctionId(f),
CallableDefId::StructId(s) => ModuleDefId::AdtId(AdtId::StructId(s)),
CallableDefId::EnumVariantId(e) => ModuleDefId::EnumVariantId(e),
}
}
}
impl CallableDefId {
pub fn krate(self, db: &dyn DefDatabase) -> CrateId {
match self {
CallableDefId::FunctionId(f) => f.krate(db),
CallableDefId::StructId(s) => s.krate(db),
CallableDefId::EnumVariantId(e) => e.krate(db),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum AttrDefId { pub enum AttrDefId {
ModuleId(ModuleId), ModuleId(ModuleId),
@ -1310,7 +1343,6 @@ impl HasModule for GenericDefId {
GenericDefId::TraitAliasId(it) => it.module(db), GenericDefId::TraitAliasId(it) => it.module(db),
GenericDefId::TypeAliasId(it) => it.module(db), GenericDefId::TypeAliasId(it) => it.module(db),
GenericDefId::ImplId(it) => it.module(db), GenericDefId::ImplId(it) => it.module(db),
GenericDefId::EnumVariantId(it) => it.module(db),
GenericDefId::ConstId(it) => it.module(db), GenericDefId::ConstId(it) => it.module(db),
} }
} }

View File

@ -103,12 +103,13 @@ const PREDEFINED_TOOLS: &[SmolStr] = &[
/// is computed by the `block_def_map` query. /// is computed by the `block_def_map` query.
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct DefMap { pub struct DefMap {
/// The crate this `DefMap` belongs to.
krate: CrateId,
/// When this is a block def map, this will hold the block id of the block and module that /// When this is a block def map, this will hold the block id of the block and module that
/// contains this block. /// contains this block.
block: Option<BlockInfo>, block: Option<BlockInfo>,
/// The modules and their data declared in this crate. /// The modules and their data declared in this crate.
pub modules: Arena<ModuleData>, pub modules: Arena<ModuleData>,
krate: CrateId,
/// The prelude module for this crate. This either comes from an import /// The prelude module for this crate. This either comes from an import
/// marked with the `prelude_import` attribute, or (in the normal case) from /// marked with the `prelude_import` attribute, or (in the normal case) from
/// a dependency (`std` or `core`). /// a dependency (`std` or `core`).
@ -124,6 +125,7 @@ pub struct DefMap {
/// Tracks which custom derives are in scope for an item, to allow resolution of derive helper /// Tracks which custom derives are in scope for an item, to allow resolution of derive helper
/// attributes. /// attributes.
// FIXME: Figure out a better way for the IDE layer to resolve these?
derive_helpers_in_scope: FxHashMap<AstId<ast::Item>, Vec<(Name, MacroId, MacroCallId)>>, derive_helpers_in_scope: FxHashMap<AstId<ast::Item>, Vec<(Name, MacroId, MacroCallId)>>,
/// The diagnostics that need to be emitted for this crate. /// The diagnostics that need to be emitted for this crate.

View File

@ -1164,7 +1164,6 @@ impl HasResolver for GenericDefId {
GenericDefId::TraitAliasId(inner) => inner.resolver(db), GenericDefId::TraitAliasId(inner) => inner.resolver(db),
GenericDefId::TypeAliasId(inner) => inner.resolver(db), GenericDefId::TypeAliasId(inner) => inner.resolver(db),
GenericDefId::ImplId(inner) => inner.resolver(db), GenericDefId::ImplId(inner) => inner.resolver(db),
GenericDefId::EnumVariantId(inner) => inner.resolver(db),
GenericDefId::ConstId(inner) => inner.resolver(db), GenericDefId::ConstId(inner) => inner.resolver(db),
} }
} }

View File

@ -2,6 +2,7 @@
use std::iter; use std::iter;
use intern::Interned;
use la_arena::ArenaMap; use la_arena::ArenaMap;
use span::SyntaxContextId; use span::SyntaxContextId;
use syntax::ast; use syntax::ast;
@ -20,14 +21,17 @@ use crate::{
pub enum RawVisibility { pub enum RawVisibility {
/// `pub(in module)`, `pub(crate)` or `pub(super)`. Also private, which is /// `pub(in module)`, `pub(crate)` or `pub(super)`. Also private, which is
/// equivalent to `pub(self)`. /// equivalent to `pub(self)`.
Module(ModPath, VisibilityExplicitness), Module(Interned<ModPath>, VisibilityExplicitness),
/// `pub`. /// `pub`.
Public, Public,
} }
impl RawVisibility { impl RawVisibility {
pub(crate) const fn private() -> RawVisibility { pub(crate) fn private() -> RawVisibility {
RawVisibility::Module(ModPath::from_kind(PathKind::SELF), VisibilityExplicitness::Implicit) RawVisibility::Module(
Interned::new(ModPath::from_kind(PathKind::SELF)),
VisibilityExplicitness::Implicit,
)
} }
pub(crate) fn from_ast( pub(crate) fn from_ast(
@ -60,7 +64,7 @@ impl RawVisibility {
ast::VisibilityKind::PubSelf => ModPath::from_kind(PathKind::SELF), ast::VisibilityKind::PubSelf => ModPath::from_kind(PathKind::SELF),
ast::VisibilityKind::Pub => return RawVisibility::Public, ast::VisibilityKind::Pub => return RawVisibility::Public,
}; };
RawVisibility::Module(path, VisibilityExplicitness::Explicit) RawVisibility::Module(Interned::new(path), VisibilityExplicitness::Explicit)
} }
pub fn resolve( pub fn resolve(

View File

@ -25,7 +25,8 @@ impl ChangeWithProcMacros {
pub fn apply(self, db: &mut (impl ExpandDatabase + SourceDatabaseExt)) { pub fn apply(self, db: &mut (impl ExpandDatabase + SourceDatabaseExt)) {
self.source_change.apply(db); self.source_change.apply(db);
if let Some(proc_macros) = self.proc_macros { if let Some(mut proc_macros) = self.proc_macros {
proc_macros.shrink_to_fit();
db.set_proc_macros_with_durability(Arc::new(proc_macros), Durability::HIGH); db.set_proc_macros_with_durability(Arc::new(proc_macros), Durability::HIGH);
} }
if let Some(target_data_layouts) = self.target_data_layouts { if let Some(target_data_layouts) = self.target_data_layouts {

View File

@ -252,8 +252,9 @@ impl TyBuilder<()> {
/// This method prepopulates the builder with placeholder substitution of `parent`, so you /// This method prepopulates the builder with placeholder substitution of `parent`, so you
/// should only push exactly 3 `GenericArg`s before building. /// should only push exactly 3 `GenericArg`s before building.
pub fn subst_for_coroutine(db: &dyn HirDatabase, parent: DefWithBodyId) -> TyBuilder<()> { pub fn subst_for_coroutine(db: &dyn HirDatabase, parent: DefWithBodyId) -> TyBuilder<()> {
let parent_subst = let parent_subst = parent
parent.as_generic_def_id().map(|p| generics(db.upcast(), p).placeholder_subst(db)); .as_generic_def_id(db.upcast())
.map(|p| generics(db.upcast(), p).placeholder_subst(db));
// These represent resume type, yield type, and return type of coroutine. // These represent resume type, yield type, and return type of coroutine.
let params = std::iter::repeat(ParamKind::Type).take(3).collect(); let params = std::iter::repeat(ParamKind::Type).take(3).collect();
TyBuilder::new((), params, parent_subst) TyBuilder::new((), params, parent_subst)
@ -266,7 +267,7 @@ impl TyBuilder<()> {
) -> Substitution { ) -> Substitution {
let sig_ty = sig_ty.cast(Interner); let sig_ty = sig_ty.cast(Interner);
let self_subst = iter::once(&sig_ty); let self_subst = iter::once(&sig_ty);
let Some(parent) = parent.as_generic_def_id() else { let Some(parent) = parent.as_generic_def_id(db.upcast()) else {
return Substitution::from_iter(Interner, self_subst); return Substitution::from_iter(Interner, self_subst);
}; };
Substitution::from_iter( Substitution::from_iter(

View File

@ -13,7 +13,8 @@ use hir_def::{
data::adt::StructFlags, data::adt::StructFlags,
hir::Movability, hir::Movability,
lang_item::{LangItem, LangItemTarget}, lang_item::{LangItem, LangItemTarget},
AssocItemId, BlockId, GenericDefId, HasModule, ItemContainerId, Lookup, TypeAliasId, VariantId, AssocItemId, BlockId, CallableDefId, GenericDefId, HasModule, ItemContainerId, Lookup,
TypeAliasId, VariantId,
}; };
use hir_expand::name::name; use hir_expand::name::name;
@ -28,9 +29,9 @@ use crate::{
to_assoc_type_id, to_chalk_trait_id, to_assoc_type_id, to_chalk_trait_id,
traits::ChalkContext, traits::ChalkContext,
utils::ClosureSubst, utils::ClosureSubst,
wrap_empty_binders, AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, wrap_empty_binders, AliasEq, AliasTy, BoundVar, DebruijnIndex, FnDefId, Interner, ProjectionTy,
Interner, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, Substitution, TraitRef, ProjectionTyExt, QuantifiedWhereClause, Substitution, TraitRef, TraitRefExt, Ty, TyBuilder,
TraitRefExt, Ty, TyBuilder, TyExt, TyKind, WhereClause, TyExt, TyKind, WhereClause,
}; };
pub(crate) type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>; pub(crate) type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>;
@ -102,7 +103,7 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
&self, &self,
fn_def_id: chalk_ir::FnDefId<Interner>, fn_def_id: chalk_ir::FnDefId<Interner>,
) -> Arc<rust_ir::FnDefDatum<Interner>> { ) -> Arc<rust_ir::FnDefDatum<Interner>> {
self.db.fn_def_datum(self.krate, fn_def_id) self.db.fn_def_datum(fn_def_id)
} }
fn impls_for_trait( fn impls_for_trait(
@ -912,16 +913,13 @@ fn type_alias_associated_ty_value(
Arc::new(value) Arc::new(value)
} }
pub(crate) fn fn_def_datum_query( pub(crate) fn fn_def_datum_query(db: &dyn HirDatabase, fn_def_id: FnDefId) -> Arc<FnDefDatum> {
db: &dyn HirDatabase,
_krate: CrateId,
fn_def_id: FnDefId,
) -> Arc<FnDefDatum> {
let callable_def: CallableDefId = from_chalk(db, fn_def_id); let callable_def: CallableDefId = from_chalk(db, fn_def_id);
let generic_params = generics(db.upcast(), callable_def.into()); let generic_def = GenericDefId::from_callable(db.upcast(), callable_def);
let generic_params = generics(db.upcast(), generic_def);
let (sig, binders) = db.callable_item_signature(callable_def).into_value_and_skipped_binders(); let (sig, binders) = db.callable_item_signature(callable_def).into_value_and_skipped_binders();
let bound_vars = generic_params.bound_vars_subst(db, DebruijnIndex::INNERMOST); let bound_vars = generic_params.bound_vars_subst(db, DebruijnIndex::INNERMOST);
let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars); let where_clauses = convert_where_clauses(db, generic_def, &bound_vars);
let bound = rust_ir::FnDefDatumBound { let bound = rust_ir::FnDefDatumBound {
// Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway // Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway
inputs_and_output: chalk_ir::Binders::empty( inputs_and_output: chalk_ir::Binders::empty(
@ -948,7 +946,8 @@ pub(crate) fn fn_def_datum_query(
pub(crate) fn fn_def_variance_query(db: &dyn HirDatabase, fn_def_id: FnDefId) -> Variances { pub(crate) fn fn_def_variance_query(db: &dyn HirDatabase, fn_def_id: FnDefId) -> Variances {
let callable_def: CallableDefId = from_chalk(db, fn_def_id); let callable_def: CallableDefId = from_chalk(db, fn_def_id);
let generic_params = generics(db.upcast(), callable_def.into()); let generic_params =
generics(db.upcast(), GenericDefId::from_callable(db.upcast(), callable_def));
Variances::from_iter( Variances::from_iter(
Interner, Interner,
std::iter::repeat(chalk_ir::Variance::Invariant).take(generic_params.len()), std::iter::repeat(chalk_ir::Variance::Invariant).take(generic_params.len()),

View File

@ -188,9 +188,10 @@ impl TyExt for Ty {
fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId> { fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId> {
match *self.kind(Interner) { match *self.kind(Interner) {
TyKind::Adt(AdtId(adt), ..) => Some(adt.into()), TyKind::Adt(AdtId(adt), ..) => Some(adt.into()),
TyKind::FnDef(callable, ..) => { TyKind::FnDef(callable, ..) => Some(GenericDefId::from_callable(
Some(db.lookup_intern_callable_def(callable.into()).into()) db.upcast(),
} db.lookup_intern_callable_def(callable.into()),
)),
TyKind::AssociatedType(type_alias, ..) => Some(from_assoc_type_id(type_alias).into()), TyKind::AssociatedType(type_alias, ..) => Some(from_assoc_type_id(type_alias).into()),
TyKind::Foreign(type_alias, ..) => Some(from_foreign_def_id(type_alias).into()), TyKind::Foreign(type_alias, ..) => Some(from_foreign_def_id(type_alias).into()),
_ => None, _ => None,

View File

@ -9,8 +9,8 @@ use base_db::{
CrateId, Upcast, CrateId, Upcast,
}; };
use hir_def::{ use hir_def::{
db::DefDatabase, hir::ExprId, layout::TargetDataLayout, AdtId, BlockId, ConstParamId, db::DefDatabase, hir::ExprId, layout::TargetDataLayout, AdtId, BlockId, CallableDefId,
DefWithBodyId, EnumVariantId, FunctionId, GeneralConstId, GenericDefId, ImplId, ConstParamId, DefWithBodyId, EnumVariantId, FunctionId, GeneralConstId, GenericDefId, ImplId,
LifetimeParamId, LocalFieldId, StaticId, TypeAliasId, TypeOrConstParamId, VariantId, LifetimeParamId, LocalFieldId, StaticId, TypeAliasId, TypeOrConstParamId, VariantId,
}; };
use la_arena::ArenaMap; use la_arena::ArenaMap;
@ -24,9 +24,8 @@ use crate::{
lower::{GenericDefaults, GenericPredicates}, lower::{GenericDefaults, GenericPredicates},
method_resolution::{InherentImpls, TraitImpls, TyFingerprint}, method_resolution::{InherentImpls, TraitImpls, TyFingerprint},
mir::{BorrowckResult, MirBody, MirLowerError}, mir::{BorrowckResult, MirBody, MirLowerError},
Binders, CallableDefId, ClosureId, Const, FnDefId, ImplTraitId, ImplTraits, InferenceResult, Binders, ClosureId, Const, FnDefId, ImplTraitId, ImplTraits, InferenceResult, Interner,
Interner, PolyFnSig, QuantifiedWhereClause, Substitution, TraitEnvironment, TraitRef, Ty, PolyFnSig, Substitution, TraitEnvironment, TraitRef, Ty, TyDefId, ValueTyDefId,
TyDefId, ValueTyDefId,
}; };
use hir_expand::name::Name; use hir_expand::name::Name;
@ -81,8 +80,32 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
#[salsa::cycle(crate::consteval::const_eval_discriminant_recover)] #[salsa::cycle(crate::consteval::const_eval_discriminant_recover)]
fn const_eval_discriminant(&self, def: EnumVariantId) -> Result<i128, ConstEvalError>; fn const_eval_discriminant(&self, def: EnumVariantId) -> Result<i128, ConstEvalError>;
#[salsa::invoke(crate::method_resolution::lookup_impl_method_query)]
fn lookup_impl_method(
&self,
env: Arc<TraitEnvironment>,
func: FunctionId,
fn_subst: Substitution,
) -> (FunctionId, Substitution);
// endregion:mir // endregion:mir
#[salsa::invoke(crate::layout::layout_of_adt_query)]
#[salsa::cycle(crate::layout::layout_of_adt_recover)]
fn layout_of_adt(
&self,
def: AdtId,
subst: Substitution,
env: Arc<TraitEnvironment>,
) -> Result<Arc<Layout>, LayoutError>;
#[salsa::invoke(crate::layout::layout_of_ty_query)]
#[salsa::cycle(crate::layout::layout_of_ty_recover)]
fn layout_of_ty(&self, ty: Ty, env: Arc<TraitEnvironment>) -> Result<Arc<Layout>, LayoutError>;
#[salsa::invoke(crate::layout::target_data_layout_query)]
fn target_data_layout(&self, krate: CrateId) -> Result<Arc<TargetDataLayout>, Arc<str>>;
#[salsa::invoke(crate::lower::ty_query)] #[salsa::invoke(crate::lower::ty_query)]
#[salsa::cycle(crate::lower::ty_recover)] #[salsa::cycle(crate::lower::ty_recover)]
fn ty(&self, def: TyDefId) -> Binders<Ty>; fn ty(&self, def: TyDefId) -> Binders<Ty>;
@ -105,30 +128,6 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
#[salsa::invoke(crate::lower::field_types_query)] #[salsa::invoke(crate::lower::field_types_query)]
fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalFieldId, Binders<Ty>>>; fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalFieldId, Binders<Ty>>>;
#[salsa::invoke(crate::layout::layout_of_adt_query)]
#[salsa::cycle(crate::layout::layout_of_adt_recover)]
fn layout_of_adt(
&self,
def: AdtId,
subst: Substitution,
env: Arc<TraitEnvironment>,
) -> Result<Arc<Layout>, LayoutError>;
#[salsa::invoke(crate::layout::layout_of_ty_query)]
#[salsa::cycle(crate::layout::layout_of_ty_recover)]
fn layout_of_ty(&self, ty: Ty, env: Arc<TraitEnvironment>) -> Result<Arc<Layout>, LayoutError>;
#[salsa::invoke(crate::layout::target_data_layout_query)]
fn target_data_layout(&self, krate: CrateId) -> Result<Arc<TargetDataLayout>, Arc<str>>;
#[salsa::invoke(crate::method_resolution::lookup_impl_method_query)]
fn lookup_impl_method(
&self,
env: Arc<TraitEnvironment>,
func: FunctionId,
fn_subst: Substitution,
) -> (FunctionId, Substitution);
#[salsa::invoke(crate::lower::callable_item_sig)] #[salsa::invoke(crate::lower::callable_item_sig)]
fn callable_item_signature(&self, def: CallableDefId) -> PolyFnSig; fn callable_item_signature(&self, def: CallableDefId) -> PolyFnSig;
@ -145,7 +144,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
def: GenericDefId, def: GenericDefId,
param_id: TypeOrConstParamId, param_id: TypeOrConstParamId,
assoc_name: Option<Name>, assoc_name: Option<Name>,
) -> Arc<[Binders<QuantifiedWhereClause>]>; ) -> GenericPredicates;
#[salsa::invoke(crate::lower::generic_predicates_query)] #[salsa::invoke(crate::lower::generic_predicates_query)]
fn generic_predicates(&self, def: GenericDefId) -> GenericPredicates; fn generic_predicates(&self, def: GenericDefId) -> GenericPredicates;
@ -232,7 +231,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
) -> sync::Arc<chalk_db::ImplDatum>; ) -> sync::Arc<chalk_db::ImplDatum>;
#[salsa::invoke(chalk_db::fn_def_datum_query)] #[salsa::invoke(chalk_db::fn_def_datum_query)]
fn fn_def_datum(&self, krate: CrateId, fn_def_id: FnDefId) -> sync::Arc<chalk_db::FnDefDatum>; fn fn_def_datum(&self, fn_def_id: FnDefId) -> sync::Arc<chalk_db::FnDefDatum>;
#[salsa::invoke(chalk_db::fn_def_variance_query)] #[salsa::invoke(chalk_db::fn_def_variance_query)]
fn fn_def_variance(&self, fn_def_id: FnDefId) -> chalk_db::Variances; fn fn_def_variance(&self, fn_def_id: FnDefId) -> chalk_db::Variances;

View File

@ -21,8 +21,8 @@ use hir_def::{
path::{Path, PathKind}, path::{Path, PathKind},
type_ref::{TraitBoundModifier, TypeBound, TypeRef}, type_ref::{TraitBoundModifier, TypeBound, TypeRef},
visibility::Visibility, visibility::Visibility,
HasModule, ImportPathConfig, ItemContainerId, LocalFieldId, Lookup, ModuleDefId, ModuleId, GenericDefId, HasModule, ImportPathConfig, ItemContainerId, LocalFieldId, Lookup, ModuleDefId,
TraitId, ModuleId, TraitId,
}; };
use hir_expand::name::Name; use hir_expand::name::Name;
use intern::{Internable, Interned}; use intern::{Internable, Interned};
@ -988,7 +988,8 @@ impl HirDisplay for Ty {
f.end_location_link(); f.end_location_link();
if parameters.len(Interner) > 0 { if parameters.len(Interner) > 0 {
let generics = generics(db.upcast(), def.into()); let generic_def_id = GenericDefId::from_callable(db.upcast(), def);
let generics = generics(db.upcast(), generic_def_id);
let (parent_len, self_param, type_, const_, impl_, lifetime) = let (parent_len, self_param, type_, const_, impl_, lifetime) =
generics.provenance_split(); generics.provenance_split();
let parameters = parameters.as_slice(Interner); let parameters = parameters.as_slice(Interner);
@ -1002,8 +1003,9 @@ impl HirDisplay for Ty {
debug_assert_eq!(parent_params.len(), parent_len); debug_assert_eq!(parent_params.len(), parent_len);
let parent_params = let parent_params =
generic_args_sans_defaults(f, Some(def.into()), parent_params); generic_args_sans_defaults(f, Some(generic_def_id), parent_params);
let fn_params = generic_args_sans_defaults(f, Some(def.into()), fn_params); let fn_params =
generic_args_sans_defaults(f, Some(generic_def_id), fn_params);
write!(f, "<")?; write!(f, "<")?;
hir_fmt_generic_arguments(f, parent_params, None)?; hir_fmt_generic_arguments(f, parent_params, None)?;

View File

@ -216,7 +216,6 @@ fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<Generic
GenericDefId::FunctionId(it) => it.lookup(db).container, GenericDefId::FunctionId(it) => it.lookup(db).container,
GenericDefId::TypeAliasId(it) => it.lookup(db).container, GenericDefId::TypeAliasId(it) => it.lookup(db).container,
GenericDefId::ConstId(it) => it.lookup(db).container, GenericDefId::ConstId(it) => it.lookup(db).container,
GenericDefId::EnumVariantId(it) => return Some(it.lookup(db).parent.into()),
GenericDefId::AdtId(_) GenericDefId::AdtId(_)
| GenericDefId::TraitId(_) | GenericDefId::TraitId(_)
| GenericDefId::ImplId(_) | GenericDefId::ImplId(_)

View File

@ -13,7 +13,7 @@ use hir_def::{
}, },
lang_item::{LangItem, LangItemTarget}, lang_item::{LangItem, LangItemTarget},
path::{GenericArgs, Path}, path::{GenericArgs, Path},
BlockId, FieldId, GenericParamId, ItemContainerId, Lookup, TupleFieldId, TupleId, BlockId, FieldId, GenericDefId, GenericParamId, ItemContainerId, Lookup, TupleFieldId, TupleId,
}; };
use hir_expand::name::{name, Name}; use hir_expand::name::{name, Name};
use stdx::always; use stdx::always;
@ -1895,7 +1895,8 @@ impl InferenceContext<'_> {
let callable_ty = self.resolve_ty_shallow(callable_ty); let callable_ty = self.resolve_ty_shallow(callable_ty);
if let TyKind::FnDef(fn_def, parameters) = callable_ty.kind(Interner) { if let TyKind::FnDef(fn_def, parameters) = callable_ty.kind(Interner) {
let def: CallableDefId = from_chalk(self.db, *fn_def); let def: CallableDefId = from_chalk(self.db, *fn_def);
let generic_predicates = self.db.generic_predicates(def.into()); let generic_predicates =
self.db.generic_predicates(GenericDefId::from_callable(self.db.upcast(), def));
for predicate in generic_predicates.iter() { for predicate in generic_predicates.iter() {
let (predicate, binders) = predicate let (predicate, binders) = predicate
.clone() .clone()

View File

@ -41,14 +41,7 @@ impl InferenceContext<'_> {
fn resolve_value_path(&mut self, path: &Path, id: ExprOrPatId) -> Option<ValuePathResolution> { fn resolve_value_path(&mut self, path: &Path, id: ExprOrPatId) -> Option<ValuePathResolution> {
let (value, self_subst) = self.resolve_value_path_inner(path, id)?; let (value, self_subst) = self.resolve_value_path_inner(path, id)?;
let value_def = match value { let value_def: ValueTyDefId = match value {
ValueNs::LocalBinding(pat) => match self.result.type_of_binding.get(pat) {
Some(ty) => return Some(ValuePathResolution::NonGeneric(ty.clone())),
None => {
never!("uninferred pattern?");
return None;
}
},
ValueNs::FunctionId(it) => it.into(), ValueNs::FunctionId(it) => it.into(),
ValueNs::ConstId(it) => it.into(), ValueNs::ConstId(it) => it.into(),
ValueNs::StaticId(it) => it.into(), ValueNs::StaticId(it) => it.into(),
@ -62,48 +55,79 @@ impl InferenceContext<'_> {
it.into() it.into()
} }
ValueNs::LocalBinding(pat) => {
return match self.result.type_of_binding.get(pat) {
Some(ty) => Some(ValuePathResolution::NonGeneric(ty.clone())),
None => {
never!("uninferred pattern?");
None
}
}
}
ValueNs::ImplSelf(impl_id) => { ValueNs::ImplSelf(impl_id) => {
let generics = crate::generics::generics(self.db.upcast(), impl_id.into()); let generics = crate::generics::generics(self.db.upcast(), impl_id.into());
let substs = generics.placeholder_subst(self.db); let substs = generics.placeholder_subst(self.db);
let ty = self.db.impl_self_ty(impl_id).substitute(Interner, &substs); let ty = self.db.impl_self_ty(impl_id).substitute(Interner, &substs);
if let Some((AdtId::StructId(struct_id), substs)) = ty.as_adt() { return if let Some((AdtId::StructId(struct_id), substs)) = ty.as_adt() {
return Some(ValuePathResolution::GenericDef( Some(ValuePathResolution::GenericDef(
struct_id.into(), struct_id.into(),
struct_id.into(), struct_id.into(),
substs.clone(), substs.clone(),
)); ))
} else { } else {
// FIXME: report error, invalid Self reference // FIXME: report error, invalid Self reference
return None; None
} };
} }
ValueNs::GenericParam(it) => { ValueNs::GenericParam(it) => {
return Some(ValuePathResolution::NonGeneric(self.db.const_param_ty(it))) return Some(ValuePathResolution::NonGeneric(self.db.const_param_ty(it)))
} }
}; };
let generic_def_id = value_def.to_generic_def_id(self.db);
let Some(generic_def) = generic_def_id else {
// `value_def` is the kind of item that can never be generic (i.e. statics, at least
// currently). We can just skip the binders to get its type.
let (ty, binders) = self.db.value_ty(value_def)?.into_value_and_skipped_binders();
stdx::always!(binders.is_empty(Interner), "non-empty binders for non-generic def",);
return Some(ValuePathResolution::NonGeneric(ty));
};
let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, self.owner.into()); let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, self.owner.into());
let substs = ctx.substs_from_path(path, value_def, true); let substs = ctx.substs_from_path(path, value_def, true);
let substs = substs.as_slice(Interner); let substs = substs.as_slice(Interner);
if let ValueNs::EnumVariantId(_) = value {
let mut it = self_subst
.as_ref()
.map_or(&[][..], |s| s.as_slice(Interner))
.iter()
.chain(substs)
.cloned();
let builder = TyBuilder::subst_for_def(self.db, generic_def, None);
let substs = builder
.fill(|x| {
it.next().unwrap_or_else(|| match x {
ParamKind::Type => {
self.result.standard_types.unknown.clone().cast(Interner)
}
ParamKind::Const(ty) => consteval::unknown_const_as_generic(ty.clone()),
ParamKind::Lifetime => error_lifetime().cast(Interner),
})
})
.build();
return Some(ValuePathResolution::GenericDef(value_def, generic_def, substs));
}
let parent_substs = self_subst.or_else(|| { let parent_substs = self_subst.or_else(|| {
let generics = generics(self.db.upcast(), value_def.to_generic_def_id()?); let generics = generics(self.db.upcast(), generic_def_id?);
let parent_params_len = generics.parent_generics()?.len(); let parent_params_len = generics.parent_generics()?.len();
let parent_args = &substs[substs.len() - parent_params_len..]; let parent_args = &substs[substs.len() - parent_params_len..];
Some(Substitution::from_iter(Interner, parent_args)) Some(Substitution::from_iter(Interner, parent_args))
}); });
let parent_substs_len = parent_substs.as_ref().map_or(0, |s| s.len(Interner)); let parent_substs_len = parent_substs.as_ref().map_or(0, |s| s.len(Interner));
let mut it = substs.iter().take(substs.len() - parent_substs_len).cloned(); let mut it = substs.iter().take(substs.len() - parent_substs_len).cloned();
let Some(generic_def) = value_def.to_generic_def_id() else {
// `value_def` is the kind of item that can never be generic (i.e. statics, at least
// currently). We can just skip the binders to get its type.
let (ty, binders) = self.db.value_ty(value_def)?.into_value_and_skipped_binders();
stdx::always!(
parent_substs.is_none() && binders.is_empty(Interner),
"non-empty binders for non-generic def",
);
return Some(ValuePathResolution::NonGeneric(ty));
};
let builder = TyBuilder::subst_for_def(self.db, generic_def, parent_substs); let builder = TyBuilder::subst_for_def(self.db, generic_def, parent_substs);
let substs = builder let substs = builder
.fill(|x| { .fill(|x| {

View File

@ -60,7 +60,7 @@ use chalk_ir::{
NoSolution, NoSolution,
}; };
use either::Either; use either::Either;
use hir_def::{hir::ExprId, type_ref::Rawness, GeneralConstId, TypeOrConstParamId}; use hir_def::{hir::ExprId, type_ref::Rawness, CallableDefId, GeneralConstId, TypeOrConstParamId};
use hir_expand::name; use hir_expand::name;
use la_arena::{Arena, Idx}; use la_arena::{Arena, Idx};
use mir::{MirEvalError, VTableMap}; use mir::{MirEvalError, VTableMap};
@ -84,8 +84,8 @@ pub use infer::{
}; };
pub use interner::Interner; pub use interner::Interner;
pub use lower::{ pub use lower::{
associated_type_shorthand_candidates, CallableDefId, ImplTraitLoweringMode, ParamLoweringMode, associated_type_shorthand_candidates, ImplTraitLoweringMode, ParamLoweringMode, TyDefId,
TyDefId, TyLoweringContext, ValueTyDefId, TyLoweringContext, ValueTyDefId,
}; };
pub use mapping::{ pub use mapping::{
from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx,

View File

@ -11,10 +11,7 @@ use std::{
ops::{self, Not as _}, ops::{self, Not as _},
}; };
use base_db::{ use base_db::{salsa::Cycle, CrateId};
salsa::{Cycle, InternValueTrivial},
CrateId,
};
use chalk_ir::{ use chalk_ir::{
cast::Cast, cast::Cast,
fold::{Shift, TypeFoldable}, fold::{Shift, TypeFoldable},
@ -38,10 +35,10 @@ use hir_def::{
type_ref::{ type_ref::{
ConstRef, LifetimeRef, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef, ConstRef, LifetimeRef, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef,
}, },
AdtId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId,
GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstLoc, ItemContainerId, LocalFieldId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstLoc, ItemContainerId,
Lookup, ModuleDefId, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId, TypeOwnerId, LocalFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId,
UnionId, VariantId, TypeOwnerId, UnionId, VariantId,
}; };
use hir_expand::{name::Name, ExpandResult}; use hir_expand::{name::Name, ExpandResult};
use intern::Interned; use intern::Interned;
@ -1535,7 +1532,7 @@ pub(crate) fn generic_predicates_for_param_query(
def: GenericDefId, def: GenericDefId,
param_id: TypeOrConstParamId, param_id: TypeOrConstParamId,
assoc_name: Option<Name>, assoc_name: Option<Name>,
) -> Arc<[Binders<QuantifiedWhereClause>]> { ) -> GenericPredicates {
let resolver = def.resolver(db.upcast()); let resolver = def.resolver(db.upcast());
let ctx = if let GenericDefId::FunctionId(_) = def { let ctx = if let GenericDefId::FunctionId(_) = def {
TyLoweringContext::new(db, &resolver, def.into()) TyLoweringContext::new(db, &resolver, def.into())
@ -1611,7 +1608,7 @@ pub(crate) fn generic_predicates_for_param_query(
); );
}; };
} }
predicates.into() GenericPredicates(predicates.is_empty().not().then(|| predicates.into()))
} }
pub(crate) fn generic_predicates_for_param_recover( pub(crate) fn generic_predicates_for_param_recover(
@ -1620,15 +1617,15 @@ pub(crate) fn generic_predicates_for_param_recover(
_def: &GenericDefId, _def: &GenericDefId,
_param_id: &TypeOrConstParamId, _param_id: &TypeOrConstParamId,
_assoc_name: &Option<Name>, _assoc_name: &Option<Name>,
) -> Arc<[Binders<QuantifiedWhereClause>]> { ) -> GenericPredicates {
Arc::from_iter(None) GenericPredicates(None)
} }
pub(crate) fn trait_environment_for_body_query( pub(crate) fn trait_environment_for_body_query(
db: &dyn HirDatabase, db: &dyn HirDatabase,
def: DefWithBodyId, def: DefWithBodyId,
) -> Arc<TraitEnvironment> { ) -> Arc<TraitEnvironment> {
let Some(def) = def.as_generic_def_id() else { let Some(def) = def.as_generic_def_id(db.upcast()) else {
let krate = def.module(db.upcast()).krate(); let krate = def.module(db.upcast()).krate();
return TraitEnvironment::empty(krate); return TraitEnvironment::empty(krate);
}; };
@ -1995,47 +1992,6 @@ fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> {
} }
} }
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum CallableDefId {
FunctionId(FunctionId),
StructId(StructId),
EnumVariantId(EnumVariantId),
}
impl InternValueTrivial for CallableDefId {}
impl_from!(FunctionId, StructId, EnumVariantId for CallableDefId);
impl From<CallableDefId> for ModuleDefId {
fn from(def: CallableDefId) -> ModuleDefId {
match def {
CallableDefId::FunctionId(f) => ModuleDefId::FunctionId(f),
CallableDefId::StructId(s) => ModuleDefId::AdtId(AdtId::StructId(s)),
CallableDefId::EnumVariantId(e) => ModuleDefId::EnumVariantId(e),
}
}
}
impl CallableDefId {
pub fn krate(self, db: &dyn HirDatabase) -> CrateId {
let db = db.upcast();
match self {
CallableDefId::FunctionId(f) => f.krate(db),
CallableDefId::StructId(s) => s.krate(db),
CallableDefId::EnumVariantId(e) => e.krate(db),
}
}
}
impl From<CallableDefId> for GenericDefId {
fn from(def: CallableDefId) -> GenericDefId {
match def {
CallableDefId::FunctionId(f) => f.into(),
CallableDefId::StructId(s) => s.into(),
CallableDefId::EnumVariantId(e) => e.into(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum TyDefId { pub enum TyDefId {
BuiltinType(BuiltinType), BuiltinType(BuiltinType),
@ -2056,12 +2012,12 @@ pub enum ValueTyDefId {
impl_from!(FunctionId, StructId, UnionId, EnumVariantId, ConstId, StaticId for ValueTyDefId); impl_from!(FunctionId, StructId, UnionId, EnumVariantId, ConstId, StaticId for ValueTyDefId);
impl ValueTyDefId { impl ValueTyDefId {
pub(crate) fn to_generic_def_id(self) -> Option<GenericDefId> { pub(crate) fn to_generic_def_id(self, db: &dyn HirDatabase) -> Option<GenericDefId> {
match self { match self {
Self::FunctionId(id) => Some(id.into()), Self::FunctionId(id) => Some(id.into()),
Self::StructId(id) => Some(id.into()), Self::StructId(id) => Some(id.into()),
Self::UnionId(id) => Some(id.into()), Self::UnionId(id) => Some(id.into()),
Self::EnumVariantId(var) => Some(var.into()), Self::EnumVariantId(var) => Some(var.lookup(db.upcast()).parent.into()),
Self::ConstId(id) => Some(id.into()), Self::ConstId(id) => Some(id.into()),
Self::StaticId(_) => None, Self::StaticId(_) => None,
} }

View File

@ -1322,7 +1322,7 @@ fn iterate_inherent_methods(
callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
) -> ControlFlow<()> { ) -> ControlFlow<()> {
for &impl_id in impls.for_self_ty(self_ty) { for &impl_id in impls.for_self_ty(self_ty) {
for &item in &table.db.impl_data(impl_id).items { for &item in table.db.impl_data(impl_id).items.iter() {
let visible = match is_valid_impl_method_candidate( let visible = match is_valid_impl_method_candidate(
table, table,
self_ty, self_ty,

View File

@ -483,7 +483,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
Ok(Some(current)) Ok(Some(current))
} }
ValueNs::GenericParam(p) => { ValueNs::GenericParam(p) => {
let Some(def) = self.owner.as_generic_def_id() else { let Some(def) = self.owner.as_generic_def_id(self.db.upcast()) else {
not_supported!("owner without generic def id"); not_supported!("owner without generic def id");
}; };
let gen = generics(self.db.upcast(), def); let gen = generics(self.db.upcast(), def);
@ -1330,7 +1330,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
} }
fn placeholder_subst(&mut self) -> Substitution { fn placeholder_subst(&mut self) -> Substitution {
match self.owner.as_generic_def_id() { match self.owner.as_generic_def_id(self.db.upcast()) {
Some(it) => TyBuilder::placeholder_subst(self.db, it), Some(it) => TyBuilder::placeholder_subst(self.db, it),
None => Substitution::empty(Interner), None => Substitution::empty(Interner),
} }

View File

@ -302,7 +302,7 @@ pub fn monomorphized_mir_body_query(
subst: Substitution, subst: Substitution,
trait_env: Arc<crate::TraitEnvironment>, trait_env: Arc<crate::TraitEnvironment>,
) -> Result<Arc<MirBody>, MirLowerError> { ) -> Result<Arc<MirBody>, MirLowerError> {
let generics = owner.as_generic_def_id().map(|g_def| generics(db.upcast(), g_def)); let generics = owner.as_generic_def_id(db.upcast()).map(|g_def| generics(db.upcast(), g_def));
let filler = &mut Filler { db, subst: &subst, trait_env, generics, owner }; let filler = &mut Filler { db, subst: &subst, trait_env, generics, owner };
let body = db.mir_body(owner)?; let body = db.mir_body(owner)?;
let mut body = (*body).clone(); let mut body = (*body).clone();
@ -327,7 +327,7 @@ pub fn monomorphized_mir_body_for_closure_query(
trait_env: Arc<crate::TraitEnvironment>, trait_env: Arc<crate::TraitEnvironment>,
) -> Result<Arc<MirBody>, MirLowerError> { ) -> Result<Arc<MirBody>, MirLowerError> {
let InternedClosure(owner, _) = db.lookup_intern_closure(closure.into()); let InternedClosure(owner, _) = db.lookup_intern_closure(closure.into());
let generics = owner.as_generic_def_id().map(|g_def| generics(db.upcast(), g_def)); let generics = owner.as_generic_def_id(db.upcast()).map(|g_def| generics(db.upcast(), g_def));
let filler = &mut Filler { db, subst: &subst, trait_env, generics, owner }; let filler = &mut Filler { db, subst: &subst, trait_env, generics, owner };
let body = db.mir_body_for_closure(closure)?; let body = db.mir_body_for_closure(closure)?;
let mut body = (*body).clone(); let mut body = (*body).clone();
@ -343,7 +343,7 @@ pub fn monomorphize_mir_body_bad(
trait_env: Arc<crate::TraitEnvironment>, trait_env: Arc<crate::TraitEnvironment>,
) -> Result<MirBody, MirLowerError> { ) -> Result<MirBody, MirLowerError> {
let owner = body.owner; let owner = body.owner;
let generics = owner.as_generic_def_id().map(|g_def| generics(db.upcast(), g_def)); let generics = owner.as_generic_def_id(db.upcast()).map(|g_def| generics(db.upcast(), g_def));
let filler = &mut Filler { db, subst: &subst, trait_env, generics, owner }; let filler = &mut Filler { db, subst: &subst, trait_env, generics, owner };
filler.fill_body(&mut body)?; filler.fill_body(&mut body)?;
Ok(body) Ok(body)

View File

@ -182,7 +182,6 @@ impl From<GenericDef> for GenericDefId {
GenericDef::TraitAlias(it) => GenericDefId::TraitAliasId(it.id), GenericDef::TraitAlias(it) => GenericDefId::TraitAliasId(it.id),
GenericDef::TypeAlias(it) => GenericDefId::TypeAliasId(it.id), GenericDef::TypeAlias(it) => GenericDefId::TypeAliasId(it.id),
GenericDef::Impl(it) => GenericDefId::ImplId(it.id), GenericDef::Impl(it) => GenericDefId::ImplId(it.id),
GenericDef::Variant(it) => GenericDefId::EnumVariantId(it.into()),
GenericDef::Const(it) => GenericDefId::ConstId(it.id), GenericDef::Const(it) => GenericDefId::ConstId(it.id),
} }
} }
@ -197,7 +196,6 @@ impl From<GenericDefId> for GenericDef {
GenericDefId::TraitAliasId(it) => GenericDef::TraitAlias(it.into()), GenericDefId::TraitAliasId(it) => GenericDef::TraitAlias(it.into()),
GenericDefId::TypeAliasId(it) => GenericDef::TypeAlias(it.into()), GenericDefId::TypeAliasId(it) => GenericDef::TypeAlias(it.into()),
GenericDefId::ImplId(it) => GenericDef::Impl(it.into()), GenericDefId::ImplId(it) => GenericDef::Impl(it.into()),
GenericDefId::EnumVariantId(it) => GenericDef::Variant(it.into()),
GenericDefId::ConstId(it) => GenericDef::Const(it.into()), GenericDefId::ConstId(it) => GenericDef::Const(it.into()),
} }
} }

View File

@ -5,10 +5,10 @@ use either::Either;
use hir_def::{ use hir_def::{
nameres::{ModuleOrigin, ModuleSource}, nameres::{ModuleOrigin, ModuleSource},
src::{HasChildSource, HasSource as _}, src::{HasChildSource, HasSource as _},
Lookup, MacroId, VariantId, CallableDefId, Lookup, MacroId, VariantId,
}; };
use hir_expand::{HirFileId, InFile}; use hir_expand::{HirFileId, InFile};
use hir_ty::{db::InternedClosure, CallableDefId}; use hir_ty::db::InternedClosure;
use syntax::ast; use syntax::ast;
use tt::TextRange; use tt::TextRange;

View File

@ -52,11 +52,11 @@ use hir_def::{
path::ImportAlias, path::ImportAlias,
per_ns::PerNs, per_ns::PerNs,
resolver::{HasResolver, Resolver}, resolver::{HasResolver, Resolver},
AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, AssocItemId, AssocItemLoc, AttrDefId, CallableDefId, ConstId, ConstParamId, CrateRootModuleId,
EnumId, EnumVariantId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FunctionId, GenericDefId, GenericParamId,
ImplId, InTypeConstId, ItemContainerId, LifetimeParamId, LocalFieldId, Lookup, MacroExpander, HasModule, ImplId, InTypeConstId, ItemContainerId, LifetimeParamId, LocalFieldId, Lookup,
ModuleId, StaticId, StructId, TraitAliasId, TraitId, TupleId, TypeAliasId, TypeOrConstParamId, MacroExpander, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TupleId, TypeAliasId,
TypeParamId, UnionId, TypeOrConstParamId, TypeParamId, UnionId,
}; };
use hir_expand::{ use hir_expand::{
attrs::collect_attrs, name::name, proc_macro::ProcMacroKind, AstId, MacroCallKind, ValueResult, attrs::collect_attrs, name::name, proc_macro::ProcMacroKind, AstId, MacroCallKind, ValueResult,
@ -71,7 +71,7 @@ use hir_ty::{
mir::{interpret_mir, MutBorrowKind}, mir::{interpret_mir, MutBorrowKind},
primitive::UintTy, primitive::UintTy,
traits::FnTrait, traits::FnTrait,
AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, GenericArg, AliasTy, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, GenericArg,
GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution, GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution,
TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, ValueTyDefId, TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, ValueTyDefId,
WhereClause, WhereClause,
@ -760,7 +760,7 @@ impl Module {
impl_assoc_items_scratch.clear(); impl_assoc_items_scratch.clear();
} }
for &item in &db.impl_data(impl_def.id).items { for &item in db.impl_data(impl_def.id).items.iter() {
AssocItem::from(item).diagnostics(db, acc, style_lints); AssocItem::from(item).diagnostics(db, acc, style_lints);
} }
} }
@ -1144,7 +1144,7 @@ impl Field {
let generic_def_id: GenericDefId = match self.parent { let generic_def_id: GenericDefId = match self.parent {
VariantDef::Struct(it) => it.id.into(), VariantDef::Struct(it) => it.id.into(),
VariantDef::Union(it) => it.id.into(), VariantDef::Union(it) => it.id.into(),
VariantDef::Variant(it) => it.id.into(), VariantDef::Variant(it) => it.id.lookup(db.upcast()).parent.into(),
}; };
let substs = TyBuilder::placeholder_subst(db, generic_def_id); let substs = TyBuilder::placeholder_subst(db, generic_def_id);
let ty = db.field_types(var_id)[self.id].clone().substitute(Interner, &substs); let ty = db.field_types(var_id)[self.id].clone().substitute(Interner, &substs);
@ -1177,7 +1177,9 @@ impl Field {
db.layout_of_ty( db.layout_of_ty(
self.ty(db).ty, self.ty(db).ty,
db.trait_environment(match hir_def::VariantId::from(self.parent) { db.trait_environment(match hir_def::VariantId::from(self.parent) {
hir_def::VariantId::EnumVariantId(id) => GenericDefId::EnumVariantId(id), hir_def::VariantId::EnumVariantId(id) => {
GenericDefId::AdtId(id.lookup(db.upcast()).parent.into())
}
hir_def::VariantId::StructId(id) => GenericDefId::AdtId(id.into()), hir_def::VariantId::StructId(id) => GenericDefId::AdtId(id.into()),
hir_def::VariantId::UnionId(id) => GenericDefId::AdtId(id.into()), hir_def::VariantId::UnionId(id) => GenericDefId::AdtId(id.into()),
}), }),
@ -2501,7 +2503,7 @@ impl Trait {
db: &dyn HirDatabase, db: &dyn HirDatabase,
count_required_only: bool, count_required_only: bool,
) -> usize { ) -> usize {
db.generic_params(GenericDefId::from(self.id)) db.generic_params(self.id.into())
.type_or_consts .type_or_consts
.iter() .iter()
.filter(|(_, ty)| !matches!(ty, TypeOrConstParamData::TypeParamData(ty) if ty.provenance != TypeParamProvenance::TypeParamList)) .filter(|(_, ty)| !matches!(ty, TypeOrConstParamData::TypeParamData(ty) if ty.provenance != TypeParamProvenance::TypeParamList))
@ -3107,9 +3109,6 @@ pub enum GenericDef {
TraitAlias(TraitAlias), TraitAlias(TraitAlias),
TypeAlias(TypeAlias), TypeAlias(TypeAlias),
Impl(Impl), Impl(Impl),
// enum variants cannot have generics themselves, but their parent enums
// can, and this makes some code easier to write
Variant(Variant),
// consts can have type parameters from their parents (i.e. associated consts of traits) // consts can have type parameters from their parents (i.e. associated consts of traits)
Const(Const), Const(Const),
} }
@ -3120,7 +3119,6 @@ impl_from!(
TraitAlias, TraitAlias,
TypeAlias, TypeAlias,
Impl, Impl,
Variant,
Const Const
for GenericDef for GenericDef
); );
@ -4052,7 +4050,9 @@ impl Type {
ValueTyDefId::FunctionId(it) => GenericDefId::FunctionId(it), ValueTyDefId::FunctionId(it) => GenericDefId::FunctionId(it),
ValueTyDefId::StructId(it) => GenericDefId::AdtId(AdtId::StructId(it)), ValueTyDefId::StructId(it) => GenericDefId::AdtId(AdtId::StructId(it)),
ValueTyDefId::UnionId(it) => GenericDefId::AdtId(AdtId::UnionId(it)), ValueTyDefId::UnionId(it) => GenericDefId::AdtId(AdtId::UnionId(it)),
ValueTyDefId::EnumVariantId(it) => GenericDefId::EnumVariantId(it), ValueTyDefId::EnumVariantId(it) => {
GenericDefId::AdtId(AdtId::EnumId(it.lookup(db.upcast()).parent))
}
ValueTyDefId::StaticId(_) => return Type::new(db, def, ty.skip_binders().clone()), ValueTyDefId::StaticId(_) => return Type::new(db, def, ty.skip_binders().clone()),
}, },
); );

View File

@ -231,7 +231,7 @@ impl<'a> SymbolCollector<'a> {
let impl_data = self.db.impl_data(impl_id); let impl_data = self.db.impl_data(impl_id);
let impl_name = Some(SmolStr::new(impl_data.self_ty.display(self.db).to_string())); let impl_name = Some(SmolStr::new(impl_data.self_ty.display(self.db).to_string()));
self.with_container_name(impl_name, |s| { self.with_container_name(impl_name, |s| {
for &assoc_item_id in &impl_data.items { for &assoc_item_id in impl_data.items.iter() {
s.push_assoc_item(assoc_item_id) s.push_assoc_item(assoc_item_id)
} }
}) })

View File

@ -209,7 +209,7 @@ impl Expr {
} }
} }
Expr::Variant { variant, generics, params } => { Expr::Variant { variant, generics, params } => {
let generics = non_default_generics(db, (*variant).into(), generics); let generics = non_default_generics(db, variant.parent_enum(db).into(), generics);
let generics_str = match generics.is_empty() { let generics_str = match generics.is_empty() {
true => String::new(), true => String::new(),
false => { false => {

View File

@ -144,7 +144,7 @@ fn f() { let a = A { x: 1, y: true }; let b: i32 = a.x; }"#,
term_search, term_search,
r#"//- minicore: todo, unimplemented, option r#"//- minicore: todo, unimplemented, option
fn f() { let a: i32 = 1; let b: Option<i32> = todo$0!(); }"#, fn f() { let a: i32 = 1; let b: Option<i32> = todo$0!(); }"#,
r#"fn f() { let a: i32 = 1; let b: Option<i32> = Some(a); }"#, r#"fn f() { let a: i32 = 1; let b: Option<i32> = Some::<i32>(a); }"#,
) )
} }
@ -156,7 +156,7 @@ fn f() { let a: i32 = 1; let b: Option<i32> = todo$0!(); }"#,
enum Option<T> { None, Some(T) } enum Option<T> { None, Some(T) }
fn f() { let a: i32 = 1; let b: Option<i32> = todo$0!(); }"#, fn f() { let a: i32 = 1; let b: Option<i32> = todo$0!(); }"#,
r#"enum Option<T> { None, Some(T) } r#"enum Option<T> { None, Some(T) }
fn f() { let a: i32 = 1; let b: Option<i32> = Option::Some(a); }"#, fn f() { let a: i32 = 1; let b: Option<i32> = Option::Some::<i32>(a); }"#,
) )
} }
@ -168,7 +168,7 @@ fn f() { let a: i32 = 1; let b: Option<i32> = Option::Some(a); }"#,
enum Option<T> { None, Some(T) } enum Option<T> { None, Some(T) }
fn f() { let a: Option<i32> = Option::None; let b: Option<Option<i32>> = todo$0!(); }"#, fn f() { let a: Option<i32> = Option::None; let b: Option<Option<i32>> = todo$0!(); }"#,
r#"enum Option<T> { None, Some(T) } r#"enum Option<T> { None, Some(T) }
fn f() { let a: Option<i32> = Option::None; let b: Option<Option<i32>> = Option::Some(a); }"#, fn f() { let a: Option<i32> = Option::None; let b: Option<Option<i32>> = Option::Some::<Option<i32>>(a); }"#,
) )
} }
@ -180,7 +180,7 @@ fn f() { let a: Option<i32> = Option::None; let b: Option<Option<i32>> = Option:
enum Foo<T = i32> { Foo(T) } enum Foo<T = i32> { Foo(T) }
fn f() { let a = 0; let b: Foo = todo$0!(); }"#, fn f() { let a = 0; let b: Foo = todo$0!(); }"#,
r#"enum Foo<T = i32> { Foo(T) } r#"enum Foo<T = i32> { Foo(T) }
fn f() { let a = 0; let b: Foo = Foo::Foo(a); }"#, fn f() { let a = 0; let b: Foo = Foo::Foo::<i32>(a); }"#,
); );
check_assist( check_assist(

View File

@ -2641,7 +2641,7 @@ fn foo() {
expect![[r#" expect![[r#"
lc foo [type+local] lc foo [type+local]
ex foo [type] ex foo [type]
ex Foo::B [type] ex Foo::B::<u32> [type]
ev Foo::A() [type_could_unify] ev Foo::A() [type_could_unify]
ev Foo::B [type_could_unify] ev Foo::B [type_could_unify]
en Foo [type_could_unify] en Foo [type_could_unify]

View File

@ -79,8 +79,9 @@ pub fn generic_def_for_node(
sema: &Semantics<'_, RootDatabase>, sema: &Semantics<'_, RootDatabase>,
generic_arg_list: &ast::GenericArgList, generic_arg_list: &ast::GenericArgList,
token: &SyntaxToken, token: &SyntaxToken,
) -> Option<(hir::GenericDef, usize, bool)> { ) -> Option<(hir::GenericDef, usize, bool, Option<hir::Variant>)> {
let parent = generic_arg_list.syntax().parent()?; let parent = generic_arg_list.syntax().parent()?;
let mut variant = None;
let def = match_ast! { let def = match_ast! {
match parent { match parent {
ast::PathSegment(ps) => { ast::PathSegment(ps) => {
@ -91,7 +92,10 @@ pub fn generic_def_for_node(
hir::PathResolution::Def(hir::ModuleDef::Trait(it)) => it.into(), hir::PathResolution::Def(hir::ModuleDef::Trait(it)) => it.into(),
hir::PathResolution::Def(hir::ModuleDef::TraitAlias(it)) => it.into(), hir::PathResolution::Def(hir::ModuleDef::TraitAlias(it)) => it.into(),
hir::PathResolution::Def(hir::ModuleDef::TypeAlias(it)) => it.into(), hir::PathResolution::Def(hir::ModuleDef::TypeAlias(it)) => it.into(),
hir::PathResolution::Def(hir::ModuleDef::Variant(it)) => it.into(), hir::PathResolution::Def(hir::ModuleDef::Variant(it)) => {
variant = Some(it);
it.parent_enum(sema.db).into()
},
hir::PathResolution::Def(hir::ModuleDef::BuiltinType(_)) hir::PathResolution::Def(hir::ModuleDef::BuiltinType(_))
| hir::PathResolution::Def(hir::ModuleDef::Const(_)) | hir::PathResolution::Def(hir::ModuleDef::Const(_))
| hir::PathResolution::Def(hir::ModuleDef::Macro(_)) | hir::PathResolution::Def(hir::ModuleDef::Macro(_))
@ -134,5 +138,5 @@ pub fn generic_def_for_node(
.next() .next()
.map_or(false, |arg| !matches!(arg, ast::GenericArg::LifetimeArg(_))); .map_or(false, |arg| !matches!(arg, ast::GenericArg::LifetimeArg(_)));
Some((def, active_param, first_arg_is_non_lifetime)) Some((def, active_param, first_arg_is_non_lifetime, variant))
} }

View File

@ -320,7 +320,6 @@ impl Definition {
hir::GenericDef::TraitAlias(it) => it.source(db).map(|src| src.syntax().cloned()), hir::GenericDef::TraitAlias(it) => it.source(db).map(|src| src.syntax().cloned()),
hir::GenericDef::TypeAlias(it) => it.source(db).map(|src| src.syntax().cloned()), hir::GenericDef::TypeAlias(it) => it.source(db).map(|src| src.syntax().cloned()),
hir::GenericDef::Impl(it) => it.source(db).map(|src| src.syntax().cloned()), hir::GenericDef::Impl(it) => it.source(db).map(|src| src.syntax().cloned()),
hir::GenericDef::Variant(it) => it.source(db).map(|src| src.syntax().cloned()),
hir::GenericDef::Const(it) => it.source(db).map(|src| src.syntax().cloned()), hir::GenericDef::Const(it) => it.source(db).map(|src| src.syntax().cloned()),
}; };
return match def { return match def {

View File

@ -272,7 +272,7 @@ fn signature_help_for_generics(
arg_list: ast::GenericArgList, arg_list: ast::GenericArgList,
token: SyntaxToken, token: SyntaxToken,
) -> Option<SignatureHelp> { ) -> Option<SignatureHelp> {
let (mut generics_def, mut active_parameter, first_arg_is_non_lifetime) = let (generics_def, mut active_parameter, first_arg_is_non_lifetime, variant) =
generic_def_for_node(sema, &arg_list, &token)?; generic_def_for_node(sema, &arg_list, &token)?;
let mut res = SignatureHelp { let mut res = SignatureHelp {
doc: None, doc: None,
@ -290,6 +290,12 @@ fn signature_help_for_generics(
hir::GenericDef::Adt(hir::Adt::Enum(it)) => { hir::GenericDef::Adt(hir::Adt::Enum(it)) => {
res.doc = it.docs(db); res.doc = it.docs(db);
format_to!(res.signature, "enum {}", it.name(db).display(db)); format_to!(res.signature, "enum {}", it.name(db).display(db));
if let Some(variant) = variant {
// In paths, generics of an enum can be specified *after* one of its variants.
// eg. `None::<u8>`
// We'll use the signature of the enum, but include the docs of the variant.
res.doc = variant.docs(db);
}
} }
hir::GenericDef::Adt(hir::Adt::Struct(it)) => { hir::GenericDef::Adt(hir::Adt::Struct(it)) => {
res.doc = it.docs(db); res.doc = it.docs(db);
@ -311,15 +317,6 @@ fn signature_help_for_generics(
res.doc = it.docs(db); res.doc = it.docs(db);
format_to!(res.signature, "type {}", it.name(db).display(db)); format_to!(res.signature, "type {}", it.name(db).display(db));
} }
hir::GenericDef::Variant(it) => {
// In paths, generics of an enum can be specified *after* one of its variants.
// eg. `None::<u8>`
// We'll use the signature of the enum, but include the docs of the variant.
res.doc = it.docs(db);
let enum_ = it.parent_enum(db);
format_to!(res.signature, "enum {}", enum_.name(db).display(db));
generics_def = enum_.into();
}
// These don't have generic args that can be specified // These don't have generic args that can be specified
hir::GenericDef::Impl(_) | hir::GenericDef::Const(_) => return None, hir::GenericDef::Impl(_) | hir::GenericDef::Const(_) => return None,
} }

View File

@ -16,6 +16,7 @@ cov-mark = "2.0.0-pre.1"
rustc-hash.workspace = true rustc-hash.workspace = true
smallvec.workspace = true smallvec.workspace = true
tracing.workspace = true tracing.workspace = true
arrayvec.workspace = true
# local deps # local deps
syntax.workspace = true syntax.workspace = true

View File

@ -170,7 +170,7 @@ fn invocation_fixtures(
Op::Literal(it) => token_trees.push(tt::Leaf::from(it.clone()).into()), Op::Literal(it) => token_trees.push(tt::Leaf::from(it.clone()).into()),
Op::Ident(it) => token_trees.push(tt::Leaf::from(it.clone()).into()), Op::Ident(it) => token_trees.push(tt::Leaf::from(it.clone()).into()),
Op::Punct(puncts) => { Op::Punct(puncts) => {
for punct in puncts { for punct in puncts.as_slice() {
token_trees.push(tt::Leaf::from(*punct).into()); token_trees.push(tt::Leaf::from(*punct).into());
} }
} }
@ -187,7 +187,7 @@ fn invocation_fixtures(
} }
if i + 1 != cnt { if i + 1 != cnt {
if let Some(sep) = separator { if let Some(sep) = separator {
match sep { match &**sep {
Separator::Literal(it) => { Separator::Literal(it) => {
token_trees.push(tt::Leaf::Literal(it.clone()).into()) token_trees.push(tt::Leaf::Literal(it.clone()).into())
} }

View File

@ -59,7 +59,7 @@
//! eof: [a $( a )* a b ·] //! eof: [a $( a )* a b ·]
//! ``` //! ```
use std::rc::Rc; use std::{rc::Rc, sync::Arc};
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
use span::{Edition, Span}; use span::{Edition, Span};
@ -315,7 +315,7 @@ struct MatchState<'t> {
up: Option<Box<MatchState<'t>>>, up: Option<Box<MatchState<'t>>>,
/// The separator if we are in a repetition. /// The separator if we are in a repetition.
sep: Option<Separator>, sep: Option<Arc<Separator>>,
/// The KleeneOp of this sequence if we are in a repetition. /// The KleeneOp of this sequence if we are in a repetition.
sep_kind: Option<RepeatKind>, sep_kind: Option<RepeatKind>,

View File

@ -195,7 +195,7 @@ fn expand_subtree(
.into(), .into(),
), ),
Op::Punct(puncts) => { Op::Punct(puncts) => {
for punct in puncts { for punct in puncts.as_slice() {
arena.push( arena.push(
tt::Leaf::from({ tt::Leaf::from({
let mut it = *punct; let mut it = *punct;
@ -222,7 +222,7 @@ fn expand_subtree(
} }
Op::Repeat { tokens: subtree, kind, separator } => { Op::Repeat { tokens: subtree, kind, separator } => {
let ExpandResult { value: fragment, err: e } = let ExpandResult { value: fragment, err: e } =
expand_repeat(ctx, subtree, *kind, separator, arena, marker); expand_repeat(ctx, subtree, *kind, separator.as_deref(), arena, marker);
err = err.or(e); err = err.or(e);
push_fragment(ctx, arena, fragment) push_fragment(ctx, arena, fragment)
} }
@ -383,7 +383,7 @@ fn expand_repeat(
ctx: &mut ExpandCtx<'_>, ctx: &mut ExpandCtx<'_>,
template: &MetaTemplate, template: &MetaTemplate,
kind: RepeatKind, kind: RepeatKind,
separator: &Option<Separator>, separator: Option<&Separator>,
arena: &mut Vec<tt::TokenTree<Span>>, arena: &mut Vec<tt::TokenTree<Span>>,
marker: impl Fn(&mut Span) + Copy, marker: impl Fn(&mut Span) + Copy,
) -> ExpandResult<Fragment> { ) -> ExpandResult<Fragment> {

View File

@ -1,7 +1,9 @@
//! Parser recognizes special macro syntax, `$var` and `$(repeat)*`, in token //! Parser recognizes special macro syntax, `$var` and `$(repeat)*`, in token
//! trees. //! trees.
use smallvec::{smallvec, SmallVec}; use std::sync::Arc;
use arrayvec::ArrayVec;
use span::{Edition, Span, SyntaxContextId}; use span::{Edition, Span, SyntaxContextId};
use syntax::SmolStr; use syntax::SmolStr;
@ -86,14 +88,14 @@ pub(crate) enum Op {
Repeat { Repeat {
tokens: MetaTemplate, tokens: MetaTemplate,
kind: RepeatKind, kind: RepeatKind,
separator: Option<Separator>, separator: Option<Arc<Separator>>,
}, },
Subtree { Subtree {
tokens: MetaTemplate, tokens: MetaTemplate,
delimiter: tt::Delimiter<Span>, delimiter: tt::Delimiter<Span>,
}, },
Literal(tt::Literal<Span>), Literal(tt::Literal<Span>),
Punct(SmallVec<[tt::Punct<Span>; 3]>), Punct(Box<ArrayVec<tt::Punct<Span>, 3>>),
Ident(tt::Ident<Span>), Ident(tt::Ident<Span>),
} }
@ -126,7 +128,7 @@ pub(crate) enum MetaVarKind {
pub(crate) enum Separator { pub(crate) enum Separator {
Literal(tt::Literal<Span>), Literal(tt::Literal<Span>),
Ident(tt::Ident<Span>), Ident(tt::Ident<Span>),
Puncts(SmallVec<[tt::Punct<Span>; 3]>), Puncts(ArrayVec<tt::Punct<Span>, 3>),
} }
// Note that when we compare a Separator, we just care about its textual value. // Note that when we compare a Separator, we just care about its textual value.
@ -165,7 +167,13 @@ fn next_op(
src.next().expect("first token already peeked"); src.next().expect("first token already peeked");
// Note that the '$' itself is a valid token inside macro_rules. // Note that the '$' itself is a valid token inside macro_rules.
let second = match src.next() { let second = match src.next() {
None => return Ok(Op::Punct(smallvec![*p])), None => {
return Ok(Op::Punct({
let mut res = ArrayVec::new();
res.push(*p);
Box::new(res)
}))
}
Some(it) => it, Some(it) => it,
}; };
match second { match second {
@ -173,7 +181,7 @@ fn next_op(
tt::DelimiterKind::Parenthesis => { tt::DelimiterKind::Parenthesis => {
let (separator, kind) = parse_repeat(src)?; let (separator, kind) = parse_repeat(src)?;
let tokens = MetaTemplate::parse(edition, subtree, mode, new_meta_vars)?; let tokens = MetaTemplate::parse(edition, subtree, mode, new_meta_vars)?;
Op::Repeat { tokens, separator, kind } Op::Repeat { tokens, separator: separator.map(Arc::new), kind }
} }
tt::DelimiterKind::Brace => match mode { tt::DelimiterKind::Brace => match mode {
Mode::Template => { Mode::Template => {
@ -216,7 +224,11 @@ fn next_op(
"`$$` is not allowed on the pattern side", "`$$` is not allowed on the pattern side",
)) ))
} }
Mode::Template => Op::Punct(smallvec![*punct]), Mode::Template => Op::Punct({
let mut res = ArrayVec::new();
res.push(*punct);
Box::new(res)
}),
}, },
tt::Leaf::Punct(_) | tt::Leaf::Literal(_) => { tt::Leaf::Punct(_) | tt::Leaf::Literal(_) => {
return Err(ParseError::expected("expected ident")) return Err(ParseError::expected("expected ident"))
@ -238,7 +250,7 @@ fn next_op(
tt::TokenTree::Leaf(tt::Leaf::Punct(_)) => { tt::TokenTree::Leaf(tt::Leaf::Punct(_)) => {
// There's at least one punct so this shouldn't fail. // There's at least one punct so this shouldn't fail.
let puncts = src.expect_glued_punct().unwrap(); let puncts = src.expect_glued_punct().unwrap();
Op::Punct(puncts) Op::Punct(Box::new(puncts))
} }
tt::TokenTree::Subtree(subtree) => { tt::TokenTree::Subtree(subtree) => {
@ -290,7 +302,7 @@ fn is_boolean_literal(lit: &tt::Literal<Span>) -> bool {
} }
fn parse_repeat(src: &mut TtIter<'_, Span>) -> Result<(Option<Separator>, RepeatKind), ParseError> { fn parse_repeat(src: &mut TtIter<'_, Span>) -> Result<(Option<Separator>, RepeatKind), ParseError> {
let mut separator = Separator::Puncts(SmallVec::new()); let mut separator = Separator::Puncts(ArrayVec::new());
for tt in src { for tt in src {
let tt = match tt { let tt = match tt {
tt::TokenTree::Leaf(leaf) => leaf, tt::TokenTree::Leaf(leaf) => leaf,
@ -312,7 +324,7 @@ fn parse_repeat(src: &mut TtIter<'_, Span>) -> Result<(Option<Separator>, Repeat
'+' => RepeatKind::OneOrMore, '+' => RepeatKind::OneOrMore,
'?' => RepeatKind::ZeroOrOne, '?' => RepeatKind::ZeroOrOne,
_ => match &mut separator { _ => match &mut separator {
Separator::Puncts(puncts) if puncts.len() != 3 => { Separator::Puncts(puncts) if puncts.len() < 3 => {
puncts.push(*punct); puncts.push(*punct);
continue; continue;
} }

View File

@ -3,7 +3,7 @@
use core::fmt; use core::fmt;
use smallvec::{smallvec, SmallVec}; use arrayvec::ArrayVec;
use syntax::SyntaxKind; use syntax::SyntaxKind;
use crate::{to_parser_input::to_parser_input, ExpandError, ExpandResult}; use crate::{to_parser_input::to_parser_input, ExpandError, ExpandResult};
@ -93,13 +93,15 @@ impl<'a, S: Copy> TtIter<'a, S> {
/// ///
/// This method currently may return a single quotation, which is part of lifetime ident and /// This method currently may return a single quotation, which is part of lifetime ident and
/// conceptually not a punct in the context of mbe. Callers should handle this. /// conceptually not a punct in the context of mbe. Callers should handle this.
pub(crate) fn expect_glued_punct(&mut self) -> Result<SmallVec<[tt::Punct<S>; 3]>, ()> { pub(crate) fn expect_glued_punct(&mut self) -> Result<ArrayVec<tt::Punct<S>, 3>, ()> {
let tt::TokenTree::Leaf(tt::Leaf::Punct(first)) = self.next().ok_or(())?.clone() else { let tt::TokenTree::Leaf(tt::Leaf::Punct(first)) = self.next().ok_or(())?.clone() else {
return Err(()); return Err(());
}; };
let mut res = ArrayVec::new();
if first.spacing == tt::Spacing::Alone { if first.spacing == tt::Spacing::Alone {
return Ok(smallvec![first]); res.push(first);
return Ok(res);
} }
let (second, third) = match (self.peek_n(0), self.peek_n(1)) { let (second, third) = match (self.peek_n(0), self.peek_n(1)) {
@ -108,14 +110,19 @@ impl<'a, S: Copy> TtIter<'a, S> {
Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p3))), Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p3))),
) if p2.spacing == tt::Spacing::Joint => (p2, Some(p3)), ) if p2.spacing == tt::Spacing::Joint => (p2, Some(p3)),
(Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p2))), _) => (p2, None), (Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p2))), _) => (p2, None),
_ => return Ok(smallvec![first]), _ => {
res.push(first);
return Ok(res);
}
}; };
match (first.char, second.char, third.map(|it| it.char)) { match (first.char, second.char, third.map(|it| it.char)) {
('.', '.', Some('.' | '=')) | ('<', '<', Some('=')) | ('>', '>', Some('=')) => { ('.', '.', Some('.' | '=')) | ('<', '<', Some('=')) | ('>', '>', Some('=')) => {
let _ = self.next().unwrap(); let _ = self.next().unwrap();
let _ = self.next().unwrap(); let _ = self.next().unwrap();
Ok(smallvec![first, *second, *third.unwrap()]) res.push(first);
res.push(*second);
res.push(*third.unwrap());
} }
('-' | '!' | '*' | '/' | '&' | '%' | '^' | '+' | '<' | '=' | '>' | '|', '=', _) ('-' | '!' | '*' | '/' | '&' | '%' | '^' | '+' | '<' | '=' | '>' | '|', '=', _)
| ('-' | '=' | '>', '>', _) | ('-' | '=' | '>', '>', _)
@ -126,10 +133,12 @@ impl<'a, S: Copy> TtIter<'a, S> {
| ('<', '<', _) | ('<', '<', _)
| ('|', '|', _) => { | ('|', '|', _) => {
let _ = self.next().unwrap(); let _ = self.next().unwrap();
Ok(smallvec![first, *second]) res.push(first);
res.push(*second);
} }
_ => Ok(smallvec![first]), _ => res.push(first),
} }
Ok(res)
} }
pub(crate) fn peek_n(&self, n: usize) -> Option<&'a tt::TokenTree<S>> { pub(crate) fn peek_n(&self, n: usize) -> Option<&'a tt::TokenTree<S>> {
self.inner.as_slice().get(n) self.inner.as_slice().get(n)