Eagerly lower enum variants in CrateDefMap construction
This commit is contained in:
parent
9d8889cdfc
commit
d80d2fcae0
@ -28,8 +28,8 @@ use crate::{
|
|||||||
lang_item::LangItem,
|
lang_item::LangItem,
|
||||||
nameres::{ModuleOrigin, ModuleSource},
|
nameres::{ModuleOrigin, ModuleSource},
|
||||||
src::{HasChildSource, HasSource},
|
src::{HasChildSource, HasSource},
|
||||||
AdtId, AssocItemLoc, AttrDefId, EnumId, GenericParamId, ItemLoc, LocalEnumVariantId,
|
AdtId, AssocItemLoc, AttrDefId, GenericParamId, ItemLoc, LocalFieldId, Lookup, MacroId,
|
||||||
LocalFieldId, Lookup, MacroId, VariantId,
|
VariantId,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq)]
|
||||||
@ -70,33 +70,6 @@ impl ops::Deref for AttrsWithOwner {
|
|||||||
impl Attrs {
|
impl Attrs {
|
||||||
pub const EMPTY: Self = Self(RawAttrs::EMPTY);
|
pub const EMPTY: Self = Self(RawAttrs::EMPTY);
|
||||||
|
|
||||||
pub(crate) fn variants_attrs_query(
|
|
||||||
db: &dyn DefDatabase,
|
|
||||||
e: EnumId,
|
|
||||||
) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>> {
|
|
||||||
let _p = profile::span("variants_attrs_query");
|
|
||||||
// FIXME: There should be some proper form of mapping between item tree enum variant ids and hir enum variant ids
|
|
||||||
let mut res = ArenaMap::default();
|
|
||||||
|
|
||||||
let loc = e.lookup(db);
|
|
||||||
let krate = loc.container.krate;
|
|
||||||
let item_tree = loc.id.item_tree(db);
|
|
||||||
let enum_ = &item_tree[loc.id.value];
|
|
||||||
let crate_graph = db.crate_graph();
|
|
||||||
let cfg_options = &crate_graph[krate].cfg_options;
|
|
||||||
|
|
||||||
let mut idx = 0;
|
|
||||||
for variant in enum_.variants.clone() {
|
|
||||||
let attrs = item_tree.attrs(db, krate, variant.into());
|
|
||||||
if attrs.is_cfg_enabled(cfg_options) {
|
|
||||||
res.insert(Idx::from_raw(RawIdx::from(idx)), attrs);
|
|
||||||
idx += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Arc::new(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn fields_attrs_query(
|
pub(crate) fn fields_attrs_query(
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
v: VariantId,
|
v: VariantId,
|
||||||
@ -108,29 +81,11 @@ impl Attrs {
|
|||||||
let crate_graph = db.crate_graph();
|
let crate_graph = db.crate_graph();
|
||||||
let (fields, item_tree, krate) = match v {
|
let (fields, item_tree, krate) = match v {
|
||||||
VariantId::EnumVariantId(it) => {
|
VariantId::EnumVariantId(it) => {
|
||||||
let e = it.parent;
|
let loc = it.lookup(db);
|
||||||
let loc = e.lookup(db);
|
|
||||||
let krate = loc.container.krate;
|
let krate = loc.container.krate;
|
||||||
let item_tree = loc.id.item_tree(db);
|
let item_tree = loc.id.item_tree(db);
|
||||||
let enum_ = &item_tree[loc.id.value];
|
let variant = &item_tree[loc.id.value];
|
||||||
|
(variant.fields.clone(), item_tree, krate)
|
||||||
let cfg_options = &crate_graph[krate].cfg_options;
|
|
||||||
|
|
||||||
let Some(variant) = enum_
|
|
||||||
.variants
|
|
||||||
.clone()
|
|
||||||
.filter(|variant| {
|
|
||||||
let attrs = item_tree.attrs(db, krate, (*variant).into());
|
|
||||||
attrs.is_cfg_enabled(cfg_options)
|
|
||||||
})
|
|
||||||
.zip(0u32..)
|
|
||||||
.find(|(_variant, idx)| it.local_id == Idx::from_raw(RawIdx::from(*idx)))
|
|
||||||
.map(|(variant, _idx)| variant)
|
|
||||||
else {
|
|
||||||
return Arc::new(res);
|
|
||||||
};
|
|
||||||
|
|
||||||
(item_tree[variant].fields.clone(), item_tree, krate)
|
|
||||||
}
|
}
|
||||||
VariantId::StructId(it) => {
|
VariantId::StructId(it) => {
|
||||||
let loc = it.lookup(db);
|
let loc = it.lookup(db);
|
||||||
@ -401,10 +356,12 @@ impl AttrsWithOwner {
|
|||||||
AttrDefId::FieldId(it) => {
|
AttrDefId::FieldId(it) => {
|
||||||
return db.fields_attrs(it.parent)[it.local_id].clone();
|
return db.fields_attrs(it.parent)[it.local_id].clone();
|
||||||
}
|
}
|
||||||
AttrDefId::EnumVariantId(it) => {
|
|
||||||
return db.variants_attrs(it.parent)[it.local_id].clone();
|
|
||||||
}
|
|
||||||
// FIXME: DRY this up
|
// FIXME: DRY this up
|
||||||
|
AttrDefId::EnumVariantId(it) => {
|
||||||
|
let id = it.lookup(db).id;
|
||||||
|
let tree = id.item_tree(db);
|
||||||
|
tree.raw_attrs(id.value.into()).clone()
|
||||||
|
}
|
||||||
AttrDefId::AdtId(it) => match it {
|
AttrDefId::AdtId(it) => match it {
|
||||||
AdtId::StructId(it) => attrs_from_item_tree_loc(db, it),
|
AdtId::StructId(it) => attrs_from_item_tree_loc(db, it),
|
||||||
AdtId::EnumId(it) => attrs_from_item_tree_loc(db, it),
|
AdtId::EnumId(it) => attrs_from_item_tree_loc(db, it),
|
||||||
@ -503,12 +460,7 @@ impl AttrsWithOwner {
|
|||||||
AdtId::EnumId(id) => any_has_attrs(db, id),
|
AdtId::EnumId(id) => any_has_attrs(db, id),
|
||||||
},
|
},
|
||||||
AttrDefId::FunctionId(id) => any_has_attrs(db, id),
|
AttrDefId::FunctionId(id) => any_has_attrs(db, id),
|
||||||
AttrDefId::EnumVariantId(id) => {
|
AttrDefId::EnumVariantId(id) => any_has_attrs(db, id),
|
||||||
let map = db.variants_attrs_source_map(id.parent);
|
|
||||||
let file_id = id.parent.lookup(db).id.file_id();
|
|
||||||
let root = db.parse_or_expand(file_id);
|
|
||||||
InFile::new(file_id, ast::AnyHasAttrs::new(map[id.local_id].to_node(&root)))
|
|
||||||
}
|
|
||||||
AttrDefId::StaticId(id) => any_has_attrs(db, id),
|
AttrDefId::StaticId(id) => any_has_attrs(db, id),
|
||||||
AttrDefId::ConstId(id) => any_has_attrs(db, id),
|
AttrDefId::ConstId(id) => any_has_attrs(db, id),
|
||||||
AttrDefId::TraitId(id) => any_has_attrs(db, id),
|
AttrDefId::TraitId(id) => any_has_attrs(db, id),
|
||||||
@ -676,20 +628,6 @@ fn attrs_from_item_tree_assoc<'db, N: ItemTreeNode>(
|
|||||||
attrs_from_item_tree(db, id)
|
attrs_from_item_tree(db, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn variants_attrs_source_map(
|
|
||||||
db: &dyn DefDatabase,
|
|
||||||
def: EnumId,
|
|
||||||
) -> Arc<ArenaMap<LocalEnumVariantId, AstPtr<ast::Variant>>> {
|
|
||||||
let mut res = ArenaMap::default();
|
|
||||||
let child_source = def.child_source(db);
|
|
||||||
|
|
||||||
for (idx, variant) in child_source.value.iter() {
|
|
||||||
res.insert(idx, AstPtr::new(variant));
|
|
||||||
}
|
|
||||||
|
|
||||||
Arc::new(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn fields_attrs_source_map(
|
pub(crate) fn fields_attrs_source_map(
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
def: VariantId,
|
def: VariantId,
|
||||||
|
@ -26,7 +26,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
nameres::DefMap,
|
nameres::DefMap,
|
||||||
path::{ModPath, Path},
|
path::{ModPath, Path},
|
||||||
src::{HasChildSource, HasSource},
|
src::HasSource,
|
||||||
BlockId, DefWithBodyId, HasModule, Lookup,
|
BlockId, DefWithBodyId, HasModule, Lookup,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -160,8 +160,9 @@ impl Body {
|
|||||||
src.map(|it| it.body())
|
src.map(|it| it.body())
|
||||||
}
|
}
|
||||||
DefWithBodyId::VariantId(v) => {
|
DefWithBodyId::VariantId(v) => {
|
||||||
let src = v.parent.child_source(db);
|
let s = v.lookup(db);
|
||||||
src.map(|it| it[v.local_id].expr())
|
let src = s.source(db);
|
||||||
|
src.map(|it| it.expr())
|
||||||
}
|
}
|
||||||
DefWithBodyId::InTypeConstId(c) => c.lookup(db).id.map(|_| c.source(db).expr()),
|
DefWithBodyId::InTypeConstId(c) => c.lookup(db).id.map(|_| c.source(db).expr()),
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use syntax::ast::HasName;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
hir::{
|
hir::{
|
||||||
@ -42,12 +41,13 @@ pub(super) fn print_body_hir(db: &dyn DefDatabase, body: &Body, owner: DefWithBo
|
|||||||
}
|
}
|
||||||
DefWithBodyId::InTypeConstId(_) => format!("In type const = "),
|
DefWithBodyId::InTypeConstId(_) => format!("In type const = "),
|
||||||
DefWithBodyId::VariantId(it) => {
|
DefWithBodyId::VariantId(it) => {
|
||||||
let src = it.parent.child_source(db);
|
let loc = it.lookup(db);
|
||||||
let variant = &src.value[it.local_id];
|
let enum_loc = loc.parent.lookup(db);
|
||||||
match &variant.name() {
|
format!(
|
||||||
Some(name) => name.to_string(),
|
"enum {}::{}",
|
||||||
None => "_".to_string(),
|
enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db.upcast()),
|
||||||
}
|
loc.id.item_tree(db)[loc.id.value].name.display(db.upcast()),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -13,8 +13,8 @@ use crate::{
|
|||||||
item_scope::ItemScope,
|
item_scope::ItemScope,
|
||||||
nameres::DefMap,
|
nameres::DefMap,
|
||||||
src::{HasChildSource, HasSource},
|
src::{HasChildSource, HasSource},
|
||||||
AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FieldId, ImplId,
|
AdtId, AssocItemId, DefWithBodyId, EnumId, ExternCrateId, FieldId, ImplId, Lookup, MacroId,
|
||||||
Lookup, MacroId, ModuleDefId, ModuleId, TraitId, UseId, VariantId,
|
ModuleDefId, ModuleId, TraitId, UseId, VariantId,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait ChildBySource {
|
pub trait ChildBySource {
|
||||||
@ -205,12 +205,18 @@ impl ChildBySource for VariantId {
|
|||||||
|
|
||||||
impl ChildBySource for EnumId {
|
impl ChildBySource for EnumId {
|
||||||
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, _: HirFileId) {
|
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, _: HirFileId) {
|
||||||
let arena_map = self.child_source(db);
|
let loc = &self.lookup(db);
|
||||||
let arena_map = arena_map.as_ref();
|
|
||||||
for (local_id, source) in arena_map.value.iter() {
|
let tree = loc.id.item_tree(db);
|
||||||
let id = EnumVariantId { parent: *self, local_id };
|
let ast_id_map = db.ast_id_map(loc.id.file_id());
|
||||||
res[keys::VARIANT].insert(source.clone(), id)
|
let root = db.parse_or_expand(loc.id.file_id());
|
||||||
}
|
|
||||||
|
db.enum_data(*self).variants.iter().for_each(|&(variant, _)| {
|
||||||
|
res[keys::VARIANT].insert(
|
||||||
|
ast_id_map.get(tree[variant.lookup(db).id.value].ast_id).to_node(&root),
|
||||||
|
variant,
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,8 +28,7 @@ use crate::{
|
|||||||
tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree},
|
tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree},
|
||||||
type_ref::TypeRef,
|
type_ref::TypeRef,
|
||||||
visibility::RawVisibility,
|
visibility::RawVisibility,
|
||||||
EnumId, EnumLoc, LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StructId,
|
EnumId, EnumVariantId, LocalFieldId, LocalModuleId, Lookup, StructId, UnionId, VariantId,
|
||||||
UnionId, VariantId,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Note that we use `StructData` for unions as well!
|
/// Note that we use `StructData` for unions as well!
|
||||||
@ -65,7 +64,7 @@ bitflags! {
|
|||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct EnumData {
|
pub struct EnumData {
|
||||||
pub name: Name,
|
pub name: Name,
|
||||||
pub variants: Arena<EnumVariantData>,
|
pub variants: Box<[(EnumVariantId, Name)]>,
|
||||||
pub repr: Option<ReprOptions>,
|
pub repr: Option<ReprOptions>,
|
||||||
pub visibility: RawVisibility,
|
pub visibility: RawVisibility,
|
||||||
pub rustc_has_incoherent_inherent_impls: bool,
|
pub rustc_has_incoherent_inherent_impls: bool,
|
||||||
@ -75,7 +74,6 @@ pub struct EnumData {
|
|||||||
pub struct EnumVariantData {
|
pub struct EnumVariantData {
|
||||||
pub name: Name,
|
pub name: Name,
|
||||||
pub variant_data: Arc<VariantData>,
|
pub variant_data: Arc<VariantData>,
|
||||||
pub tree_id: la_arena::Idx<crate::item_tree::Variant>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
@ -287,17 +285,9 @@ impl StructData {
|
|||||||
|
|
||||||
impl EnumData {
|
impl EnumData {
|
||||||
pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> {
|
pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> {
|
||||||
db.enum_data_with_diagnostics(e).0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn enum_data_with_diagnostics_query(
|
|
||||||
db: &dyn DefDatabase,
|
|
||||||
e: EnumId,
|
|
||||||
) -> (Arc<EnumData>, Arc<[DefDiagnostic]>) {
|
|
||||||
let loc = e.lookup(db);
|
let loc = e.lookup(db);
|
||||||
let krate = loc.container.krate;
|
let krate = loc.container.krate;
|
||||||
let item_tree = loc.id.item_tree(db);
|
let item_tree = loc.id.item_tree(db);
|
||||||
let cfg_options = db.crate_graph()[krate].cfg_options.clone();
|
|
||||||
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
|
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
|
||||||
let rustc_has_incoherent_inherent_impls = item_tree
|
let rustc_has_incoherent_inherent_impls = item_tree
|
||||||
.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into())
|
.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into())
|
||||||
@ -305,53 +295,21 @@ impl EnumData {
|
|||||||
.exists();
|
.exists();
|
||||||
|
|
||||||
let enum_ = &item_tree[loc.id.value];
|
let enum_ = &item_tree[loc.id.value];
|
||||||
let mut variants = Arena::new();
|
|
||||||
let mut diagnostics = Vec::new();
|
|
||||||
for tree_id in enum_.variants.clone() {
|
|
||||||
let attrs = item_tree.attrs(db, krate, tree_id.into());
|
|
||||||
let var = &item_tree[tree_id];
|
|
||||||
if attrs.is_cfg_enabled(&cfg_options) {
|
|
||||||
let (var_data, field_diagnostics) = lower_fields(
|
|
||||||
db,
|
|
||||||
krate,
|
|
||||||
loc.id.file_id(),
|
|
||||||
loc.container.local_id,
|
|
||||||
&item_tree,
|
|
||||||
&cfg_options,
|
|
||||||
&var.fields,
|
|
||||||
Some(enum_.visibility),
|
|
||||||
);
|
|
||||||
diagnostics.extend(field_diagnostics);
|
|
||||||
|
|
||||||
variants.alloc(EnumVariantData {
|
|
||||||
name: var.name.clone(),
|
|
||||||
variant_data: Arc::new(var_data),
|
|
||||||
tree_id,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
diagnostics.push(DefDiagnostic::unconfigured_code(
|
|
||||||
loc.container.local_id,
|
|
||||||
InFile::new(loc.id.file_id(), var.ast_id.erase()),
|
|
||||||
attrs.cfg().unwrap(),
|
|
||||||
cfg_options.clone(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(
|
|
||||||
Arc::new(EnumData {
|
Arc::new(EnumData {
|
||||||
name: enum_.name.clone(),
|
name: enum_.name.clone(),
|
||||||
variants,
|
variants: loc.container.def_map(db)[loc.container.local_id].scope.enums[&e]
|
||||||
|
.iter()
|
||||||
|
.map(|&id| (id, item_tree[id.lookup(db).id.value].name.clone()))
|
||||||
|
.collect(),
|
||||||
repr,
|
repr,
|
||||||
visibility: item_tree[enum_.visibility].clone(),
|
visibility: item_tree[enum_.visibility].clone(),
|
||||||
rustc_has_incoherent_inherent_impls,
|
rustc_has_incoherent_inherent_impls,
|
||||||
}),
|
})
|
||||||
diagnostics.into(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> {
|
pub fn variant(&self, name: &Name) -> Option<EnumVariantId> {
|
||||||
let (id, _) = self.variants.iter().find(|(_id, data)| &data.name == name)?;
|
let &(id, _) = self.variants.iter().find(|(_id, n)| n == name)?;
|
||||||
Some(id)
|
Some(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,82 +321,46 @@ impl EnumData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasChildSource<LocalEnumVariantId> for EnumId {
|
impl EnumVariantData {
|
||||||
type Value = ast::Variant;
|
pub(crate) fn enum_variant_data_query(
|
||||||
fn child_source(
|
|
||||||
&self,
|
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
) -> InFile<ArenaMap<LocalEnumVariantId, Self::Value>> {
|
e: EnumVariantId,
|
||||||
let loc = &self.lookup(db);
|
) -> Arc<EnumVariantData> {
|
||||||
let src = loc.source(db);
|
db.enum_variant_data_with_diagnostics(e).0
|
||||||
let mut trace = Trace::new_for_map();
|
|
||||||
lower_enum(db, &mut trace, &src, loc);
|
|
||||||
src.with_value(trace.into_map())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_enum(
|
pub(crate) fn enum_variant_data_with_diagnostics_query(
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
trace: &mut Trace<EnumVariantData, ast::Variant>,
|
e: EnumVariantId,
|
||||||
ast: &InFile<ast::Enum>,
|
) -> (Arc<EnumVariantData>, Arc<[DefDiagnostic]>) {
|
||||||
loc: &EnumLoc,
|
let loc = e.lookup(db);
|
||||||
) {
|
|
||||||
let item_tree = loc.id.item_tree(db);
|
|
||||||
let krate = loc.container.krate;
|
let krate = loc.container.krate;
|
||||||
|
let item_tree = loc.id.item_tree(db);
|
||||||
|
let cfg_options = db.crate_graph()[krate].cfg_options.clone();
|
||||||
|
let variant = &item_tree[loc.id.value];
|
||||||
|
|
||||||
let item_tree_variants = item_tree[loc.id.value].variants.clone();
|
let (var_data, field_diagnostics) = lower_fields(
|
||||||
|
|
||||||
let cfg_options = &db.crate_graph()[krate].cfg_options;
|
|
||||||
let variants = ast
|
|
||||||
.value
|
|
||||||
.variant_list()
|
|
||||||
.into_iter()
|
|
||||||
.flat_map(|it| it.variants())
|
|
||||||
.zip(item_tree_variants)
|
|
||||||
.filter(|&(_, item_tree_id)| {
|
|
||||||
item_tree.attrs(db, krate, item_tree_id.into()).is_cfg_enabled(cfg_options)
|
|
||||||
});
|
|
||||||
for (var, item_tree_id) in variants {
|
|
||||||
trace.alloc(
|
|
||||||
|| var.clone(),
|
|
||||||
|| EnumVariantData {
|
|
||||||
name: var.name().map_or_else(Name::missing, |it| it.as_name()),
|
|
||||||
variant_data: Arc::new(VariantData::new(
|
|
||||||
db,
|
db,
|
||||||
ast.with_value(var.kind()),
|
krate,
|
||||||
loc.container,
|
loc.id.file_id(),
|
||||||
|
loc.container.local_id,
|
||||||
&item_tree,
|
&item_tree,
|
||||||
item_tree_id,
|
&cfg_options,
|
||||||
)),
|
&variant.fields,
|
||||||
tree_id: item_tree_id,
|
Some(item_tree[loc.parent.lookup(db).id.value].visibility),
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
(
|
||||||
|
Arc::new(EnumVariantData {
|
||||||
|
name: variant.name.clone(),
|
||||||
|
variant_data: Arc::new(var_data),
|
||||||
|
}),
|
||||||
|
field_diagnostics.into(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VariantData {
|
impl VariantData {
|
||||||
fn new(
|
|
||||||
db: &dyn DefDatabase,
|
|
||||||
flavor: InFile<ast::StructKind>,
|
|
||||||
module_id: ModuleId,
|
|
||||||
item_tree: &ItemTree,
|
|
||||||
variant: la_arena::Idx<crate::item_tree::Variant>,
|
|
||||||
) -> Self {
|
|
||||||
let mut trace = Trace::new_for_arena();
|
|
||||||
match lower_struct(
|
|
||||||
db,
|
|
||||||
&mut trace,
|
|
||||||
&flavor,
|
|
||||||
module_id.krate,
|
|
||||||
item_tree,
|
|
||||||
&item_tree[variant].fields,
|
|
||||||
) {
|
|
||||||
StructKind::Tuple => VariantData::Tuple(trace.into_arena()),
|
|
||||||
StructKind::Record => VariantData::Record(trace.into_arena()),
|
|
||||||
StructKind::Unit => VariantData::Unit,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fields(&self) -> &Arena<FieldData> {
|
pub fn fields(&self) -> &Arena<FieldData> {
|
||||||
const EMPTY: &Arena<FieldData> = &Arena::new();
|
const EMPTY: &Arena<FieldData> = &Arena::new();
|
||||||
match &self {
|
match &self {
|
||||||
@ -468,14 +390,13 @@ impl HasChildSource<LocalFieldId> for VariantId {
|
|||||||
let item_tree;
|
let item_tree;
|
||||||
let (src, fields, container) = match *self {
|
let (src, fields, container) = match *self {
|
||||||
VariantId::EnumVariantId(it) => {
|
VariantId::EnumVariantId(it) => {
|
||||||
// I don't really like the fact that we call into parent source
|
let lookup = it.lookup(db);
|
||||||
// here, this might add to more queries then necessary.
|
|
||||||
let lookup = it.parent.lookup(db);
|
|
||||||
item_tree = lookup.id.item_tree(db);
|
item_tree = lookup.id.item_tree(db);
|
||||||
let src = it.parent.child_source(db);
|
(
|
||||||
let tree_id = db.enum_data(it.parent).variants[it.local_id].tree_id;
|
lookup.source(db).map(|it| it.kind()),
|
||||||
let fields = &item_tree[tree_id].fields;
|
&item_tree[lookup.id.value].fields,
|
||||||
(src.map(|map| map[it.local_id].kind()), fields, lookup.container)
|
lookup.container,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
VariantId::StructId(it) => {
|
VariantId::StructId(it) => {
|
||||||
let lookup = it.lookup(db);
|
let lookup = it.lookup(db);
|
||||||
|
@ -11,7 +11,7 @@ use crate::{
|
|||||||
attr::{Attrs, AttrsWithOwner},
|
attr::{Attrs, AttrsWithOwner},
|
||||||
body::{scope::ExprScopes, Body, BodySourceMap},
|
body::{scope::ExprScopes, Body, BodySourceMap},
|
||||||
data::{
|
data::{
|
||||||
adt::{EnumData, StructData},
|
adt::{EnumData, EnumVariantData, StructData},
|
||||||
ConstData, ExternCrateDeclData, FunctionData, ImplData, Macro2Data, MacroRulesData,
|
ConstData, ExternCrateDeclData, FunctionData, ImplData, Macro2Data, MacroRulesData,
|
||||||
ProcMacroData, StaticData, TraitAliasData, TraitData, TypeAliasData,
|
ProcMacroData, StaticData, TraitAliasData, TraitData, TypeAliasData,
|
||||||
},
|
},
|
||||||
@ -22,12 +22,12 @@ use crate::{
|
|||||||
nameres::{diagnostics::DefDiagnostic, DefMap},
|
nameres::{diagnostics::DefDiagnostic, DefMap},
|
||||||
visibility::{self, Visibility},
|
visibility::{self, Visibility},
|
||||||
AttrDefId, BlockId, BlockLoc, ConstBlockId, ConstBlockLoc, ConstId, ConstLoc, DefWithBodyId,
|
AttrDefId, BlockId, BlockLoc, ConstBlockId, ConstBlockLoc, ConstId, ConstLoc, DefWithBodyId,
|
||||||
EnumId, EnumLoc, ExternBlockId, ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId,
|
EnumId, EnumLoc, EnumVariantId, EnumVariantLoc, ExternBlockId, ExternBlockLoc, ExternCrateId,
|
||||||
FunctionLoc, GenericDefId, ImplId, ImplLoc, InTypeConstId, InTypeConstLoc, LocalEnumVariantId,
|
ExternCrateLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, InTypeConstId,
|
||||||
LocalFieldId, Macro2Id, Macro2Loc, MacroId, MacroRulesId, MacroRulesLoc, MacroRulesLocFlags,
|
InTypeConstLoc, LocalFieldId, Macro2Id, Macro2Loc, MacroId, MacroRulesId, MacroRulesLoc,
|
||||||
ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc, TraitAliasId,
|
MacroRulesLocFlags, ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc,
|
||||||
TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, UseId, UseLoc,
|
TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc,
|
||||||
VariantId,
|
UseId, UseLoc, VariantId,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[salsa::query_group(InternDatabaseStorage)]
|
#[salsa::query_group(InternDatabaseStorage)]
|
||||||
@ -46,6 +46,8 @@ pub trait InternDatabase: SourceDatabase {
|
|||||||
#[salsa::interned]
|
#[salsa::interned]
|
||||||
fn intern_enum(&self, loc: EnumLoc) -> EnumId;
|
fn intern_enum(&self, loc: EnumLoc) -> EnumId;
|
||||||
#[salsa::interned]
|
#[salsa::interned]
|
||||||
|
fn intern_enum_variant(&self, loc: EnumVariantLoc) -> EnumVariantId;
|
||||||
|
#[salsa::interned]
|
||||||
fn intern_const(&self, loc: ConstLoc) -> ConstId;
|
fn intern_const(&self, loc: ConstLoc) -> ConstId;
|
||||||
#[salsa::interned]
|
#[salsa::interned]
|
||||||
fn intern_static(&self, loc: StaticLoc) -> StaticId;
|
fn intern_static(&self, loc: StaticLoc) -> StaticId;
|
||||||
@ -131,8 +133,14 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
|
|||||||
#[salsa::invoke(EnumData::enum_data_query)]
|
#[salsa::invoke(EnumData::enum_data_query)]
|
||||||
fn enum_data(&self, e: EnumId) -> Arc<EnumData>;
|
fn enum_data(&self, e: EnumId) -> Arc<EnumData>;
|
||||||
|
|
||||||
#[salsa::invoke(EnumData::enum_data_with_diagnostics_query)]
|
#[salsa::invoke(EnumVariantData::enum_variant_data_query)]
|
||||||
fn enum_data_with_diagnostics(&self, e: EnumId) -> (Arc<EnumData>, Arc<[DefDiagnostic]>);
|
fn enum_variant_data(&self, id: EnumVariantId) -> Arc<EnumVariantData>;
|
||||||
|
|
||||||
|
#[salsa::invoke(EnumVariantData::enum_variant_data_with_diagnostics_query)]
|
||||||
|
fn enum_variant_data_with_diagnostics(
|
||||||
|
&self,
|
||||||
|
id: EnumVariantId,
|
||||||
|
) -> (Arc<EnumVariantData>, Arc<[DefDiagnostic]>);
|
||||||
|
|
||||||
#[salsa::invoke(ImplData::impl_data_query)]
|
#[salsa::invoke(ImplData::impl_data_query)]
|
||||||
fn impl_data(&self, e: ImplId) -> Arc<ImplData>;
|
fn impl_data(&self, e: ImplId) -> Arc<ImplData>;
|
||||||
@ -189,18 +197,9 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
|
|||||||
|
|
||||||
// region:attrs
|
// region:attrs
|
||||||
|
|
||||||
#[salsa::invoke(Attrs::variants_attrs_query)]
|
|
||||||
fn variants_attrs(&self, def: EnumId) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>>;
|
|
||||||
|
|
||||||
#[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>>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::attr::variants_attrs_source_map)]
|
|
||||||
fn variants_attrs_source_map(
|
|
||||||
&self,
|
|
||||||
def: EnumId,
|
|
||||||
) -> Arc<ArenaMap<LocalEnumVariantId, AstPtr<ast::Variant>>>;
|
|
||||||
|
|
||||||
#[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,
|
||||||
|
@ -2,7 +2,10 @@
|
|||||||
|
|
||||||
use std::{cmp::Ordering, iter};
|
use std::{cmp::Ordering, iter};
|
||||||
|
|
||||||
use hir_expand::name::{known, AsName, Name};
|
use hir_expand::{
|
||||||
|
name::{known, AsName, Name},
|
||||||
|
Lookup,
|
||||||
|
};
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -139,9 +142,10 @@ fn find_path_inner(ctx: FindPathCtx<'_>, item: ItemInNs, from: ModuleId) -> Opti
|
|||||||
|
|
||||||
if let Some(ModuleDefId::EnumVariantId(variant)) = item.as_module_def_id() {
|
if let Some(ModuleDefId::EnumVariantId(variant)) = item.as_module_def_id() {
|
||||||
// - if the item is an enum variant, refer to it via the enum
|
// - if the item is an enum variant, refer to it via the enum
|
||||||
if let Some(mut path) = find_path_inner(ctx, ItemInNs::Types(variant.parent.into()), from) {
|
if let Some(mut path) =
|
||||||
let data = ctx.db.enum_data(variant.parent);
|
find_path_inner(ctx, ItemInNs::Types(variant.lookup(ctx.db).parent.into()), from)
|
||||||
path.push_segment(data.variants[variant.local_id].name.clone());
|
{
|
||||||
|
path.push_segment(ctx.db.enum_variant_data(variant).name.clone());
|
||||||
return Some(path);
|
return Some(path);
|
||||||
}
|
}
|
||||||
// If this doesn't work, it seems we have no way of referring to the
|
// If this doesn't work, it seems we have no way of referring to the
|
||||||
|
@ -18,8 +18,8 @@ use crate::{
|
|||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
per_ns::PerNs,
|
per_ns::PerNs,
|
||||||
visibility::{Visibility, VisibilityExplicity},
|
visibility::{Visibility, VisibilityExplicity},
|
||||||
AdtId, BuiltinType, ConstId, ExternCrateId, HasModule, ImplId, LocalModuleId, Lookup, MacroId,
|
AdtId, BuiltinType, ConstId, EnumId, EnumVariantId, ExternCrateId, HasModule, ImplId,
|
||||||
ModuleDefId, ModuleId, TraitId, UseId,
|
LocalModuleId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId, UseId,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
@ -79,6 +79,7 @@ pub struct ItemScope {
|
|||||||
/// declared.
|
/// declared.
|
||||||
declarations: Vec<ModuleDefId>,
|
declarations: Vec<ModuleDefId>,
|
||||||
|
|
||||||
|
pub enums: FxHashMap<EnumId, Box<[EnumVariantId]>>,
|
||||||
impls: Vec<ImplId>,
|
impls: Vec<ImplId>,
|
||||||
unnamed_consts: Vec<ConstId>,
|
unnamed_consts: Vec<ConstId>,
|
||||||
/// Traits imported via `use Trait as _;`.
|
/// Traits imported via `use Trait as _;`.
|
||||||
@ -718,6 +719,7 @@ impl ItemScope {
|
|||||||
use_imports_types,
|
use_imports_types,
|
||||||
use_imports_macros,
|
use_imports_macros,
|
||||||
macro_invocations,
|
macro_invocations,
|
||||||
|
enums,
|
||||||
} = self;
|
} = self;
|
||||||
types.shrink_to_fit();
|
types.shrink_to_fit();
|
||||||
values.shrink_to_fit();
|
values.shrink_to_fit();
|
||||||
@ -736,6 +738,7 @@ impl ItemScope {
|
|||||||
extern_crate_decls.shrink_to_fit();
|
extern_crate_decls.shrink_to_fit();
|
||||||
use_decls.shrink_to_fit();
|
use_decls.shrink_to_fit();
|
||||||
macro_invocations.shrink_to_fit();
|
macro_invocations.shrink_to_fit();
|
||||||
|
enums.shrink_to_fit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ mod tests;
|
|||||||
use std::{
|
use std::{
|
||||||
fmt::{self, Debug},
|
fmt::{self, Debug},
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
ops::Index,
|
ops::{Index, Range},
|
||||||
};
|
};
|
||||||
|
|
||||||
use ast::{AstNode, HasName, StructKind};
|
use ast::{AstNode, HasName, StructKind};
|
||||||
@ -308,7 +308,7 @@ pub enum AttrOwner {
|
|||||||
/// Inner attributes of the source file.
|
/// Inner attributes of the source file.
|
||||||
TopLevel,
|
TopLevel,
|
||||||
|
|
||||||
Variant(Idx<Variant>),
|
Variant(FileItemTreeId<Variant>),
|
||||||
Field(Idx<Field>),
|
Field(Idx<Field>),
|
||||||
Param(Idx<Param>),
|
Param(Idx<Param>),
|
||||||
TypeOrConstParamData(Idx<TypeOrConstParamData>),
|
TypeOrConstParamData(Idx<TypeOrConstParamData>),
|
||||||
@ -329,7 +329,7 @@ macro_rules! from_attrs {
|
|||||||
|
|
||||||
from_attrs!(
|
from_attrs!(
|
||||||
ModItem(ModItem),
|
ModItem(ModItem),
|
||||||
Variant(Idx<Variant>),
|
Variant(FileItemTreeId<Variant>),
|
||||||
Field(Idx<Field>),
|
Field(Idx<Field>),
|
||||||
Param(Idx<Param>),
|
Param(Idx<Param>),
|
||||||
TypeOrConstParamData(Idx<TypeOrConstParamData>),
|
TypeOrConstParamData(Idx<TypeOrConstParamData>),
|
||||||
@ -352,35 +352,44 @@ pub trait ItemTreeNode: Clone {
|
|||||||
fn id_to_mod_item(id: FileItemTreeId<Self>) -> ModItem;
|
fn id_to_mod_item(id: FileItemTreeId<Self>) -> ModItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FileItemTreeId<N: ItemTreeNode>(Idx<N>);
|
pub struct FileItemTreeId<N>(Idx<N>);
|
||||||
|
|
||||||
impl<N: ItemTreeNode> FileItemTreeId<N> {
|
impl<N> FileItemTreeId<N> {
|
||||||
|
pub fn range_iter(range: Range<Self>) -> impl Iterator<Item = Self> {
|
||||||
|
(range.start.index().into_raw().into_u32()..range.end.index().into_raw().into_u32())
|
||||||
|
.map(RawIdx::from_u32)
|
||||||
|
.map(Idx::from_raw)
|
||||||
|
.map(Self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N> FileItemTreeId<N> {
|
||||||
pub fn index(&self) -> Idx<N> {
|
pub fn index(&self) -> Idx<N> {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: ItemTreeNode> Clone for FileItemTreeId<N> {
|
impl<N> Clone for FileItemTreeId<N> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self(self.0)
|
Self(self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<N: ItemTreeNode> Copy for FileItemTreeId<N> {}
|
impl<N> Copy for FileItemTreeId<N> {}
|
||||||
|
|
||||||
impl<N: ItemTreeNode> PartialEq for FileItemTreeId<N> {
|
impl<N> PartialEq for FileItemTreeId<N> {
|
||||||
fn eq(&self, other: &FileItemTreeId<N>) -> bool {
|
fn eq(&self, other: &FileItemTreeId<N>) -> bool {
|
||||||
self.0 == other.0
|
self.0 == other.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<N: ItemTreeNode> Eq for FileItemTreeId<N> {}
|
impl<N> Eq for FileItemTreeId<N> {}
|
||||||
|
|
||||||
impl<N: ItemTreeNode> Hash for FileItemTreeId<N> {
|
impl<N> Hash for FileItemTreeId<N> {
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
self.0.hash(state)
|
self.0.hash(state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: ItemTreeNode> fmt::Debug for FileItemTreeId<N> {
|
impl<N> fmt::Debug for FileItemTreeId<N> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
self.0.fmt(f)
|
self.0.fmt(f)
|
||||||
}
|
}
|
||||||
@ -415,12 +424,12 @@ impl TreeId {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ItemTreeId<N: ItemTreeNode> {
|
pub struct ItemTreeId<N> {
|
||||||
tree: TreeId,
|
tree: TreeId,
|
||||||
pub value: FileItemTreeId<N>,
|
pub value: FileItemTreeId<N>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: ItemTreeNode> ItemTreeId<N> {
|
impl<N> ItemTreeId<N> {
|
||||||
pub fn new(tree: TreeId, idx: FileItemTreeId<N>) -> Self {
|
pub fn new(tree: TreeId, idx: FileItemTreeId<N>) -> Self {
|
||||||
Self { tree, value: idx }
|
Self { tree, value: idx }
|
||||||
}
|
}
|
||||||
@ -438,22 +447,22 @@ impl<N: ItemTreeNode> ItemTreeId<N> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: ItemTreeNode> Copy for ItemTreeId<N> {}
|
impl<N> Copy for ItemTreeId<N> {}
|
||||||
impl<N: ItemTreeNode> Clone for ItemTreeId<N> {
|
impl<N> Clone for ItemTreeId<N> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
*self
|
*self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: ItemTreeNode> PartialEq for ItemTreeId<N> {
|
impl<N> PartialEq for ItemTreeId<N> {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
self.tree == other.tree && self.value == other.value
|
self.tree == other.tree && self.value == other.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: ItemTreeNode> Eq for ItemTreeId<N> {}
|
impl<N> Eq for ItemTreeId<N> {}
|
||||||
|
|
||||||
impl<N: ItemTreeNode> Hash for ItemTreeId<N> {
|
impl<N> Hash for ItemTreeId<N> {
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
self.tree.hash(state);
|
self.tree.hash(state);
|
||||||
self.value.hash(state);
|
self.value.hash(state);
|
||||||
@ -568,6 +577,13 @@ impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Index<FileItemTreeId<Variant>> for ItemTree {
|
||||||
|
type Output = Variant;
|
||||||
|
fn index(&self, id: FileItemTreeId<Variant>) -> &Variant {
|
||||||
|
&self[id.index()]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
pub struct Use {
|
pub struct Use {
|
||||||
pub visibility: RawVisibilityId,
|
pub visibility: RawVisibilityId,
|
||||||
@ -678,7 +694,7 @@ pub struct Enum {
|
|||||||
pub name: Name,
|
pub name: Name,
|
||||||
pub visibility: RawVisibilityId,
|
pub visibility: RawVisibilityId,
|
||||||
pub generic_params: Interned<GenericParams>,
|
pub generic_params: Interned<GenericParams>,
|
||||||
pub variants: IdxRange<Variant>,
|
pub variants: Range<FileItemTreeId<Variant>>,
|
||||||
pub ast_id: FileAstId<ast::Enum>,
|
pub ast_id: FileAstId<ast::Enum>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,25 +253,27 @@ impl<'a> Ctx<'a> {
|
|||||||
let generic_params = self.lower_generic_params(HasImplicitSelf::No, enum_);
|
let generic_params = self.lower_generic_params(HasImplicitSelf::No, enum_);
|
||||||
let variants = match &enum_.variant_list() {
|
let variants = match &enum_.variant_list() {
|
||||||
Some(variant_list) => self.lower_variants(variant_list),
|
Some(variant_list) => self.lower_variants(variant_list),
|
||||||
None => IdxRange::new(self.next_variant_idx()..self.next_variant_idx()),
|
None => {
|
||||||
|
FileItemTreeId(self.next_variant_idx())..FileItemTreeId(self.next_variant_idx())
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let res = Enum { name, visibility, generic_params, variants, ast_id };
|
let res = Enum { name, visibility, generic_params, variants, ast_id };
|
||||||
Some(id(self.data().enums.alloc(res)))
|
Some(id(self.data().enums.alloc(res)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_variants(&mut self, variants: &ast::VariantList) -> IdxRange<Variant> {
|
fn lower_variants(&mut self, variants: &ast::VariantList) -> Range<FileItemTreeId<Variant>> {
|
||||||
let start = self.next_variant_idx();
|
let start = self.next_variant_idx();
|
||||||
for variant in variants.variants() {
|
for variant in variants.variants() {
|
||||||
if let Some(data) = self.lower_variant(&variant) {
|
if let Some(data) = self.lower_variant(&variant) {
|
||||||
let idx = self.data().variants.alloc(data);
|
let idx = self.data().variants.alloc(data);
|
||||||
self.add_attrs(
|
self.add_attrs(
|
||||||
idx.into(),
|
FileItemTreeId(idx).into(),
|
||||||
RawAttrs::new(self.db.upcast(), &variant, self.span_map()),
|
RawAttrs::new(self.db.upcast(), &variant, self.span_map()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let end = self.next_variant_idx();
|
let end = self.next_variant_idx();
|
||||||
IdxRange::new(start..end)
|
FileItemTreeId(start)..FileItemTreeId(end)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_variant(&mut self, variant: &ast::Variant) -> Option<Variant> {
|
fn lower_variant(&mut self, variant: &ast::Variant) -> Option<Variant> {
|
||||||
|
@ -318,7 +318,7 @@ impl Printer<'_> {
|
|||||||
self.print_generic_params(generic_params);
|
self.print_generic_params(generic_params);
|
||||||
self.print_where_clause_and_opening_brace(generic_params);
|
self.print_where_clause_and_opening_brace(generic_params);
|
||||||
self.indented(|this| {
|
self.indented(|this| {
|
||||||
for variant in variants.clone() {
|
for variant in FileItemTreeId::range_iter(variants.clone()) {
|
||||||
let Variant { name, fields, ast_id: _ } = &this.tree[variant];
|
let Variant { name, fields, ast_id: _ } = &this.tree[variant];
|
||||||
this.print_attrs_of(variant, "\n");
|
this.print_attrs_of(variant, "\n");
|
||||||
w!(this, "{}", name.display(self.db.upcast()));
|
w!(this, "{}", name.display(self.db.upcast()));
|
||||||
|
@ -125,12 +125,8 @@ impl LangItems {
|
|||||||
}
|
}
|
||||||
ModuleDefId::AdtId(AdtId::EnumId(e)) => {
|
ModuleDefId::AdtId(AdtId::EnumId(e)) => {
|
||||||
lang_items.collect_lang_item(db, e, LangItemTarget::EnumId);
|
lang_items.collect_lang_item(db, e, LangItemTarget::EnumId);
|
||||||
db.enum_data(e).variants.iter().for_each(|(local_id, _)| {
|
module_data.scope.enums[&e].iter().for_each(|&id| {
|
||||||
lang_items.collect_lang_item(
|
lang_items.collect_lang_item(db, id, LangItemTarget::EnumVariant);
|
||||||
db,
|
|
||||||
EnumVariantId { parent: e, local_id },
|
|
||||||
LangItemTarget::EnumVariant,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ModuleDefId::AdtId(AdtId::StructId(s)) => {
|
ModuleDefId::AdtId(AdtId::StructId(s)) => {
|
||||||
|
@ -100,7 +100,7 @@ use crate::{
|
|||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
item_tree::{
|
item_tree::{
|
||||||
Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeNode, Macro2, MacroRules,
|
Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeNode, Macro2, MacroRules,
|
||||||
Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use,
|
Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, Variant,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -299,12 +299,15 @@ impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum);
|
|||||||
|
|
||||||
// FIXME: rename to `VariantId`, only enums can ave variants
|
// FIXME: rename to `VariantId`, only enums can ave variants
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct EnumVariantId {
|
pub struct EnumVariantId(salsa::InternId);
|
||||||
pub parent: EnumId,
|
|
||||||
pub local_id: LocalEnumVariantId,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type LocalEnumVariantId = Idx<data::adt::EnumVariantData>;
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub struct EnumVariantLoc {
|
||||||
|
pub container: ModuleId,
|
||||||
|
pub id: ItemTreeId<Variant>,
|
||||||
|
pub parent: EnumId,
|
||||||
|
}
|
||||||
|
impl_intern!(EnumVariantId, EnumVariantLoc, intern_enum_variant, lookup_intern_enum_variant);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct FieldId {
|
pub struct FieldId {
|
||||||
@ -953,23 +956,21 @@ impl VariantId {
|
|||||||
match self {
|
match self {
|
||||||
VariantId::StructId(it) => db.struct_data(it).variant_data.clone(),
|
VariantId::StructId(it) => db.struct_data(it).variant_data.clone(),
|
||||||
VariantId::UnionId(it) => db.union_data(it).variant_data.clone(),
|
VariantId::UnionId(it) => db.union_data(it).variant_data.clone(),
|
||||||
VariantId::EnumVariantId(it) => {
|
VariantId::EnumVariantId(it) => db.enum_variant_data(it).variant_data.clone(),
|
||||||
db.enum_data(it.parent).variants[it.local_id].variant_data.clone()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn file_id(self, db: &dyn DefDatabase) -> HirFileId {
|
pub fn file_id(self, db: &dyn DefDatabase) -> HirFileId {
|
||||||
match self {
|
match self {
|
||||||
VariantId::EnumVariantId(it) => it.parent.lookup(db).id.file_id(),
|
VariantId::EnumVariantId(it) => it.lookup(db).id.file_id(),
|
||||||
VariantId::StructId(it) => it.lookup(db).id.file_id(),
|
VariantId::StructId(it) => it.lookup(db).id.file_id(),
|
||||||
VariantId::UnionId(it) => it.lookup(db).id.file_id(),
|
VariantId::UnionId(it) => it.lookup(db).id.file_id(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn adt_id(self) -> AdtId {
|
pub fn adt_id(self, db: &dyn DefDatabase) -> AdtId {
|
||||||
match self {
|
match self {
|
||||||
VariantId::EnumVariantId(it) => it.parent.into(),
|
VariantId::EnumVariantId(it) => it.lookup(db).parent.into(),
|
||||||
VariantId::StructId(it) => it.into(),
|
VariantId::StructId(it) => it.into(),
|
||||||
VariantId::UnionId(it) => it.into(),
|
VariantId::UnionId(it) => it.into(),
|
||||||
}
|
}
|
||||||
@ -1016,7 +1017,7 @@ impl HasModule for ExternCrateId {
|
|||||||
impl HasModule for VariantId {
|
impl HasModule for VariantId {
|
||||||
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
|
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
|
||||||
match self {
|
match self {
|
||||||
VariantId::EnumVariantId(it) => it.parent.lookup(db).container,
|
VariantId::EnumVariantId(it) => it.lookup(db).container,
|
||||||
VariantId::StructId(it) => it.lookup(db).container,
|
VariantId::StructId(it) => it.lookup(db).container,
|
||||||
VariantId::UnionId(it) => it.lookup(db).container,
|
VariantId::UnionId(it) => it.lookup(db).container,
|
||||||
}
|
}
|
||||||
@ -1045,7 +1046,7 @@ impl HasModule for TypeOwnerId {
|
|||||||
TypeOwnerId::TraitAliasId(it) => it.lookup(db).container,
|
TypeOwnerId::TraitAliasId(it) => it.lookup(db).container,
|
||||||
TypeOwnerId::TypeAliasId(it) => it.lookup(db).module(db),
|
TypeOwnerId::TypeAliasId(it) => it.lookup(db).module(db),
|
||||||
TypeOwnerId::ImplId(it) => it.lookup(db).container,
|
TypeOwnerId::ImplId(it) => it.lookup(db).container,
|
||||||
TypeOwnerId::EnumVariantId(it) => it.parent.lookup(db).container,
|
TypeOwnerId::EnumVariantId(it) => it.lookup(db).container,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1056,7 +1057,7 @@ impl HasModule for DefWithBodyId {
|
|||||||
DefWithBodyId::FunctionId(it) => it.lookup(db).module(db),
|
DefWithBodyId::FunctionId(it) => it.lookup(db).module(db),
|
||||||
DefWithBodyId::StaticId(it) => it.lookup(db).module(db),
|
DefWithBodyId::StaticId(it) => it.lookup(db).module(db),
|
||||||
DefWithBodyId::ConstId(it) => it.lookup(db).module(db),
|
DefWithBodyId::ConstId(it) => it.lookup(db).module(db),
|
||||||
DefWithBodyId::VariantId(it) => it.parent.lookup(db).container,
|
DefWithBodyId::VariantId(it) => it.lookup(db).container,
|
||||||
DefWithBodyId::InTypeConstId(it) => it.lookup(db).owner.module(db),
|
DefWithBodyId::InTypeConstId(it) => it.lookup(db).owner.module(db),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1071,7 +1072,7 @@ impl HasModule for GenericDefId {
|
|||||||
GenericDefId::TraitAliasId(it) => it.lookup(db).container,
|
GenericDefId::TraitAliasId(it) => it.lookup(db).container,
|
||||||
GenericDefId::TypeAliasId(it) => it.lookup(db).module(db),
|
GenericDefId::TypeAliasId(it) => it.lookup(db).module(db),
|
||||||
GenericDefId::ImplId(it) => it.lookup(db).container,
|
GenericDefId::ImplId(it) => it.lookup(db).container,
|
||||||
GenericDefId::EnumVariantId(it) => it.parent.lookup(db).container,
|
GenericDefId::EnumVariantId(it) => it.lookup(db).container,
|
||||||
GenericDefId::ConstId(it) => it.lookup(db).module(db),
|
GenericDefId::ConstId(it) => it.lookup(db).module(db),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1098,7 +1099,7 @@ impl ModuleDefId {
|
|||||||
ModuleDefId::ModuleId(id) => *id,
|
ModuleDefId::ModuleId(id) => *id,
|
||||||
ModuleDefId::FunctionId(id) => id.lookup(db).module(db),
|
ModuleDefId::FunctionId(id) => id.lookup(db).module(db),
|
||||||
ModuleDefId::AdtId(id) => id.module(db),
|
ModuleDefId::AdtId(id) => id.module(db),
|
||||||
ModuleDefId::EnumVariantId(id) => id.parent.lookup(db).container,
|
ModuleDefId::EnumVariantId(id) => id.lookup(db).container,
|
||||||
ModuleDefId::ConstId(id) => id.lookup(db).container.module(db),
|
ModuleDefId::ConstId(id) => id.lookup(db).container.module(db),
|
||||||
ModuleDefId::StaticId(id) => id.lookup(db).module(db),
|
ModuleDefId::StaticId(id) => id.lookup(db).module(db),
|
||||||
ModuleDefId::TraitId(id) => id.lookup(db).container,
|
ModuleDefId::TraitId(id) => id.lookup(db).container,
|
||||||
@ -1117,7 +1118,7 @@ impl AttrDefId {
|
|||||||
AttrDefId::FieldId(it) => it.parent.module(db).krate,
|
AttrDefId::FieldId(it) => it.parent.module(db).krate,
|
||||||
AttrDefId::AdtId(it) => it.module(db).krate,
|
AttrDefId::AdtId(it) => it.module(db).krate,
|
||||||
AttrDefId::FunctionId(it) => it.lookup(db).module(db).krate,
|
AttrDefId::FunctionId(it) => it.lookup(db).module(db).krate,
|
||||||
AttrDefId::EnumVariantId(it) => it.parent.lookup(db).container.krate,
|
AttrDefId::EnumVariantId(it) => it.lookup(db).container.krate,
|
||||||
AttrDefId::StaticId(it) => it.lookup(db).module(db).krate,
|
AttrDefId::StaticId(it) => it.lookup(db).module(db).krate,
|
||||||
AttrDefId::ConstId(it) => it.lookup(db).module(db).krate,
|
AttrDefId::ConstId(it) => it.lookup(db).module(db).krate,
|
||||||
AttrDefId::TraitId(it) => it.lookup(db).container.krate,
|
AttrDefId::TraitId(it) => it.lookup(db).container.krate,
|
||||||
|
@ -23,7 +23,7 @@ use itertools::{izip, Itertools};
|
|||||||
use la_arena::Idx;
|
use la_arena::Idx;
|
||||||
use limit::Limit;
|
use limit::Limit;
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use span::{Span, SyntaxContextId};
|
use span::{ErasedFileAstId, Span, SyntaxContextId};
|
||||||
use stdx::always;
|
use stdx::always;
|
||||||
use syntax::{ast, SmolStr};
|
use syntax::{ast, SmolStr};
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
@ -51,7 +51,7 @@ use crate::{
|
|||||||
per_ns::PerNs,
|
per_ns::PerNs,
|
||||||
tt,
|
tt,
|
||||||
visibility::{RawVisibility, Visibility},
|
visibility::{RawVisibility, Visibility},
|
||||||
AdtId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, EnumVariantId,
|
AdtId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, EnumVariantLoc,
|
||||||
ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern,
|
ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern,
|
||||||
ItemContainerId, LocalModuleId, Lookup, Macro2Id, Macro2Loc, MacroExpander, MacroId,
|
ItemContainerId, LocalModuleId, Lookup, Macro2Id, Macro2Loc, MacroExpander, MacroId,
|
||||||
MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ModuleDefId, ModuleId, ProcMacroId,
|
MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ModuleDefId, ModuleId, ProcMacroId,
|
||||||
@ -980,24 +980,35 @@ impl DefCollector<'_> {
|
|||||||
cov_mark::hit!(glob_enum);
|
cov_mark::hit!(glob_enum);
|
||||||
// glob import from enum => just import all the variants
|
// glob import from enum => just import all the variants
|
||||||
|
|
||||||
// XXX: urgh, so this works by accident! Here, we look at
|
// We need to check if the def map the enum is from is us, then we can't
|
||||||
// the enum data, and, in theory, this might require us to
|
// call the def-map query since we are currently constructing it!
|
||||||
// look back at the crate_def_map, creating a cycle. For
|
let loc = e.lookup(self.db);
|
||||||
// example, `enum E { crate::some_macro!(); }`. Luckily, the
|
let tree = loc.id.item_tree(self.db);
|
||||||
// only kind of macro that is allowed inside enum is a
|
let current_def_map = self.def_map.krate == loc.container.krate
|
||||||
// `cfg_macro`, and we don't need to run name resolution for
|
&& self.def_map.block_id() == loc.container.block;
|
||||||
// it, but this is sheer luck!
|
let resolutions = if current_def_map {
|
||||||
let enum_data = self.db.enum_data(e);
|
self.def_map.modules[loc.container.local_id].scope.enums[&e]
|
||||||
let resolutions = enum_data
|
|
||||||
.variants
|
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(local_id, variant_data)| {
|
.map(|&variant| {
|
||||||
let name = variant_data.name.clone();
|
let name = tree[variant.lookup(self.db).id.value].name.clone();
|
||||||
let variant = EnumVariantId { parent: e, local_id };
|
let res =
|
||||||
let res = PerNs::both(variant.into(), variant.into(), vis, None);
|
PerNs::both(variant.into(), variant.into(), vis, None);
|
||||||
(Some(name), res)
|
(Some(name), res)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>()
|
||||||
|
} else {
|
||||||
|
loc.container.def_map(self.db).modules[loc.container.local_id]
|
||||||
|
.scope
|
||||||
|
.enums[&e]
|
||||||
|
.iter()
|
||||||
|
.map(|&variant| {
|
||||||
|
let name = tree[variant.lookup(self.db).id.value].name.clone();
|
||||||
|
let res =
|
||||||
|
PerNs::both(variant.into(), variant.into(), vis, None);
|
||||||
|
(Some(name), res)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
};
|
||||||
self.update(module_id, &resolutions, vis, Some(ImportType::Glob(id)));
|
self.update(module_id, &resolutions, vis, Some(ImportType::Glob(id)));
|
||||||
}
|
}
|
||||||
Some(d) => {
|
Some(d) => {
|
||||||
@ -1577,7 +1588,7 @@ impl ModCollector<'_, '_> {
|
|||||||
let attrs = self.item_tree.attrs(db, krate, item.into());
|
let attrs = self.item_tree.attrs(db, krate, item.into());
|
||||||
if let Some(cfg) = attrs.cfg() {
|
if let Some(cfg) = attrs.cfg() {
|
||||||
if !self.is_cfg_enabled(&cfg) {
|
if !self.is_cfg_enabled(&cfg) {
|
||||||
self.emit_unconfigured_diagnostic(item, &cfg);
|
self.emit_unconfigured_diagnostic(item.ast_id(self.item_tree).erase(), &cfg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1708,17 +1719,40 @@ impl ModCollector<'_, '_> {
|
|||||||
}
|
}
|
||||||
ModItem::Enum(id) => {
|
ModItem::Enum(id) => {
|
||||||
let it = &self.item_tree[id];
|
let it = &self.item_tree[id];
|
||||||
|
let enum_ =
|
||||||
|
EnumLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
|
||||||
|
.intern(db);
|
||||||
|
|
||||||
let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
|
let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
|
||||||
update_def(
|
update_def(self.def_collector, enum_.into(), &it.name, vis, false);
|
||||||
self.def_collector,
|
|
||||||
EnumLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
|
let variants = FileItemTreeId::range_iter(it.variants.clone())
|
||||||
.intern(db)
|
.filter_map(|variant| {
|
||||||
.into(),
|
let attrs = self.item_tree.attrs(db, krate, variant.into());
|
||||||
&it.name,
|
if let Some(cfg) = attrs.cfg() {
|
||||||
vis,
|
if !self.is_cfg_enabled(&cfg) {
|
||||||
false,
|
self.emit_unconfigured_diagnostic(
|
||||||
|
self.item_tree[variant.index()].ast_id.erase(),
|
||||||
|
&cfg,
|
||||||
);
|
);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(
|
||||||
|
EnumVariantLoc {
|
||||||
|
container: module,
|
||||||
|
id: ItemTreeId::new(self.tree_id, variant),
|
||||||
|
parent: enum_,
|
||||||
|
}
|
||||||
|
.intern(db),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
self.def_collector.def_map.modules[module_id]
|
||||||
|
.scope
|
||||||
|
.enums
|
||||||
|
.insert(enum_, variants);
|
||||||
}
|
}
|
||||||
ModItem::Const(id) => {
|
ModItem::Const(id) => {
|
||||||
let it = &self.item_tree[id];
|
let it = &self.item_tree[id];
|
||||||
@ -2360,10 +2394,8 @@ impl ModCollector<'_, '_> {
|
|||||||
self.def_collector.cfg_options.check(cfg) != Some(false)
|
self.def_collector.cfg_options.check(cfg) != Some(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_unconfigured_diagnostic(&mut self, item: ModItem, cfg: &CfgExpr) {
|
fn emit_unconfigured_diagnostic(&mut self, ast_id: ErasedFileAstId, cfg: &CfgExpr) {
|
||||||
let ast_id = item.ast_id(self.item_tree);
|
let ast_id = InFile::new(self.file_id(), ast_id);
|
||||||
|
|
||||||
let ast_id = InFile::new(self.file_id(), ast_id.erase());
|
|
||||||
self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
|
self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
|
||||||
self.module_id,
|
self.module_id,
|
||||||
ast_id,
|
ast_id,
|
||||||
|
@ -11,18 +11,18 @@
|
|||||||
//! `ReachedFixedPoint` signals about this.
|
//! `ReachedFixedPoint` signals about this.
|
||||||
|
|
||||||
use base_db::Edition;
|
use base_db::Edition;
|
||||||
use hir_expand::name::Name;
|
use hir_expand::{name::Name, Lookup};
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
data::adt::VariantData,
|
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
item_scope::{ImportOrExternCrate, BUILTIN_SCOPE},
|
item_scope::{ImportOrExternCrate, BUILTIN_SCOPE},
|
||||||
|
item_tree::Fields,
|
||||||
nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, MacroSubNs},
|
nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, MacroSubNs},
|
||||||
path::{ModPath, PathKind},
|
path::{ModPath, PathKind},
|
||||||
per_ns::PerNs,
|
per_ns::PerNs,
|
||||||
visibility::{RawVisibility, Visibility},
|
visibility::{RawVisibility, Visibility},
|
||||||
AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId,
|
AdtId, CrateId, LocalModuleId, ModuleDefId,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
@ -355,29 +355,55 @@ impl DefMap {
|
|||||||
ModuleDefId::AdtId(AdtId::EnumId(e)) => {
|
ModuleDefId::AdtId(AdtId::EnumId(e)) => {
|
||||||
// enum variant
|
// enum variant
|
||||||
cov_mark::hit!(can_import_enum_variant);
|
cov_mark::hit!(can_import_enum_variant);
|
||||||
let enum_data = db.enum_data(e);
|
|
||||||
match enum_data.variant(segment) {
|
let loc = e.lookup(db);
|
||||||
Some(local_id) => {
|
let tree = loc.id.item_tree(db);
|
||||||
let variant = EnumVariantId { parent: e, local_id };
|
let current_def_map =
|
||||||
match &*enum_data.variants[local_id].variant_data {
|
self.krate == loc.container.krate && self.block_id() == loc.container.block;
|
||||||
VariantData::Record(_) => {
|
let res = if current_def_map {
|
||||||
|
self.modules[loc.container.local_id].scope.enums[&e].iter().find_map(
|
||||||
|
|&variant| {
|
||||||
|
let variant_data = &tree[variant.lookup(db).id.value];
|
||||||
|
(variant_data.name == *segment).then(|| match variant_data.fields {
|
||||||
|
Fields::Record(_) => {
|
||||||
PerNs::types(variant.into(), Visibility::Public, None)
|
PerNs::types(variant.into(), Visibility::Public, None)
|
||||||
}
|
}
|
||||||
VariantData::Tuple(_) | VariantData::Unit => PerNs::both(
|
Fields::Tuple(_) | Fields::Unit => PerNs::both(
|
||||||
variant.into(),
|
variant.into(),
|
||||||
variant.into(),
|
variant.into(),
|
||||||
Visibility::Public,
|
Visibility::Public,
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
loc.container.def_map(db).modules[loc.container.local_id].scope.enums[&e]
|
||||||
|
.iter()
|
||||||
|
.find_map(|&variant| {
|
||||||
|
let variant_data = &tree[variant.lookup(db).id.value];
|
||||||
|
(variant_data.name == *segment).then(|| match variant_data.fields {
|
||||||
|
Fields::Record(_) => {
|
||||||
|
PerNs::types(variant.into(), Visibility::Public, None)
|
||||||
}
|
}
|
||||||
}
|
Fields::Tuple(_) | Fields::Unit => PerNs::both(
|
||||||
|
variant.into(),
|
||||||
|
variant.into(),
|
||||||
|
Visibility::Public,
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
};
|
||||||
|
match res {
|
||||||
|
Some(res) => res,
|
||||||
None => {
|
None => {
|
||||||
return ResolvePathResult::with(
|
return ResolvePathResult::with(
|
||||||
PerNs::types(e.into(), vis, imp),
|
PerNs::types(e.into(), vis, imp),
|
||||||
ReachedFixedPoint::Yes,
|
ReachedFixedPoint::Yes,
|
||||||
Some(i),
|
Some(i),
|
||||||
Some(self.krate),
|
Some(self.krate),
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,11 +39,9 @@ pub(crate) fn print_path(db: &dyn DefDatabase, path: &Path, buf: &mut dyn Write)
|
|||||||
LangItemTarget::Trait(it) => {
|
LangItemTarget::Trait(it) => {
|
||||||
write!(buf, "{}", db.trait_data(it).name.display(db.upcast()))?
|
write!(buf, "{}", db.trait_data(it).name.display(db.upcast()))?
|
||||||
}
|
}
|
||||||
LangItemTarget::EnumVariant(it) => write!(
|
LangItemTarget::EnumVariant(it) => {
|
||||||
buf,
|
write!(buf, "{}", db.enum_variant_data(it).name.display(db.upcast()))?
|
||||||
"{}",
|
}
|
||||||
db.enum_data(it.parent).variants[it.local_id].name.display(db.upcast())
|
|
||||||
)?,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(s) = s {
|
if let Some(s) = s {
|
||||||
|
@ -1111,7 +1111,7 @@ impl HasResolver for DefWithBodyId {
|
|||||||
DefWithBodyId::ConstId(c) => c.resolver(db),
|
DefWithBodyId::ConstId(c) => c.resolver(db),
|
||||||
DefWithBodyId::FunctionId(f) => f.resolver(db),
|
DefWithBodyId::FunctionId(f) => f.resolver(db),
|
||||||
DefWithBodyId::StaticId(s) => s.resolver(db),
|
DefWithBodyId::StaticId(s) => s.resolver(db),
|
||||||
DefWithBodyId::VariantId(v) => v.parent.resolver(db),
|
DefWithBodyId::VariantId(v) => v.resolver(db),
|
||||||
DefWithBodyId::InTypeConstId(c) => c.lookup(db).owner.resolver(db),
|
DefWithBodyId::InTypeConstId(c) => c.lookup(db).owner.resolver(db),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1137,7 +1137,7 @@ 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.parent.resolver(db),
|
GenericDefId::EnumVariantId(inner) => inner.resolver(db),
|
||||||
GenericDefId::ConstId(inner) => inner.resolver(db),
|
GenericDefId::ConstId(inner) => inner.resolver(db),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1145,14 +1145,14 @@ impl HasResolver for GenericDefId {
|
|||||||
|
|
||||||
impl HasResolver for EnumVariantId {
|
impl HasResolver for EnumVariantId {
|
||||||
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
||||||
self.parent.resolver(db)
|
self.lookup(db).parent.resolver(db)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasResolver for VariantId {
|
impl HasResolver for VariantId {
|
||||||
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
||||||
match self {
|
match self {
|
||||||
VariantId::EnumVariantId(it) => it.parent.resolver(db),
|
VariantId::EnumVariantId(it) => it.resolver(db),
|
||||||
VariantId::StructId(it) => it.resolver(db),
|
VariantId::StructId(it) => it.resolver(db),
|
||||||
VariantId::UnionId(it) => it.resolver(db),
|
VariantId::UnionId(it) => it.resolver(db),
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,8 @@ use la_arena::ArenaMap;
|
|||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::DefDatabase, item_tree::ItemTreeNode, AssocItemLoc, ItemLoc, Lookup, Macro2Loc,
|
db::DefDatabase, item_tree::ItemTreeNode, AssocItemLoc, EnumVariantLoc, ItemLoc, Lookup,
|
||||||
MacroRulesLoc, ProcMacroLoc, UseId,
|
Macro2Loc, MacroRulesLoc, ProcMacroLoc, UseId,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait HasSource {
|
pub trait HasSource {
|
||||||
@ -40,6 +40,19 @@ impl<N: ItemTreeNode> HasSource for ItemLoc<N> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl HasSource for EnumVariantLoc {
|
||||||
|
type Value = ast::Variant;
|
||||||
|
|
||||||
|
fn source(&self, db: &dyn DefDatabase) -> InFile<ast::Variant> {
|
||||||
|
let tree = self.id.item_tree(db);
|
||||||
|
let ast_id_map = db.ast_id_map(self.id.file_id());
|
||||||
|
let root = db.parse_or_expand(self.id.file_id());
|
||||||
|
let node = &tree[self.id.value];
|
||||||
|
|
||||||
|
InFile::new(self.id.file_id(), ast_id_map.get(node.ast_id).to_node(&root))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl HasSource for Macro2Loc {
|
impl HasSource for Macro2Loc {
|
||||||
type Value = ast::MacroDef;
|
type Value = ast::MacroDef;
|
||||||
|
|
||||||
|
@ -18,10 +18,7 @@ pub(crate) struct Trace<T, V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T, V> Trace<T, V> {
|
impl<T, V> Trace<T, V> {
|
||||||
pub(crate) fn new_for_arena() -> Trace<T, V> {
|
#[allow(dead_code)]
|
||||||
Trace { arena: Some(Arena::default()), map: None, len: 0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn new_for_map() -> Trace<T, V> {
|
pub(crate) fn new_for_map() -> Trace<T, V> {
|
||||||
Trace { arena: None, map: Some(ArenaMap::default()), len: 0 }
|
Trace { arena: None, map: Some(ArenaMap::default()), len: 0 }
|
||||||
}
|
}
|
||||||
@ -41,6 +38,7 @@ impl<T, V> Trace<T, V> {
|
|||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub(crate) fn into_arena(mut self) -> Arena<T> {
|
pub(crate) fn into_arena(mut self) -> Arena<T> {
|
||||||
self.arena.take().unwrap()
|
self.arena.take().unwrap()
|
||||||
}
|
}
|
||||||
|
@ -225,9 +225,7 @@ pub(crate) fn field_visibilities_query(
|
|||||||
let var_data = match variant_id {
|
let var_data = match variant_id {
|
||||||
VariantId::StructId(it) => db.struct_data(it).variant_data.clone(),
|
VariantId::StructId(it) => db.struct_data(it).variant_data.clone(),
|
||||||
VariantId::UnionId(it) => db.union_data(it).variant_data.clone(),
|
VariantId::UnionId(it) => db.union_data(it).variant_data.clone(),
|
||||||
VariantId::EnumVariantId(it) => {
|
VariantId::EnumVariantId(it) => db.enum_variant_data(it).variant_data.clone(),
|
||||||
db.enum_data(it.parent).variants[it.local_id].variant_data.clone()
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
let resolver = variant_id.module(db).resolver(db);
|
let resolver = variant_id.module(db).resolver(db);
|
||||||
let mut res = ArenaMap::default();
|
let mut res = ArenaMap::default();
|
||||||
|
@ -218,6 +218,9 @@ pub fn real_span_map(db: &dyn ExpandDatabase, file_id: FileId) -> Arc<RealSpanMa
|
|||||||
let mut pairs = vec![(syntax::TextSize::new(0), span::ROOT_ERASED_FILE_AST_ID)];
|
let mut pairs = vec![(syntax::TextSize::new(0), span::ROOT_ERASED_FILE_AST_ID)];
|
||||||
let ast_id_map = db.ast_id_map(file_id.into());
|
let ast_id_map = db.ast_id_map(file_id.into());
|
||||||
let tree = db.parse(file_id).tree();
|
let tree = db.parse(file_id).tree();
|
||||||
|
// FIXME: Descend into modules and other item containing items that are not annotated with attributes
|
||||||
|
// and allocate pairs for those as well. This gives us finer grained span anchors resulting in
|
||||||
|
// better incrementality
|
||||||
pairs.extend(
|
pairs.extend(
|
||||||
tree.items()
|
tree.items()
|
||||||
.map(|item| (item.syntax().text_range().start(), ast_id_map.ast_id(&item).erase())),
|
.map(|item| (item.syntax().text_range().start(), ast_id_map.ast_id(&item).erase())),
|
||||||
|
@ -10,7 +10,7 @@ use hir_def::{
|
|||||||
type_ref::LiteralConstRef,
|
type_ref::LiteralConstRef,
|
||||||
ConstBlockLoc, EnumVariantId, GeneralConstId, StaticId,
|
ConstBlockLoc, EnumVariantId, GeneralConstId, StaticId,
|
||||||
};
|
};
|
||||||
use la_arena::{Idx, RawIdx};
|
use hir_expand::Lookup;
|
||||||
use stdx::never;
|
use stdx::never;
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
||||||
@ -256,12 +256,21 @@ pub(crate) fn const_eval_discriminant_variant(
|
|||||||
let def = variant_id.into();
|
let def = variant_id.into();
|
||||||
let body = db.body(def);
|
let body = db.body(def);
|
||||||
if body.exprs[body.body_expr] == Expr::Missing {
|
if body.exprs[body.body_expr] == Expr::Missing {
|
||||||
let prev_idx: u32 = variant_id.local_id.into_raw().into();
|
let loc = variant_id.lookup(db.upcast());
|
||||||
let prev_idx = prev_idx.checked_sub(1).map(RawIdx::from).map(Idx::from_raw);
|
let parent_id = loc.parent.lookup(db.upcast()).id;
|
||||||
|
let index = loc.id.value.index().into_raw().into_u32()
|
||||||
|
- parent_id.item_tree(db.upcast())[parent_id.value]
|
||||||
|
.variants
|
||||||
|
.start
|
||||||
|
.index()
|
||||||
|
.into_raw()
|
||||||
|
.into_u32();
|
||||||
|
let prev_idx = index.checked_sub(1);
|
||||||
let value = match prev_idx {
|
let value = match prev_idx {
|
||||||
Some(local_id) => {
|
Some(prev_idx) => {
|
||||||
let prev_variant = EnumVariantId { local_id, parent: variant_id.parent };
|
1 + db.const_eval_discriminant(
|
||||||
1 + db.const_eval_discriminant(prev_variant)?
|
db.enum_data(loc.parent).variants[prev_idx as usize].0,
|
||||||
|
)?
|
||||||
}
|
}
|
||||||
_ => 0,
|
_ => 0,
|
||||||
};
|
};
|
||||||
|
@ -292,7 +292,7 @@ fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult>
|
|||||||
.display(db.upcast())
|
.display(db.upcast())
|
||||||
.to_string(),
|
.to_string(),
|
||||||
DefWithBodyId::VariantId(it) => {
|
DefWithBodyId::VariantId(it) => {
|
||||||
db.enum_data(it.parent).variants[it.local_id].name.display(db.upcast()).to_string()
|
db.enum_variant_data(it).name.display(db.upcast()).to_string()
|
||||||
}
|
}
|
||||||
DefWithBodyId::InTypeConstId(it) => format!("in type const {it:?}"),
|
DefWithBodyId::InTypeConstId(it) => format!("in type const {it:?}"),
|
||||||
});
|
});
|
||||||
|
@ -582,11 +582,11 @@ impl<'a> DeclValidator<'a> {
|
|||||||
// Check the field names.
|
// Check the field names.
|
||||||
let enum_fields_replacements = data
|
let enum_fields_replacements = data
|
||||||
.variants
|
.variants
|
||||||
.values()
|
.iter()
|
||||||
.filter_map(|variant| {
|
.filter_map(|(_, name)| {
|
||||||
Some(Replacement {
|
Some(Replacement {
|
||||||
current_name: variant.name.clone(),
|
current_name: name.clone(),
|
||||||
suggested_text: to_camel_case(&variant.name.to_smol_str())?,
|
suggested_text: to_camel_case(&name.to_smol_str())?,
|
||||||
expected_case: CaseType::UpperCamelCase,
|
expected_case: CaseType::UpperCamelCase,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -318,8 +318,7 @@ impl HirDisplay for Pat {
|
|||||||
if let Some(variant) = variant {
|
if let Some(variant) = variant {
|
||||||
match variant {
|
match variant {
|
||||||
VariantId::EnumVariantId(v) => {
|
VariantId::EnumVariantId(v) => {
|
||||||
let data = f.db.enum_data(v.parent);
|
write!(f, "{}", f.db.enum_variant_data(v).name.display(f.db.upcast()))?;
|
||||||
write!(f, "{}", data.variants[v.local_id].name.display(f.db.upcast()))?;
|
|
||||||
}
|
}
|
||||||
VariantId::StructId(s) => {
|
VariantId::StructId(s) => {
|
||||||
write!(f, "{}", f.db.struct_data(s).name.display(f.db.upcast()))?
|
write!(f, "{}", f.db.struct_data(s).name.display(f.db.upcast()))?
|
||||||
|
@ -594,7 +594,7 @@ impl SplitWildcard {
|
|||||||
let mut ctors: SmallVec<[_; 1]> = enum_data
|
let mut ctors: SmallVec<[_; 1]> = enum_data
|
||||||
.variants
|
.variants
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(local_id, _)| EnumVariantId { parent: *enum_id, local_id })
|
.map(|&(variant, _)| variant)
|
||||||
.filter(|&variant| {
|
.filter(|&variant| {
|
||||||
// If `exhaustive_patterns` is enabled, we exclude variants known to be
|
// If `exhaustive_patterns` is enabled, we exclude variants known to be
|
||||||
// uninhabited.
|
// uninhabited.
|
||||||
|
@ -20,8 +20,7 @@ use hir_def::{
|
|||||||
path::{Path, PathKind},
|
path::{Path, PathKind},
|
||||||
type_ref::{TraitBoundModifier, TypeBound, TypeRef},
|
type_ref::{TraitBoundModifier, TypeBound, TypeRef},
|
||||||
visibility::Visibility,
|
visibility::Visibility,
|
||||||
EnumVariantId, HasModule, ItemContainerId, LocalFieldId, Lookup, ModuleDefId, ModuleId,
|
HasModule, ItemContainerId, LocalFieldId, Lookup, ModuleDefId, ModuleId, TraitId,
|
||||||
TraitId,
|
|
||||||
};
|
};
|
||||||
use hir_expand::name::Name;
|
use hir_expand::name::Name;
|
||||||
use intern::{Internable, Interned};
|
use intern::{Internable, Interned};
|
||||||
@ -613,10 +612,9 @@ fn render_const_scalar(
|
|||||||
else {
|
else {
|
||||||
return f.write_str("<failed-to-detect-variant>");
|
return f.write_str("<failed-to-detect-variant>");
|
||||||
};
|
};
|
||||||
let data = &f.db.enum_data(e).variants[var_id];
|
let data = f.db.enum_variant_data(var_id);
|
||||||
write!(f, "{}", data.name.display(f.db.upcast()))?;
|
write!(f, "{}", data.name.display(f.db.upcast()))?;
|
||||||
let field_types =
|
let field_types = f.db.field_types(var_id.into());
|
||||||
f.db.field_types(EnumVariantId { parent: e, local_id: var_id }.into());
|
|
||||||
render_variant_after_name(
|
render_variant_after_name(
|
||||||
&data.variant_data,
|
&data.variant_data,
|
||||||
f,
|
f,
|
||||||
@ -892,11 +890,9 @@ impl HirDisplay for Ty {
|
|||||||
CallableDefId::StructId(s) => {
|
CallableDefId::StructId(s) => {
|
||||||
write!(f, "{}", db.struct_data(s).name.display(f.db.upcast()))?
|
write!(f, "{}", db.struct_data(s).name.display(f.db.upcast()))?
|
||||||
}
|
}
|
||||||
CallableDefId::EnumVariantId(e) => write!(
|
CallableDefId::EnumVariantId(e) => {
|
||||||
f,
|
write!(f, "{}", db.enum_variant_data(e).name.display(f.db.upcast()))?
|
||||||
"{}",
|
}
|
||||||
db.enum_data(e.parent).variants[e.local_id].name.display(f.db.upcast())
|
|
||||||
)?,
|
|
||||||
};
|
};
|
||||||
f.end_location_link();
|
f.end_location_link();
|
||||||
if parameters.len(Interner) > 0 {
|
if parameters.len(Interner) > 0 {
|
||||||
|
@ -40,8 +40,8 @@ use hir_def::{
|
|||||||
path::{ModPath, Path},
|
path::{ModPath, Path},
|
||||||
resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
|
resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
|
||||||
type_ref::TypeRef,
|
type_ref::TypeRef,
|
||||||
AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, ItemContainerId, Lookup,
|
AdtId, AssocItemId, DefWithBodyId, FieldId, FunctionId, ItemContainerId, Lookup, TraitId,
|
||||||
TraitId, TupleFieldId, TupleId, TypeAliasId, VariantId,
|
TupleFieldId, TupleId, TypeAliasId, VariantId,
|
||||||
};
|
};
|
||||||
use hir_expand::name::{name, Name};
|
use hir_expand::name::{name, Name};
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
@ -87,7 +87,8 @@ pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<Infer
|
|||||||
DefWithBodyId::ConstId(c) => ctx.collect_const(&db.const_data(c)),
|
DefWithBodyId::ConstId(c) => ctx.collect_const(&db.const_data(c)),
|
||||||
DefWithBodyId::StaticId(s) => ctx.collect_static(&db.static_data(s)),
|
DefWithBodyId::StaticId(s) => ctx.collect_static(&db.static_data(s)),
|
||||||
DefWithBodyId::VariantId(v) => {
|
DefWithBodyId::VariantId(v) => {
|
||||||
ctx.return_ty = TyBuilder::builtin(match db.enum_data(v.parent).variant_body_type() {
|
ctx.return_ty = TyBuilder::builtin(
|
||||||
|
match db.enum_data(v.lookup(db.upcast()).parent.into()).variant_body_type() {
|
||||||
hir_def::layout::IntegerType::Pointer(signed) => match signed {
|
hir_def::layout::IntegerType::Pointer(signed) => match signed {
|
||||||
true => BuiltinType::Int(BuiltinInt::Isize),
|
true => BuiltinType::Int(BuiltinInt::Isize),
|
||||||
false => BuiltinType::Uint(BuiltinUint::Usize),
|
false => BuiltinType::Uint(BuiltinUint::Usize),
|
||||||
@ -108,7 +109,8 @@ pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<Infer
|
|||||||
Integer::I128 => BuiltinUint::U128,
|
Integer::I128 => BuiltinUint::U128,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
DefWithBodyId::InTypeConstId(c) => {
|
DefWithBodyId::InTypeConstId(c) => {
|
||||||
// FIXME(const-generic-body): We should not get the return type in this way.
|
// FIXME(const-generic-body): We should not get the return type in this way.
|
||||||
@ -1062,7 +1064,7 @@ impl<'a> InferenceContext<'a> {
|
|||||||
Some(ResolveValueResult::ValueNs(value, _)) => match value {
|
Some(ResolveValueResult::ValueNs(value, _)) => match value {
|
||||||
ValueNs::EnumVariantId(var) => {
|
ValueNs::EnumVariantId(var) => {
|
||||||
let substs = ctx.substs_from_path(path, var.into(), true);
|
let substs = ctx.substs_from_path(path, var.into(), true);
|
||||||
let ty = self.db.ty(var.parent.into());
|
let ty = self.db.ty(var.lookup(self.db.upcast()).parent.into());
|
||||||
let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
|
let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
|
||||||
return (ty, Some(var.into()));
|
return (ty, Some(var.into()));
|
||||||
}
|
}
|
||||||
@ -1105,7 +1107,7 @@ impl<'a> InferenceContext<'a> {
|
|||||||
}
|
}
|
||||||
TypeNs::EnumVariantId(var) => {
|
TypeNs::EnumVariantId(var) => {
|
||||||
let substs = ctx.substs_from_path(path, var.into(), true);
|
let substs = ctx.substs_from_path(path, var.into(), true);
|
||||||
let ty = self.db.ty(var.parent.into());
|
let ty = self.db.ty(var.lookup(self.db.upcast()).parent.into());
|
||||||
let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
|
let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
|
||||||
forbid_unresolved_segments((ty, Some(var.into())), unresolved)
|
forbid_unresolved_segments((ty, Some(var.into())), unresolved)
|
||||||
}
|
}
|
||||||
@ -1131,8 +1133,7 @@ impl<'a> InferenceContext<'a> {
|
|||||||
if let Some((AdtId::EnumId(id), _)) = ty.as_adt() {
|
if let Some((AdtId::EnumId(id), _)) = ty.as_adt() {
|
||||||
let enum_data = self.db.enum_data(id);
|
let enum_data = self.db.enum_data(id);
|
||||||
let name = current_segment.first().unwrap().name;
|
let name = current_segment.first().unwrap().name;
|
||||||
if let Some(local_id) = enum_data.variant(name) {
|
if let Some(variant) = enum_data.variant(name) {
|
||||||
let variant = EnumVariantId { parent: id, local_id };
|
|
||||||
return if remaining_segments.len() == 1 {
|
return if remaining_segments.len() == 1 {
|
||||||
(ty, Some(variant.into()))
|
(ty, Some(variant.into()))
|
||||||
} else {
|
} else {
|
||||||
@ -1247,8 +1248,7 @@ impl<'a> InferenceContext<'a> {
|
|||||||
// this could be an enum variant or associated type
|
// this could be an enum variant or associated type
|
||||||
if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() {
|
if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() {
|
||||||
let enum_data = self.db.enum_data(enum_id);
|
let enum_data = self.db.enum_data(enum_id);
|
||||||
if let Some(local_id) = enum_data.variant(segment) {
|
if let Some(variant) = enum_data.variant(segment) {
|
||||||
let variant = EnumVariantId { parent: enum_id, local_id };
|
|
||||||
return (ty, Some(variant.into()));
|
return (ty, Some(variant.into()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -666,7 +666,7 @@ impl InferenceContext<'_> {
|
|||||||
| Pat::Or(_) => (),
|
| Pat::Or(_) => (),
|
||||||
Pat::TupleStruct { .. } | Pat::Record { .. } => {
|
Pat::TupleStruct { .. } | Pat::Record { .. } => {
|
||||||
if let Some(variant) = self.result.variant_resolution_for_pat(p) {
|
if let Some(variant) = self.result.variant_resolution_for_pat(p) {
|
||||||
let adt = variant.adt_id();
|
let adt = variant.adt_id(self.db.upcast());
|
||||||
let is_multivariant = match adt {
|
let is_multivariant = match adt {
|
||||||
hir_def::AdtId::EnumId(e) => self.db.enum_data(e).variants.len() != 1,
|
hir_def::AdtId::EnumId(e) => self.db.enum_data(e).variants.len() != 1,
|
||||||
_ => false,
|
_ => false,
|
||||||
|
@ -4,7 +4,7 @@ use chalk_ir::cast::Cast;
|
|||||||
use hir_def::{
|
use hir_def::{
|
||||||
path::{Path, PathSegment},
|
path::{Path, PathSegment},
|
||||||
resolver::{ResolveValueResult, TypeNs, ValueNs},
|
resolver::{ResolveValueResult, TypeNs, ValueNs},
|
||||||
AdtId, AssocItemId, EnumVariantId, GenericDefId, ItemContainerId, Lookup,
|
AdtId, AssocItemId, GenericDefId, ItemContainerId, Lookup,
|
||||||
};
|
};
|
||||||
use hir_expand::name::Name;
|
use hir_expand::name::Name;
|
||||||
use stdx::never;
|
use stdx::never;
|
||||||
@ -395,8 +395,7 @@ impl InferenceContext<'_> {
|
|||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
let enum_data = self.db.enum_data(enum_id);
|
let enum_data = self.db.enum_data(enum_id);
|
||||||
let local_id = enum_data.variant(name)?;
|
let variant = enum_data.variant(name)?;
|
||||||
let variant = EnumVariantId { parent: enum_id, local_id };
|
|
||||||
self.write_variant_resolution(id, variant.into());
|
self.write_variant_resolution(id, variant.into());
|
||||||
Some((ValueNs::EnumVariantId(variant), subst.clone()))
|
Some((ValueNs::EnumVariantId(variant), subst.clone()))
|
||||||
}
|
}
|
||||||
|
@ -30,17 +30,15 @@ pub(crate) fn is_enum_variant_uninhabited_from(
|
|||||||
target_mod: ModuleId,
|
target_mod: ModuleId,
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let enum_data = db.enum_data(variant.parent);
|
let is_local = variant.lookup(db.upcast()).container.krate() == target_mod.krate();
|
||||||
let vars_attrs = db.variants_attrs(variant.parent);
|
|
||||||
let is_local = variant.parent.lookup(db.upcast()).container.krate() == target_mod.krate();
|
|
||||||
|
|
||||||
let mut uninhabited_from =
|
let mut uninhabited_from =
|
||||||
UninhabitedFrom { target_mod, db, max_depth: 500, recursive_ty: FxHashSet::default() };
|
UninhabitedFrom { target_mod, db, max_depth: 500, recursive_ty: FxHashSet::default() };
|
||||||
let inhabitedness = uninhabited_from.visit_variant(
|
let inhabitedness = uninhabited_from.visit_variant(
|
||||||
variant.into(),
|
variant.into(),
|
||||||
&enum_data.variants[variant.local_id].variant_data,
|
&db.enum_variant_data(variant).variant_data,
|
||||||
subst,
|
subst,
|
||||||
&vars_attrs[variant.local_id],
|
&db.attrs(variant.into()),
|
||||||
is_local,
|
is_local,
|
||||||
);
|
);
|
||||||
inhabitedness == BREAK_VISIBLY_UNINHABITED
|
inhabitedness == BREAK_VISIBLY_UNINHABITED
|
||||||
@ -117,15 +115,14 @@ impl UninhabitedFrom<'_> {
|
|||||||
self.visit_variant(s.into(), &struct_data.variant_data, subst, &attrs, is_local)
|
self.visit_variant(s.into(), &struct_data.variant_data, subst, &attrs, is_local)
|
||||||
}
|
}
|
||||||
AdtId::EnumId(e) => {
|
AdtId::EnumId(e) => {
|
||||||
let vars_attrs = self.db.variants_attrs(e);
|
|
||||||
let enum_data = self.db.enum_data(e);
|
let enum_data = self.db.enum_data(e);
|
||||||
|
|
||||||
for (local_id, enum_var) in enum_data.variants.iter() {
|
for &(variant, _) in enum_data.variants.iter() {
|
||||||
let variant_inhabitedness = self.visit_variant(
|
let variant_inhabitedness = self.visit_variant(
|
||||||
EnumVariantId { parent: e, local_id }.into(),
|
variant.into(),
|
||||||
&enum_var.variant_data,
|
&self.db.enum_variant_data(variant).variant_data,
|
||||||
subst,
|
subst,
|
||||||
&vars_attrs[local_id],
|
&self.db.attrs(variant.into()),
|
||||||
is_local,
|
is_local,
|
||||||
);
|
);
|
||||||
match variant_inhabitedness {
|
match variant_inhabitedness {
|
||||||
|
@ -9,7 +9,7 @@ use hir_def::{
|
|||||||
Abi, FieldsShape, Integer, LayoutCalculator, LayoutS, Primitive, ReprOptions, Scalar, Size,
|
Abi, FieldsShape, Integer, LayoutCalculator, LayoutS, Primitive, ReprOptions, Scalar, Size,
|
||||||
StructKind, TargetDataLayout, WrappingRange,
|
StructKind, TargetDataLayout, WrappingRange,
|
||||||
},
|
},
|
||||||
LocalEnumVariantId, LocalFieldId, StructId,
|
LocalFieldId, StructId,
|
||||||
};
|
};
|
||||||
use la_arena::{Idx, RawIdx};
|
use la_arena::{Idx, RawIdx};
|
||||||
use rustc_abi::AddressSpace;
|
use rustc_abi::AddressSpace;
|
||||||
@ -32,15 +32,15 @@ mod adt;
|
|||||||
mod target;
|
mod target;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct RustcEnumVariantIdx(pub LocalEnumVariantId);
|
pub struct RustcEnumVariantIdx(pub usize);
|
||||||
|
|
||||||
impl rustc_index::Idx for RustcEnumVariantIdx {
|
impl rustc_index::Idx for RustcEnumVariantIdx {
|
||||||
fn new(idx: usize) -> Self {
|
fn new(idx: usize) -> Self {
|
||||||
RustcEnumVariantIdx(Idx::from_raw(RawIdx::from(idx as u32)))
|
RustcEnumVariantIdx(idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn index(self) -> usize {
|
fn index(self) -> usize {
|
||||||
u32::from(self.0.into_raw()) as usize
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,9 +6,8 @@ use base_db::salsa::Cycle;
|
|||||||
use hir_def::{
|
use hir_def::{
|
||||||
data::adt::VariantData,
|
data::adt::VariantData,
|
||||||
layout::{Integer, LayoutCalculator, ReprOptions, TargetDataLayout},
|
layout::{Integer, LayoutCalculator, ReprOptions, TargetDataLayout},
|
||||||
AdtId, EnumVariantId, LocalEnumVariantId, VariantId,
|
AdtId, VariantId,
|
||||||
};
|
};
|
||||||
use la_arena::RawIdx;
|
|
||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
@ -22,8 +21,8 @@ use crate::{
|
|||||||
|
|
||||||
use super::LayoutCx;
|
use super::LayoutCx;
|
||||||
|
|
||||||
pub(crate) const fn struct_variant_idx() -> RustcEnumVariantIdx {
|
pub(crate) fn struct_variant_idx() -> RustcEnumVariantIdx {
|
||||||
RustcEnumVariantIdx(LocalEnumVariantId::from_raw(RawIdx::from_u32(0)))
|
RustcEnumVariantIdx(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn layout_of_adt_query(
|
pub fn layout_of_adt_query(
|
||||||
@ -62,12 +61,7 @@ pub fn layout_of_adt_query(
|
|||||||
let r = data
|
let r = data
|
||||||
.variants
|
.variants
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(idx, v)| {
|
.map(|&(v, _)| handle_variant(v.into(), &db.enum_variant_data(v).variant_data))
|
||||||
handle_variant(
|
|
||||||
EnumVariantId { parent: e, local_id: idx }.into(),
|
|
||||||
&v.variant_data,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect::<Result<SmallVec<_>, _>>()?;
|
.collect::<Result<SmallVec<_>, _>>()?;
|
||||||
(r, data.repr.unwrap_or_default())
|
(r, data.repr.unwrap_or_default())
|
||||||
}
|
}
|
||||||
@ -89,8 +83,7 @@ pub fn layout_of_adt_query(
|
|||||||
|min, max| repr_discr(&dl, &repr, min, max).unwrap_or((Integer::I8, false)),
|
|min, max| repr_discr(&dl, &repr, min, max).unwrap_or((Integer::I8, false)),
|
||||||
variants.iter_enumerated().filter_map(|(id, _)| {
|
variants.iter_enumerated().filter_map(|(id, _)| {
|
||||||
let AdtId::EnumId(e) = def else { return None };
|
let AdtId::EnumId(e) = def else { return None };
|
||||||
let d =
|
let d = db.const_eval_discriminant(db.enum_data(e).variants[id.0].0).ok()?;
|
||||||
db.const_eval_discriminant(EnumVariantId { parent: e, local_id: id.0 }).ok()?;
|
|
||||||
Some((id, d))
|
Some((id, d))
|
||||||
}),
|
}),
|
||||||
// FIXME: The current code for niche-filling relies on variant indices
|
// FIXME: The current code for niche-filling relies on variant indices
|
||||||
|
@ -762,7 +762,7 @@ impl<'a> TyLoweringContext<'a> {
|
|||||||
Some(segment) if segment.args_and_bindings.is_some() => Some(segment),
|
Some(segment) if segment.args_and_bindings.is_some() => Some(segment),
|
||||||
_ => last,
|
_ => last,
|
||||||
};
|
};
|
||||||
(segment, Some(var.parent.into()))
|
(segment, Some(var.lookup(self.db.upcast()).parent.into()))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(segment) = segment {
|
if let Some(segment) = segment {
|
||||||
@ -1375,11 +1375,13 @@ pub(crate) fn field_types_query(
|
|||||||
let (resolver, def): (_, GenericDefId) = match variant_id {
|
let (resolver, def): (_, GenericDefId) = match variant_id {
|
||||||
VariantId::StructId(it) => (it.resolver(db.upcast()), it.into()),
|
VariantId::StructId(it) => (it.resolver(db.upcast()), it.into()),
|
||||||
VariantId::UnionId(it) => (it.resolver(db.upcast()), it.into()),
|
VariantId::UnionId(it) => (it.resolver(db.upcast()), it.into()),
|
||||||
VariantId::EnumVariantId(it) => (it.parent.resolver(db.upcast()), it.parent.into()),
|
VariantId::EnumVariantId(it) => {
|
||||||
|
(it.resolver(db.upcast()), it.lookup(db.upcast()).parent.into())
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let generics = generics(db.upcast(), def);
|
let generics = generics(db.upcast(), def);
|
||||||
let mut res = ArenaMap::default();
|
let mut res = ArenaMap::default();
|
||||||
let ctx = TyLoweringContext::new(db, &resolver, GenericDefId::from(variant_id.adt_id()).into())
|
let ctx = TyLoweringContext::new(db, &resolver, def.into())
|
||||||
.with_type_param_mode(ParamLoweringMode::Variable);
|
.with_type_param_mode(ParamLoweringMode::Variable);
|
||||||
for (field_id, field_data) in var_data.fields().iter() {
|
for (field_id, field_data) in var_data.fields().iter() {
|
||||||
res.insert(field_id, make_binders(db, &generics, ctx.lower_ty(&field_data.type_ref)));
|
res.insert(field_id, make_binders(db, &generics, ctx.lower_ty(&field_data.type_ref)));
|
||||||
@ -1740,25 +1742,24 @@ fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Binders<T
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -> PolyFnSig {
|
fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -> PolyFnSig {
|
||||||
let enum_data = db.enum_data(def.parent);
|
let var_data = db.enum_variant_data(def);
|
||||||
let var_data = &enum_data.variants[def.local_id];
|
|
||||||
let fields = var_data.variant_data.fields();
|
let fields = var_data.variant_data.fields();
|
||||||
let resolver = def.parent.resolver(db.upcast());
|
let resolver = def.resolver(db.upcast());
|
||||||
let ctx = TyLoweringContext::new(db, &resolver, DefWithBodyId::VariantId(def).into())
|
let ctx = TyLoweringContext::new(db, &resolver, DefWithBodyId::VariantId(def).into())
|
||||||
.with_type_param_mode(ParamLoweringMode::Variable);
|
.with_type_param_mode(ParamLoweringMode::Variable);
|
||||||
let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>();
|
let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>();
|
||||||
let (ret, binders) = type_for_adt(db, def.parent.into()).into_value_and_skipped_binders();
|
let (ret, binders) =
|
||||||
|
type_for_adt(db, def.lookup(db.upcast()).parent.into()).into_value_and_skipped_binders();
|
||||||
Binders::new(binders, CallableSig::from_params_and_return(params, ret, false, Safety::Safe))
|
Binders::new(binders, CallableSig::from_params_and_return(params, ret, false, Safety::Safe))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build the type of a tuple enum variant constructor.
|
/// Build the type of a tuple enum variant constructor.
|
||||||
fn type_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -> Binders<Ty> {
|
fn type_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -> Binders<Ty> {
|
||||||
let enum_data = db.enum_data(def.parent);
|
let e = def.lookup(db.upcast()).parent;
|
||||||
let var_data = &enum_data.variants[def.local_id].variant_data;
|
if let StructKind::Unit = db.enum_variant_data(def).variant_data.kind() {
|
||||||
if let StructKind::Unit = var_data.kind() {
|
return type_for_adt(db, e.into());
|
||||||
return type_for_adt(db, def.parent.into());
|
|
||||||
}
|
}
|
||||||
let generics = generics(db.upcast(), def.parent.into());
|
let generics = generics(db.upcast(), e.into());
|
||||||
let substs = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
|
let substs = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
|
||||||
make_binders(
|
make_binders(
|
||||||
db,
|
db,
|
||||||
@ -1812,7 +1813,7 @@ impl CallableDefId {
|
|||||||
match self {
|
match self {
|
||||||
CallableDefId::FunctionId(f) => f.lookup(db).module(db),
|
CallableDefId::FunctionId(f) => f.lookup(db).module(db),
|
||||||
CallableDefId::StructId(s) => s.lookup(db).container,
|
CallableDefId::StructId(s) => s.lookup(db).container,
|
||||||
CallableDefId::EnumVariantId(e) => e.parent.lookup(db).container,
|
CallableDefId::EnumVariantId(e) => e.lookup(db).container,
|
||||||
}
|
}
|
||||||
.krate()
|
.krate()
|
||||||
}
|
}
|
||||||
|
@ -751,9 +751,19 @@ impl Evaluator<'_> {
|
|||||||
Variants::Single { .. } => &layout,
|
Variants::Single { .. } => &layout,
|
||||||
Variants::Multiple { variants, .. } => {
|
Variants::Multiple { variants, .. } => {
|
||||||
&variants[match f.parent {
|
&variants[match f.parent {
|
||||||
hir_def::VariantId::EnumVariantId(it) => {
|
hir_def::VariantId::EnumVariantId(it) => RustcEnumVariantIdx({
|
||||||
RustcEnumVariantIdx(it.local_id)
|
let lookup = it.lookup(self.db.upcast());
|
||||||
}
|
let rustc_enum_variant_idx =
|
||||||
|
lookup.id.value.index().into_raw().into_u32()
|
||||||
|
- lookup.id.item_tree(self.db.upcast())
|
||||||
|
[lookup.parent.lookup(self.db.upcast()).id.value]
|
||||||
|
.variants
|
||||||
|
.start
|
||||||
|
.index()
|
||||||
|
.into_raw()
|
||||||
|
.into_u32();
|
||||||
|
rustc_enum_variant_idx as usize
|
||||||
|
}),
|
||||||
_ => {
|
_ => {
|
||||||
return Err(MirEvalError::TypeError(
|
return Err(MirEvalError::TypeError(
|
||||||
"Multivariant layout only happens for enums",
|
"Multivariant layout only happens for enums",
|
||||||
@ -1412,22 +1422,12 @@ impl Evaluator<'_> {
|
|||||||
|
|
||||||
fn compute_discriminant(&self, ty: Ty, bytes: &[u8]) -> Result<i128> {
|
fn compute_discriminant(&self, ty: Ty, bytes: &[u8]) -> Result<i128> {
|
||||||
let layout = self.layout(&ty)?;
|
let layout = self.layout(&ty)?;
|
||||||
let enum_id = 'b: {
|
let &TyKind::Adt(chalk_ir::AdtId(AdtId::EnumId(e)), _) = ty.kind(Interner) else {
|
||||||
match ty.kind(Interner) {
|
|
||||||
TyKind::Adt(e, _) => match e.0 {
|
|
||||||
AdtId::EnumId(e) => break 'b e,
|
|
||||||
_ => (),
|
|
||||||
},
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
return Ok(0);
|
return Ok(0);
|
||||||
};
|
};
|
||||||
match &layout.variants {
|
match &layout.variants {
|
||||||
Variants::Single { index } => {
|
Variants::Single { index } => {
|
||||||
let r = self.const_eval_discriminant(EnumVariantId {
|
let r = self.const_eval_discriminant(self.db.enum_data(e).variants[index.0].0)?;
|
||||||
parent: enum_id,
|
|
||||||
local_id: index.0,
|
|
||||||
})?;
|
|
||||||
Ok(r)
|
Ok(r)
|
||||||
}
|
}
|
||||||
Variants::Multiple { tag, tag_encoding, variants, .. } => {
|
Variants::Multiple { tag, tag_encoding, variants, .. } => {
|
||||||
@ -1446,17 +1446,15 @@ impl Evaluator<'_> {
|
|||||||
let candidate_tag = i128::from_le_bytes(pad16(tag, false))
|
let candidate_tag = i128::from_le_bytes(pad16(tag, false))
|
||||||
.wrapping_sub(*niche_start as i128)
|
.wrapping_sub(*niche_start as i128)
|
||||||
as usize;
|
as usize;
|
||||||
let variant = variants
|
let idx = variants
|
||||||
.iter_enumerated()
|
.iter_enumerated()
|
||||||
.map(|(it, _)| it)
|
.map(|(it, _)| it)
|
||||||
.filter(|it| it != untagged_variant)
|
.filter(|it| it != untagged_variant)
|
||||||
.nth(candidate_tag)
|
.nth(candidate_tag)
|
||||||
.unwrap_or(*untagged_variant)
|
.unwrap_or(*untagged_variant)
|
||||||
.0;
|
.0;
|
||||||
let result = self.const_eval_discriminant(EnumVariantId {
|
let result =
|
||||||
parent: enum_id,
|
self.const_eval_discriminant(self.db.enum_data(e).variants[idx].0)?;
|
||||||
local_id: variant,
|
|
||||||
})?;
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1579,10 +1577,11 @@ impl Evaluator<'_> {
|
|||||||
subst: Substitution,
|
subst: Substitution,
|
||||||
locals: &Locals,
|
locals: &Locals,
|
||||||
) -> Result<(usize, Arc<Layout>, Option<(usize, usize, i128)>)> {
|
) -> Result<(usize, Arc<Layout>, Option<(usize, usize, i128)>)> {
|
||||||
let adt = it.adt_id();
|
let adt = it.adt_id(self.db.upcast());
|
||||||
if let DefWithBodyId::VariantId(f) = locals.body.owner {
|
if let DefWithBodyId::VariantId(f) = locals.body.owner {
|
||||||
if let VariantId::EnumVariantId(it) = it {
|
if let VariantId::EnumVariantId(it) = it {
|
||||||
if AdtId::from(f.parent) == adt {
|
if let AdtId::EnumId(e) = adt {
|
||||||
|
if f.lookup(self.db.upcast()).parent == e {
|
||||||
// Computing the exact size of enums require resolving the enum discriminants. In order to prevent loops (and
|
// Computing the exact size of enums require resolving the enum discriminants. In order to prevent loops (and
|
||||||
// infinite sized type errors) we use a dummy layout
|
// infinite sized type errors) we use a dummy layout
|
||||||
let i = self.const_eval_discriminant(it)?;
|
let i = self.const_eval_discriminant(it)?;
|
||||||
@ -1590,6 +1589,7 @@ impl Evaluator<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
let layout = self.layout_adt(adt, subst)?;
|
let layout = self.layout_adt(adt, subst)?;
|
||||||
Ok(match &layout.variants {
|
Ok(match &layout.variants {
|
||||||
Variants::Single { .. } => (layout.size.bytes_usize(), layout, None),
|
Variants::Single { .. } => (layout.size.bytes_usize(), layout, None),
|
||||||
@ -1602,8 +1602,17 @@ impl Evaluator<'_> {
|
|||||||
VariantId::EnumVariantId(it) => it,
|
VariantId::EnumVariantId(it) => it,
|
||||||
_ => not_supported!("multi variant layout for non-enums"),
|
_ => not_supported!("multi variant layout for non-enums"),
|
||||||
};
|
};
|
||||||
let rustc_enum_variant_idx = RustcEnumVariantIdx(enum_variant_id.local_id);
|
|
||||||
let mut discriminant = self.const_eval_discriminant(enum_variant_id)?;
|
let mut discriminant = self.const_eval_discriminant(enum_variant_id)?;
|
||||||
|
let lookup = enum_variant_id.lookup(self.db.upcast());
|
||||||
|
let rustc_enum_variant_idx = lookup.id.value.index().into_raw().into_u32()
|
||||||
|
- lookup.id.item_tree(self.db.upcast())
|
||||||
|
[lookup.parent.lookup(self.db.upcast()).id.value]
|
||||||
|
.variants
|
||||||
|
.start
|
||||||
|
.index()
|
||||||
|
.into_raw()
|
||||||
|
.into_u32();
|
||||||
|
let rustc_enum_variant_idx = RustcEnumVariantIdx(rustc_enum_variant_idx as usize);
|
||||||
let variant_layout = variants[rustc_enum_variant_idx].clone();
|
let variant_layout = variants[rustc_enum_variant_idx].clone();
|
||||||
let have_tag = match tag_encoding {
|
let have_tag = match tag_encoding {
|
||||||
TagEncoding::Direct => true,
|
TagEncoding::Direct => true,
|
||||||
@ -1847,8 +1856,8 @@ impl Evaluator<'_> {
|
|||||||
.then(|| (layout.size.bytes_usize(), layout.align.abi.bytes() as usize)));
|
.then(|| (layout.size.bytes_usize(), layout.align.abi.bytes() as usize)));
|
||||||
}
|
}
|
||||||
if let DefWithBodyId::VariantId(f) = locals.body.owner {
|
if let DefWithBodyId::VariantId(f) = locals.body.owner {
|
||||||
if let Some((adt, _)) = ty.as_adt() {
|
if let Some((AdtId::EnumId(e), _)) = ty.as_adt() {
|
||||||
if AdtId::from(f.parent) == adt {
|
if f.lookup(self.db.upcast()).parent == e {
|
||||||
// Computing the exact size of enums require resolving the enum discriminants. In order to prevent loops (and
|
// Computing the exact size of enums require resolving the enum discriminants. In order to prevent loops (and
|
||||||
// infinite sized type errors) we use a dummy size
|
// infinite sized type errors) we use a dummy size
|
||||||
return Ok(Some((16, 16)));
|
return Ok(Some((16, 16)));
|
||||||
@ -2019,10 +2028,8 @@ impl Evaluator<'_> {
|
|||||||
bytes,
|
bytes,
|
||||||
e,
|
e,
|
||||||
) {
|
) {
|
||||||
let data = &this.db.enum_data(e).variants[v].variant_data;
|
let data = &this.db.enum_variant_data(v).variant_data;
|
||||||
let field_types = this
|
let field_types = this.db.field_types(v.into());
|
||||||
.db
|
|
||||||
.field_types(EnumVariantId { parent: e, local_id: v }.into());
|
|
||||||
for (f, _) in data.fields().iter() {
|
for (f, _) in data.fields().iter() {
|
||||||
let offset =
|
let offset =
|
||||||
l.fields.offset(u32::from(f.into_raw()) as usize).bytes_usize();
|
l.fields.offset(u32::from(f.into_raw()) as usize).bytes_usize();
|
||||||
@ -2093,14 +2100,13 @@ impl Evaluator<'_> {
|
|||||||
}
|
}
|
||||||
AdtId::UnionId(_) => (),
|
AdtId::UnionId(_) => (),
|
||||||
AdtId::EnumId(e) => {
|
AdtId::EnumId(e) => {
|
||||||
if let Some((variant, layout)) = detect_variant_from_bytes(
|
if let Some((ev, layout)) = detect_variant_from_bytes(
|
||||||
&layout,
|
&layout,
|
||||||
self.db,
|
self.db,
|
||||||
self.trait_env.clone(),
|
self.trait_env.clone(),
|
||||||
self.read_memory(addr, layout.size.bytes_usize())?,
|
self.read_memory(addr, layout.size.bytes_usize())?,
|
||||||
e,
|
e,
|
||||||
) {
|
) {
|
||||||
let ev = EnumVariantId { parent: e, local_id: variant };
|
|
||||||
for (i, (_, ty)) in self.db.field_types(ev.into()).iter().enumerate() {
|
for (i, (_, ty)) in self.db.field_types(ev.into()).iter().enumerate() {
|
||||||
let offset = layout.fields.offset(i).bytes_usize();
|
let offset = layout.fields.offset(i).bytes_usize();
|
||||||
let ty = ty.clone().substitute(Interner, subst);
|
let ty = ty.clone().substitute(Interner, subst);
|
||||||
@ -2540,11 +2546,13 @@ impl Evaluator<'_> {
|
|||||||
match r {
|
match r {
|
||||||
Ok(r) => Ok(r),
|
Ok(r) => Ok(r),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let data = self.db.enum_data(variant.parent);
|
let db = self.db.upcast();
|
||||||
|
let loc = variant.lookup(db);
|
||||||
|
let enum_loc = loc.parent.lookup(db);
|
||||||
let name = format!(
|
let name = format!(
|
||||||
"{}::{}",
|
"{}::{}",
|
||||||
data.name.display(self.db.upcast()),
|
enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db.upcast()),
|
||||||
data.variants[variant.local_id].name.display(self.db.upcast())
|
loc.id.item_tree(db)[loc.id.value].name.display(db.upcast()),
|
||||||
);
|
);
|
||||||
Err(MirEvalError::ConstEvalError(name, Box::new(e)))
|
Err(MirEvalError::ConstEvalError(name, Box::new(e)))
|
||||||
}
|
}
|
||||||
|
@ -456,9 +456,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||||||
Ok(Some(current))
|
Ok(Some(current))
|
||||||
}
|
}
|
||||||
ValueNs::EnumVariantId(variant_id) => {
|
ValueNs::EnumVariantId(variant_id) => {
|
||||||
let variant_data =
|
let variant_data = &self.db.enum_variant_data(variant_id).variant_data;
|
||||||
&self.db.enum_data(variant_id.parent).variants[variant_id.local_id];
|
if variant_data.kind() == StructKind::Unit {
|
||||||
if variant_data.variant_data.kind() == StructKind::Unit {
|
|
||||||
let ty = self.infer.type_of_expr[expr_id].clone();
|
let ty = self.infer.type_of_expr[expr_id].clone();
|
||||||
current = self.lower_enum_variant(
|
current = self.lower_enum_variant(
|
||||||
variant_id,
|
variant_id,
|
||||||
@ -1874,11 +1873,13 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||||||
match r {
|
match r {
|
||||||
Ok(r) => Ok(r),
|
Ok(r) => Ok(r),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let data = self.db.enum_data(variant.parent);
|
let db = self.db.upcast();
|
||||||
|
let loc = variant.lookup(db);
|
||||||
|
let enum_loc = loc.parent.lookup(db);
|
||||||
let name = format!(
|
let name = format!(
|
||||||
"{}::{}",
|
"{}::{}",
|
||||||
data.name.display(self.db.upcast()),
|
enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db.upcast()),
|
||||||
data.variants[variant.local_id].name.display(self.db.upcast())
|
loc.id.item_tree(db)[loc.id.value].name.display(db.upcast()),
|
||||||
);
|
);
|
||||||
Err(MirLowerError::ConstEvalError(name.into(), Box::new(e)))
|
Err(MirLowerError::ConstEvalError(name.into(), Box::new(e)))
|
||||||
}
|
}
|
||||||
@ -2104,7 +2105,7 @@ pub fn mir_body_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Result<Arc<Mi
|
|||||||
.display(db.upcast())
|
.display(db.upcast())
|
||||||
.to_string(),
|
.to_string(),
|
||||||
DefWithBodyId::VariantId(it) => {
|
DefWithBodyId::VariantId(it) => {
|
||||||
db.enum_data(it.parent).variants[it.local_id].name.display(db.upcast()).to_string()
|
db.enum_variant_data(it).name.display(db.upcast()).to_string()
|
||||||
}
|
}
|
||||||
DefWithBodyId::InTypeConstId(it) => format!("in type const {it:?}"),
|
DefWithBodyId::InTypeConstId(it) => format!("in type const {it:?}"),
|
||||||
});
|
});
|
||||||
|
@ -524,10 +524,9 @@ impl MirLowerCtx<'_> {
|
|||||||
);
|
);
|
||||||
current = next;
|
current = next;
|
||||||
}
|
}
|
||||||
let enum_data = self.db.enum_data(v.parent);
|
|
||||||
self.pattern_matching_variant_fields(
|
self.pattern_matching_variant_fields(
|
||||||
shape,
|
shape,
|
||||||
&enum_data.variants[v.local_id].variant_data,
|
&self.db.enum_variant_data(v).variant_data,
|
||||||
variant,
|
variant,
|
||||||
current,
|
current,
|
||||||
current_else,
|
current_else,
|
||||||
@ -535,18 +534,15 @@ impl MirLowerCtx<'_> {
|
|||||||
mode,
|
mode,
|
||||||
)?
|
)?
|
||||||
}
|
}
|
||||||
VariantId::StructId(s) => {
|
VariantId::StructId(s) => self.pattern_matching_variant_fields(
|
||||||
let struct_data = self.db.struct_data(s);
|
|
||||||
self.pattern_matching_variant_fields(
|
|
||||||
shape,
|
shape,
|
||||||
&struct_data.variant_data,
|
&self.db.struct_data(s).variant_data,
|
||||||
variant,
|
variant,
|
||||||
current,
|
current,
|
||||||
current_else,
|
current_else,
|
||||||
&cond_place,
|
&cond_place,
|
||||||
mode,
|
mode,
|
||||||
)?
|
)?,
|
||||||
}
|
|
||||||
VariantId::UnionId(_) => {
|
VariantId::UnionId(_) => {
|
||||||
return Err(MirLowerError::TypeError("pattern matching on union"))
|
return Err(MirLowerError::TypeError("pattern matching on union"))
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ use std::{
|
|||||||
|
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use hir_def::{body::Body, hir::BindingId};
|
use hir_def::{body::Body, hir::BindingId};
|
||||||
use hir_expand::name::Name;
|
use hir_expand::{name::Name, Lookup};
|
||||||
use la_arena::ArenaMap;
|
use la_arena::ArenaMap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -58,8 +58,14 @@ impl MirBody {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
hir_def::DefWithBodyId::VariantId(id) => {
|
hir_def::DefWithBodyId::VariantId(id) => {
|
||||||
let data = db.enum_data(id.parent);
|
let loc = id.lookup(db.upcast());
|
||||||
w!(this, "enum {} = ", data.name.display(db.upcast()));
|
let enum_loc = loc.parent.lookup(db.upcast());
|
||||||
|
w!(
|
||||||
|
this,
|
||||||
|
"enum {}::{} = ",
|
||||||
|
enum_loc.id.item_tree(db.upcast())[enum_loc.id.value].name.display(db.upcast()),
|
||||||
|
loc.id.item_tree(db.upcast())[loc.id.value].name.display(db.upcast()),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
hir_def::DefWithBodyId::InTypeConstId(id) => {
|
hir_def::DefWithBodyId::InTypeConstId(id) => {
|
||||||
w!(this, "in type const {id:?} = ");
|
w!(this, "in type const {id:?} = ");
|
||||||
@ -306,8 +312,7 @@ impl<'a> MirPrettyCtx<'a> {
|
|||||||
hir_def::VariantId::EnumVariantId(e) => {
|
hir_def::VariantId::EnumVariantId(e) => {
|
||||||
w!(this, "(");
|
w!(this, "(");
|
||||||
f(this, local, head);
|
f(this, local, head);
|
||||||
let variant_name =
|
let variant_name = &this.db.enum_variant_data(e).name;
|
||||||
&this.db.enum_data(e.parent).variants[e.local_id].name;
|
|
||||||
w!(
|
w!(
|
||||||
this,
|
this,
|
||||||
" as {}).{}",
|
" as {}).{}",
|
||||||
|
@ -16,7 +16,7 @@ use base_db::{FileRange, SourceDatabaseExt};
|
|||||||
use expect_test::Expect;
|
use expect_test::Expect;
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
body::{Body, BodySourceMap, SyntheticSyntax},
|
body::{Body, BodySourceMap, SyntheticSyntax},
|
||||||
db::{DefDatabase, InternDatabase},
|
db::DefDatabase,
|
||||||
hir::{ExprId, Pat, PatId},
|
hir::{ExprId, Pat, PatId},
|
||||||
item_scope::ItemScope,
|
item_scope::ItemScope,
|
||||||
nameres::DefMap,
|
nameres::DefMap,
|
||||||
@ -145,7 +145,7 @@ fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_sour
|
|||||||
loc.source(&db).value.syntax().text_range().start()
|
loc.source(&db).value.syntax().text_range().start()
|
||||||
}
|
}
|
||||||
DefWithBodyId::VariantId(it) => {
|
DefWithBodyId::VariantId(it) => {
|
||||||
let loc = db.lookup_intern_enum(it.parent);
|
let loc = it.lookup(&db);
|
||||||
loc.source(&db).value.syntax().text_range().start()
|
loc.source(&db).value.syntax().text_range().start()
|
||||||
}
|
}
|
||||||
DefWithBodyId::InTypeConstId(it) => it.source(&db).syntax().text_range().start(),
|
DefWithBodyId::InTypeConstId(it) => it.source(&db).syntax().text_range().start(),
|
||||||
@ -383,7 +383,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
|
|||||||
loc.source(&db).value.syntax().text_range().start()
|
loc.source(&db).value.syntax().text_range().start()
|
||||||
}
|
}
|
||||||
DefWithBodyId::VariantId(it) => {
|
DefWithBodyId::VariantId(it) => {
|
||||||
let loc = db.lookup_intern_enum(it.parent);
|
let loc = it.lookup(&db);
|
||||||
loc.source(&db).value.syntax().text_range().start()
|
loc.source(&db).value.syntax().text_range().start()
|
||||||
}
|
}
|
||||||
DefWithBodyId::InTypeConstId(it) => it.source(&db).syntax().text_range().start(),
|
DefWithBodyId::InTypeConstId(it) => it.source(&db).syntax().text_range().start(),
|
||||||
@ -453,11 +453,7 @@ fn visit_module(
|
|||||||
visit_body(db, &body, cb);
|
visit_body(db, &body, cb);
|
||||||
}
|
}
|
||||||
ModuleDefId::AdtId(hir_def::AdtId::EnumId(it)) => {
|
ModuleDefId::AdtId(hir_def::AdtId::EnumId(it)) => {
|
||||||
db.enum_data(it)
|
db.enum_data(it).variants.iter().for_each(|&(it, _)| {
|
||||||
.variants
|
|
||||||
.iter()
|
|
||||||
.map(|(id, _)| hir_def::EnumVariantId { parent: it, local_id: id })
|
|
||||||
.for_each(|it| {
|
|
||||||
let def = it.into();
|
let def = it.into();
|
||||||
cb(def);
|
cb(def);
|
||||||
let body = db.body(def);
|
let body = db.body(def);
|
||||||
|
@ -107,10 +107,7 @@ impl DebugContext<'_> {
|
|||||||
let name = match def {
|
let name = match def {
|
||||||
CallableDefId::FunctionId(ff) => self.0.function_data(ff).name.clone(),
|
CallableDefId::FunctionId(ff) => self.0.function_data(ff).name.clone(),
|
||||||
CallableDefId::StructId(s) => self.0.struct_data(s).name.clone(),
|
CallableDefId::StructId(s) => self.0.struct_data(s).name.clone(),
|
||||||
CallableDefId::EnumVariantId(e) => {
|
CallableDefId::EnumVariantId(e) => self.0.enum_variant_data(e).name.clone(),
|
||||||
let enum_data = self.0.enum_data(e.parent);
|
|
||||||
enum_data.variants[e.local_id].name.clone()
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
match def {
|
match def {
|
||||||
CallableDefId::FunctionId(_) => write!(fmt, "{{fn {}}}", name.display(self.0.upcast())),
|
CallableDefId::FunctionId(_) => write!(fmt, "{{fn {}}}", name.display(self.0.upcast())),
|
||||||
|
@ -19,9 +19,8 @@ use hir_def::{
|
|||||||
lang_item::LangItem,
|
lang_item::LangItem,
|
||||||
resolver::{HasResolver, TypeNs},
|
resolver::{HasResolver, TypeNs},
|
||||||
type_ref::{TraitBoundModifier, TypeRef},
|
type_ref::{TraitBoundModifier, TypeRef},
|
||||||
ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, ItemContainerId,
|
ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, ItemContainerId, Lookup,
|
||||||
LocalEnumVariantId, Lookup, OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId,
|
OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId,
|
||||||
TypeParamId,
|
|
||||||
};
|
};
|
||||||
use hir_expand::name::Name;
|
use hir_expand::name::Name;
|
||||||
use intern::Interned;
|
use intern::Interned;
|
||||||
@ -355,7 +354,7 @@ 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.parent.into()),
|
GenericDefId::EnumVariantId(it) => return Some(it.lookup(db).parent.into()),
|
||||||
GenericDefId::AdtId(_)
|
GenericDefId::AdtId(_)
|
||||||
| GenericDefId::TraitId(_)
|
| GenericDefId::TraitId(_)
|
||||||
| GenericDefId::ImplId(_)
|
| GenericDefId::ImplId(_)
|
||||||
@ -435,10 +434,12 @@ pub(crate) fn detect_variant_from_bytes<'a>(
|
|||||||
trait_env: Arc<TraitEnvironment>,
|
trait_env: Arc<TraitEnvironment>,
|
||||||
b: &[u8],
|
b: &[u8],
|
||||||
e: EnumId,
|
e: EnumId,
|
||||||
) -> Option<(LocalEnumVariantId, &'a Layout)> {
|
) -> Option<(EnumVariantId, &'a Layout)> {
|
||||||
let krate = trait_env.krate;
|
let krate = trait_env.krate;
|
||||||
let (var_id, var_layout) = match &layout.variants {
|
let (var_id, var_layout) = match &layout.variants {
|
||||||
hir_def::layout::Variants::Single { index } => (index.0, &*layout),
|
hir_def::layout::Variants::Single { index } => {
|
||||||
|
(db.enum_data(e).variants[index.0].0, &*layout)
|
||||||
|
}
|
||||||
hir_def::layout::Variants::Multiple { tag, tag_encoding, variants, .. } => {
|
hir_def::layout::Variants::Multiple { tag, tag_encoding, variants, .. } => {
|
||||||
let target_data_layout = db.target_data_layout(krate)?;
|
let target_data_layout = db.target_data_layout(krate)?;
|
||||||
let size = tag.size(&*target_data_layout).bytes_usize();
|
let size = tag.size(&*target_data_layout).bytes_usize();
|
||||||
@ -446,11 +447,12 @@ pub(crate) fn detect_variant_from_bytes<'a>(
|
|||||||
let tag = i128::from_le_bytes(pad16(&b[offset..offset + size], false));
|
let tag = i128::from_le_bytes(pad16(&b[offset..offset + size], false));
|
||||||
match tag_encoding {
|
match tag_encoding {
|
||||||
TagEncoding::Direct => {
|
TagEncoding::Direct => {
|
||||||
let x = variants.iter_enumerated().find(|x| {
|
let (var_idx, layout) =
|
||||||
db.const_eval_discriminant(EnumVariantId { parent: e, local_id: x.0 .0 })
|
variants.iter_enumerated().find_map(|(var_idx, v)| {
|
||||||
== Ok(tag)
|
let def = db.enum_data(e).variants[var_idx.0].0;
|
||||||
|
(db.const_eval_discriminant(def) == Ok(tag)).then_some((def, v))
|
||||||
})?;
|
})?;
|
||||||
(x.0 .0, x.1)
|
(var_idx, layout)
|
||||||
}
|
}
|
||||||
TagEncoding::Niche { untagged_variant, niche_start, .. } => {
|
TagEncoding::Niche { untagged_variant, niche_start, .. } => {
|
||||||
let candidate_tag = tag.wrapping_sub(*niche_start as i128) as usize;
|
let candidate_tag = tag.wrapping_sub(*niche_start as i128) as usize;
|
||||||
@ -460,7 +462,7 @@ pub(crate) fn detect_variant_from_bytes<'a>(
|
|||||||
.filter(|x| x != untagged_variant)
|
.filter(|x| x != untagged_variant)
|
||||||
.nth(candidate_tag)
|
.nth(candidate_tag)
|
||||||
.unwrap_or(*untagged_variant);
|
.unwrap_or(*untagged_variant);
|
||||||
(variant.0, &variants[variant])
|
(db.enum_data(e).variants[variant.0].0, &variants[variant])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ fn resolve_doc_path_on_(
|
|||||||
AttrDefId::FieldId(it) => it.parent.resolver(db.upcast()),
|
AttrDefId::FieldId(it) => it.parent.resolver(db.upcast()),
|
||||||
AttrDefId::AdtId(it) => it.resolver(db.upcast()),
|
AttrDefId::AdtId(it) => it.resolver(db.upcast()),
|
||||||
AttrDefId::FunctionId(it) => it.resolver(db.upcast()),
|
AttrDefId::FunctionId(it) => it.resolver(db.upcast()),
|
||||||
AttrDefId::EnumVariantId(it) => it.parent.resolver(db.upcast()),
|
AttrDefId::EnumVariantId(it) => it.resolver(db.upcast()),
|
||||||
AttrDefId::StaticId(it) => it.resolver(db.upcast()),
|
AttrDefId::StaticId(it) => it.resolver(db.upcast()),
|
||||||
AttrDefId::ConstId(it) => it.resolver(db.upcast()),
|
AttrDefId::ConstId(it) => it.resolver(db.upcast()),
|
||||||
AttrDefId::TraitId(it) => it.resolver(db.upcast()),
|
AttrDefId::TraitId(it) => it.resolver(db.upcast()),
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
pub use hir_def::db::{
|
pub use hir_def::db::{
|
||||||
AttrsQuery, BlockDefMapQuery, BlockItemTreeQueryQuery, BodyQuery, BodyWithSourceMapQuery,
|
AttrsQuery, BlockDefMapQuery, BlockItemTreeQueryQuery, BodyQuery, BodyWithSourceMapQuery,
|
||||||
ConstDataQuery, ConstVisibilityQuery, CrateDefMapQueryQuery, CrateLangItemsQuery,
|
ConstDataQuery, ConstVisibilityQuery, CrateDefMapQueryQuery, CrateLangItemsQuery,
|
||||||
CrateSupportsNoStdQuery, DefDatabase, DefDatabaseStorage, EnumDataQuery,
|
CrateSupportsNoStdQuery, DefDatabase, DefDatabaseStorage, EnumDataQuery, EnumVariantDataQuery,
|
||||||
EnumDataWithDiagnosticsQuery, ExprScopesQuery, ExternCrateDeclDataQuery,
|
EnumVariantDataWithDiagnosticsQuery, ExprScopesQuery, ExternCrateDeclDataQuery,
|
||||||
FieldVisibilitiesQuery, FieldsAttrsQuery, FieldsAttrsSourceMapQuery, FileItemTreeQuery,
|
FieldVisibilitiesQuery, FieldsAttrsQuery, FieldsAttrsSourceMapQuery, FileItemTreeQuery,
|
||||||
FunctionDataQuery, FunctionVisibilityQuery, GenericParamsQuery, ImplDataQuery,
|
FunctionDataQuery, FunctionVisibilityQuery, GenericParamsQuery, ImplDataQuery,
|
||||||
ImplDataWithDiagnosticsQuery, ImportMapQuery, InternAnonymousConstQuery, InternBlockQuery,
|
ImplDataWithDiagnosticsQuery, ImportMapQuery, InternAnonymousConstQuery, InternBlockQuery,
|
||||||
@ -19,7 +19,7 @@ pub use hir_def::db::{
|
|||||||
MacroRulesDataQuery, ProcMacroDataQuery, StaticDataQuery, StructDataQuery,
|
MacroRulesDataQuery, ProcMacroDataQuery, StaticDataQuery, StructDataQuery,
|
||||||
StructDataWithDiagnosticsQuery, TraitAliasDataQuery, TraitDataQuery,
|
StructDataWithDiagnosticsQuery, TraitAliasDataQuery, TraitDataQuery,
|
||||||
TraitDataWithDiagnosticsQuery, TypeAliasDataQuery, UnionDataQuery,
|
TraitDataWithDiagnosticsQuery, TypeAliasDataQuery, UnionDataQuery,
|
||||||
UnionDataWithDiagnosticsQuery, VariantsAttrsQuery, VariantsAttrsSourceMapQuery,
|
UnionDataWithDiagnosticsQuery,
|
||||||
};
|
};
|
||||||
pub use hir_expand::db::{
|
pub use hir_expand::db::{
|
||||||
AstIdMapQuery, DeclMacroExpanderQuery, ExpandDatabase, ExpandDatabaseStorage,
|
AstIdMapQuery, DeclMacroExpanderQuery, ExpandDatabase, ExpandDatabaseStorage,
|
||||||
|
@ -93,13 +93,13 @@ impl From<GenericParam> for GenericParamId {
|
|||||||
|
|
||||||
impl From<EnumVariantId> for Variant {
|
impl From<EnumVariantId> for Variant {
|
||||||
fn from(id: EnumVariantId) -> Self {
|
fn from(id: EnumVariantId) -> Self {
|
||||||
Variant { parent: id.parent.into(), id: id.local_id }
|
Variant { id }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Variant> for EnumVariantId {
|
impl From<Variant> for EnumVariantId {
|
||||||
fn from(def: Variant) -> Self {
|
fn from(def: Variant) -> Self {
|
||||||
EnumVariantId { parent: def.parent.id, local_id: def.id }
|
def.id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ impl HasSource for Enum {
|
|||||||
impl HasSource for Variant {
|
impl HasSource for Variant {
|
||||||
type Ast = ast::Variant;
|
type Ast = ast::Variant;
|
||||||
fn source(self, db: &dyn HirDatabase) -> Option<InFile<ast::Variant>> {
|
fn source(self, db: &dyn HirDatabase) -> Option<InFile<ast::Variant>> {
|
||||||
Some(self.parent.id.child_source(db.upcast()).map(|map| map[self.id].clone()))
|
Some(self.id.lookup(db.upcast()).source(db.upcast()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl HasSource for Function {
|
impl HasSource for Function {
|
||||||
|
@ -54,9 +54,9 @@ use hir_def::{
|
|||||||
src::HasSource as _,
|
src::HasSource as _,
|
||||||
AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId,
|
AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId,
|
||||||
EnumId, EnumVariantId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule,
|
EnumId, EnumVariantId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule,
|
||||||
ImplId, InTypeConstId, ItemContainerId, LifetimeParamId, LocalEnumVariantId, LocalFieldId,
|
ImplId, InTypeConstId, ItemContainerId, LifetimeParamId, LocalFieldId, Lookup, MacroExpander,
|
||||||
Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TupleId,
|
MacroId, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TupleId, TypeAliasId,
|
||||||
TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId,
|
TypeOrConstParamId, TypeParamId, UnionId,
|
||||||
};
|
};
|
||||||
use hir_expand::{attrs::collect_attrs, name::name, proc_macro::ProcMacroKind, MacroCallKind};
|
use hir_expand::{attrs::collect_attrs, name::name, proc_macro::ProcMacroKind, MacroCallKind};
|
||||||
use hir_ty::{
|
use hir_ty::{
|
||||||
@ -375,9 +375,7 @@ impl ModuleDef {
|
|||||||
ModuleDef::Module(it) => it.id.into(),
|
ModuleDef::Module(it) => it.id.into(),
|
||||||
ModuleDef::Const(it) => it.id.into(),
|
ModuleDef::Const(it) => it.id.into(),
|
||||||
ModuleDef::Static(it) => it.id.into(),
|
ModuleDef::Static(it) => it.id.into(),
|
||||||
ModuleDef::Variant(it) => {
|
ModuleDef::Variant(it) => it.id.into(),
|
||||||
EnumVariantId { parent: it.parent.into(), local_id: it.id }.into()
|
|
||||||
}
|
|
||||||
ModuleDef::BuiltinType(_) | ModuleDef::Macro(_) => return Vec::new(),
|
ModuleDef::BuiltinType(_) | ModuleDef::Macro(_) => return Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -586,13 +584,12 @@ impl Module {
|
|||||||
Adt::Enum(e) => {
|
Adt::Enum(e) => {
|
||||||
for v in e.variants(db) {
|
for v in e.variants(db) {
|
||||||
acc.extend(ModuleDef::Variant(v).diagnostics(db));
|
acc.extend(ModuleDef::Variant(v).diagnostics(db));
|
||||||
}
|
for diag in db.enum_variant_data_with_diagnostics(v.id).1.iter() {
|
||||||
|
|
||||||
for diag in db.enum_data_with_diagnostics(e.id).1.iter() {
|
|
||||||
emit_def_diagnostic(db, acc, diag);
|
emit_def_diagnostic(db, acc, diag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
acc.extend(def.diagnostics(db))
|
acc.extend(def.diagnostics(db))
|
||||||
}
|
}
|
||||||
ModuleDef::Macro(m) => emit_macro_def_diagnostics(db, acc, m),
|
ModuleDef::Macro(m) => emit_macro_def_diagnostics(db, acc, m),
|
||||||
@ -1084,7 +1081,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.parent.id.into(),
|
VariantDef::Variant(it) => it.id.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);
|
||||||
@ -1224,7 +1221,7 @@ impl Enum {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn variants(self, db: &dyn HirDatabase) -> Vec<Variant> {
|
pub fn variants(self, db: &dyn HirDatabase) -> Vec<Variant> {
|
||||||
db.enum_data(self.id).variants.iter().map(|(id, _)| Variant { parent: self, id }).collect()
|
db.enum_data(self.id).variants.iter().map(|&(id, _)| Variant { id }).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprOptions> {
|
pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprOptions> {
|
||||||
@ -1292,25 +1289,24 @@ impl From<&Variant> for DefWithBodyId {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct Variant {
|
pub struct Variant {
|
||||||
pub(crate) parent: Enum,
|
pub(crate) id: EnumVariantId,
|
||||||
pub(crate) id: LocalEnumVariantId,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Variant {
|
impl Variant {
|
||||||
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
||||||
self.parent.module(db)
|
Module { id: self.id.lookup(db.upcast()).container }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parent_enum(self, _db: &dyn HirDatabase) -> Enum {
|
pub fn parent_enum(self, db: &dyn HirDatabase) -> Enum {
|
||||||
self.parent
|
self.id.lookup(db.upcast()).parent.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type {
|
pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type {
|
||||||
Type::from_value_def(db, EnumVariantId { parent: self.parent.id, local_id: self.id })
|
Type::from_value_def(db, self.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
||||||
db.enum_data(self.parent.id).variants[self.id].name.clone()
|
db.enum_variant_data(self.id).name.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
|
pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
|
||||||
@ -1326,7 +1322,7 @@ impl Variant {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
|
pub(crate) fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
|
||||||
db.enum_data(self.parent.id).variants[self.id].variant_data.clone()
|
db.enum_variant_data(self.id).variant_data.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
|
pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
|
||||||
@ -1342,7 +1338,21 @@ impl Variant {
|
|||||||
let parent_layout = parent_enum.layout(db)?;
|
let parent_layout = parent_enum.layout(db)?;
|
||||||
Ok(match &parent_layout.0.variants {
|
Ok(match &parent_layout.0.variants {
|
||||||
layout::Variants::Multiple { variants, .. } => Layout(
|
layout::Variants::Multiple { variants, .. } => Layout(
|
||||||
Arc::new(variants[RustcEnumVariantIdx(self.id)].clone()),
|
{
|
||||||
|
let lookup = self.id.lookup(db.upcast());
|
||||||
|
let rustc_enum_variant_idx = lookup.id.value.index().into_raw().into_u32()
|
||||||
|
- lookup.id.item_tree(db.upcast())
|
||||||
|
[lookup.parent.lookup(db.upcast()).id.value]
|
||||||
|
.variants
|
||||||
|
.start
|
||||||
|
.index()
|
||||||
|
.into_raw()
|
||||||
|
.into_u32();
|
||||||
|
let rustc_enum_variant_idx =
|
||||||
|
RustcEnumVariantIdx(rustc_enum_variant_idx as usize);
|
||||||
|
|
||||||
|
Arc::new(variants[rustc_enum_variant_idx].clone())
|
||||||
|
},
|
||||||
db.target_data_layout(parent_enum.krate(db).into()).unwrap(),
|
db.target_data_layout(parent_enum.krate(db).into()).unwrap(),
|
||||||
),
|
),
|
||||||
_ => parent_layout,
|
_ => parent_layout,
|
||||||
@ -1547,7 +1557,7 @@ impl DefWithBody {
|
|||||||
DefWithBody::Function(it) => it.ret_type(db),
|
DefWithBody::Function(it) => it.ret_type(db),
|
||||||
DefWithBody::Static(it) => it.ty(db),
|
DefWithBody::Static(it) => it.ty(db),
|
||||||
DefWithBody::Const(it) => it.ty(db),
|
DefWithBody::Const(it) => it.ty(db),
|
||||||
DefWithBody::Variant(it) => it.parent.variant_body_ty(db),
|
DefWithBody::Variant(it) => it.parent_enum(db).variant_body_ty(db),
|
||||||
DefWithBody::InTypeConst(it) => Type::new_with_resolver_inner(
|
DefWithBody::InTypeConst(it) => Type::new_with_resolver_inner(
|
||||||
db,
|
db,
|
||||||
&DefWithBodyId::from(it.id).resolver(db.upcast()),
|
&DefWithBodyId::from(it.id).resolver(db.upcast()),
|
||||||
|
@ -262,9 +262,7 @@ impl<'a> SymbolCollector<'a> {
|
|||||||
DefWithBodyId::FunctionId(id) => Some(self.db.function_data(id).name.to_smol_str()),
|
DefWithBodyId::FunctionId(id) => Some(self.db.function_data(id).name.to_smol_str()),
|
||||||
DefWithBodyId::StaticId(id) => Some(self.db.static_data(id).name.to_smol_str()),
|
DefWithBodyId::StaticId(id) => Some(self.db.static_data(id).name.to_smol_str()),
|
||||||
DefWithBodyId::ConstId(id) => Some(self.db.const_data(id).name.as_ref()?.to_smol_str()),
|
DefWithBodyId::ConstId(id) => Some(self.db.const_data(id).name.as_ref()?.to_smol_str()),
|
||||||
DefWithBodyId::VariantId(id) => {
|
DefWithBodyId::VariantId(id) => Some(self.db.enum_variant_data(id).name.to_smol_str()),
|
||||||
Some(self.db.enum_data(id.parent).variants[id.local_id].name.to_smol_str())
|
|
||||||
}
|
|
||||||
DefWithBodyId::InTypeConstId(_) => Some("in type const".into()),
|
DefWithBodyId::InTypeConstId(_) => Some("in type const".into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,8 @@ impl RootDatabase {
|
|||||||
hir::db::UnionDataQuery
|
hir::db::UnionDataQuery
|
||||||
hir::db::UnionDataWithDiagnosticsQuery
|
hir::db::UnionDataWithDiagnosticsQuery
|
||||||
hir::db::EnumDataQuery
|
hir::db::EnumDataQuery
|
||||||
hir::db::EnumDataWithDiagnosticsQuery
|
hir::db::EnumVariantDataWithDiagnosticsQuery
|
||||||
|
hir::db::EnumVariantDataQuery
|
||||||
hir::db::ImplDataQuery
|
hir::db::ImplDataQuery
|
||||||
hir::db::ImplDataWithDiagnosticsQuery
|
hir::db::ImplDataWithDiagnosticsQuery
|
||||||
hir::db::TraitDataQuery
|
hir::db::TraitDataQuery
|
||||||
@ -158,9 +159,7 @@ impl RootDatabase {
|
|||||||
hir::db::BodyQuery
|
hir::db::BodyQuery
|
||||||
hir::db::ExprScopesQuery
|
hir::db::ExprScopesQuery
|
||||||
hir::db::GenericParamsQuery
|
hir::db::GenericParamsQuery
|
||||||
hir::db::VariantsAttrsQuery
|
|
||||||
hir::db::FieldsAttrsQuery
|
hir::db::FieldsAttrsQuery
|
||||||
hir::db::VariantsAttrsSourceMapQuery
|
|
||||||
hir::db::FieldsAttrsSourceMapQuery
|
hir::db::FieldsAttrsSourceMapQuery
|
||||||
hir::db::AttrsQuery
|
hir::db::AttrsQuery
|
||||||
hir::db::CrateLangItemsQuery
|
hir::db::CrateLangItemsQuery
|
||||||
|
@ -222,7 +222,8 @@ impl RootDatabase {
|
|||||||
hir_db::UnionDataQuery
|
hir_db::UnionDataQuery
|
||||||
hir_db::UnionDataWithDiagnosticsQuery
|
hir_db::UnionDataWithDiagnosticsQuery
|
||||||
hir_db::EnumDataQuery
|
hir_db::EnumDataQuery
|
||||||
hir_db::EnumDataWithDiagnosticsQuery
|
hir_db::EnumDataQuery
|
||||||
|
hir_db::EnumVariantDataWithDiagnosticsQuery
|
||||||
hir_db::ImplDataQuery
|
hir_db::ImplDataQuery
|
||||||
hir_db::ImplDataWithDiagnosticsQuery
|
hir_db::ImplDataWithDiagnosticsQuery
|
||||||
hir_db::TraitDataQuery
|
hir_db::TraitDataQuery
|
||||||
@ -239,9 +240,7 @@ impl RootDatabase {
|
|||||||
hir_db::BodyQuery
|
hir_db::BodyQuery
|
||||||
hir_db::ExprScopesQuery
|
hir_db::ExprScopesQuery
|
||||||
hir_db::GenericParamsQuery
|
hir_db::GenericParamsQuery
|
||||||
hir_db::VariantsAttrsQuery
|
|
||||||
hir_db::FieldsAttrsQuery
|
hir_db::FieldsAttrsQuery
|
||||||
hir_db::VariantsAttrsSourceMapQuery
|
|
||||||
hir_db::FieldsAttrsSourceMapQuery
|
hir_db::FieldsAttrsSourceMapQuery
|
||||||
hir_db::AttrsQuery
|
hir_db::AttrsQuery
|
||||||
hir_db::CrateLangItemsQuery
|
hir_db::CrateLangItemsQuery
|
||||||
|
Loading…
x
Reference in New Issue
Block a user