mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 04:44:57 +00:00
Implemented basic enum const eval
This commit is contained in:
parent
f64c95600c
commit
997fc46efa
14 changed files with 227 additions and 17 deletions
|
@ -27,7 +27,7 @@ use crate::{
|
||||||
macro_id_to_def_id,
|
macro_id_to_def_id,
|
||||||
nameres::DefMap,
|
nameres::DefMap,
|
||||||
path::{ModPath, Path},
|
path::{ModPath, Path},
|
||||||
src::HasSource,
|
src::{HasChildSource, HasSource},
|
||||||
AsMacroCall, BlockId, DefWithBodyId, HasModule, LocalModuleId, Lookup, MacroId, ModuleId,
|
AsMacroCall, BlockId, DefWithBodyId, HasModule, LocalModuleId, Lookup, MacroId, ModuleId,
|
||||||
UnresolvedMacro,
|
UnresolvedMacro,
|
||||||
};
|
};
|
||||||
|
@ -324,6 +324,13 @@ impl Body {
|
||||||
let src = s.source(db);
|
let src = s.source(db);
|
||||||
(src.file_id, s.module(db), src.value.body())
|
(src.file_id, s.module(db), src.value.body())
|
||||||
}
|
}
|
||||||
|
DefWithBodyId::VariantId(v) => {
|
||||||
|
let e = v.parent.lookup(db);
|
||||||
|
let src = v.parent.child_source(db);
|
||||||
|
let variant = &src.value[v.local_id];
|
||||||
|
// TODO(ole): Handle missing exprs (+1 to the prev)
|
||||||
|
(src.file_id, e.container, variant.expr())
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let expander = Expander::new(db, file_id, module);
|
let expander = Expander::new(db, file_id, module);
|
||||||
let (mut body, source_map) = Body::new(db, expander, params, body);
|
let (mut body, source_map) = Body::new(db, expander, params, body);
|
||||||
|
|
|
@ -474,16 +474,25 @@ pub enum DefWithBodyId {
|
||||||
FunctionId(FunctionId),
|
FunctionId(FunctionId),
|
||||||
StaticId(StaticId),
|
StaticId(StaticId),
|
||||||
ConstId(ConstId),
|
ConstId(ConstId),
|
||||||
|
VariantId(EnumVariantId),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_from!(FunctionId, ConstId, StaticId for DefWithBodyId);
|
impl_from!(FunctionId, ConstId, StaticId for DefWithBodyId);
|
||||||
|
|
||||||
|
// FIXME: Rename EnumVariantId to VariantId so that the macro above can be used
|
||||||
|
impl From<EnumVariantId> for DefWithBodyId {
|
||||||
|
fn from(id: EnumVariantId) -> Self {
|
||||||
|
DefWithBodyId::VariantId(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl DefWithBodyId {
|
impl DefWithBodyId {
|
||||||
pub fn as_generic_def_id(self) -> Option<GenericDefId> {
|
pub fn as_generic_def_id(self) -> Option<GenericDefId> {
|
||||||
match self {
|
match self {
|
||||||
DefWithBodyId::FunctionId(f) => Some(f.into()),
|
DefWithBodyId::FunctionId(f) => Some(f.into()),
|
||||||
DefWithBodyId::StaticId(_) => None,
|
DefWithBodyId::StaticId(_) => None,
|
||||||
DefWithBodyId::ConstId(c) => Some(c.into()),
|
DefWithBodyId::ConstId(c) => Some(c.into()),
|
||||||
|
DefWithBodyId::VariantId(c) => Some(c.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -681,6 +690,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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -691,6 +701,7 @@ impl DefWithBodyId {
|
||||||
DefWithBodyId::FunctionId(it) => it.lookup(db).id.value.into(),
|
DefWithBodyId::FunctionId(it) => it.lookup(db).id.value.into(),
|
||||||
DefWithBodyId::StaticId(it) => it.lookup(db).id.value.into(),
|
DefWithBodyId::StaticId(it) => it.lookup(db).id.value.into(),
|
||||||
DefWithBodyId::ConstId(it) => it.lookup(db).id.value.into(),
|
DefWithBodyId::ConstId(it) => it.lookup(db).id.value.into(),
|
||||||
|
DefWithBodyId::VariantId(it) => it.parent.lookup(db).id.value.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -839,6 +839,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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ use hir_def::{
|
||||||
path::ModPath,
|
path::ModPath,
|
||||||
resolver::{resolver_for_expr, ResolveValueResult, Resolver, ValueNs},
|
resolver::{resolver_for_expr, ResolveValueResult, Resolver, ValueNs},
|
||||||
type_ref::ConstScalar,
|
type_ref::ConstScalar,
|
||||||
ConstId, DefWithBodyId,
|
ConstId, DefWithBodyId, EnumVariantId,
|
||||||
};
|
};
|
||||||
use la_arena::{Arena, Idx};
|
use la_arena::{Arena, Idx};
|
||||||
use stdx::never;
|
use stdx::never;
|
||||||
|
@ -339,6 +339,7 @@ pub fn eval_const(
|
||||||
ValueNs::GenericParam(_) => {
|
ValueNs::GenericParam(_) => {
|
||||||
Err(ConstEvalError::NotSupported("const generic without substitution"))
|
Err(ConstEvalError::NotSupported("const generic without substitution"))
|
||||||
}
|
}
|
||||||
|
ValueNs::EnumVariantId(id) => ctx.db.const_eval_variant(id), // TODO(ole): Assuming this is all that has to happen?
|
||||||
_ => Err(ConstEvalError::NotSupported("path that are not const or local")),
|
_ => Err(ConstEvalError::NotSupported("path that are not const or local")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -412,6 +413,14 @@ pub(crate) fn const_eval_recover(
|
||||||
Err(ConstEvalError::Loop)
|
Err(ConstEvalError::Loop)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn const_eval_recover_variant(
|
||||||
|
_: &dyn HirDatabase,
|
||||||
|
_: &[String],
|
||||||
|
_: &EnumVariantId,
|
||||||
|
) -> Result<ComputedExpr, ConstEvalError> {
|
||||||
|
Err(ConstEvalError::Loop)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn const_eval_query(
|
pub(crate) fn const_eval_query(
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
const_id: ConstId,
|
const_id: ConstId,
|
||||||
|
@ -433,6 +442,26 @@ pub(crate) fn const_eval_query(
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn const_eval_query_variant(
|
||||||
|
db: &dyn HirDatabase,
|
||||||
|
variant_id: EnumVariantId,
|
||||||
|
) -> Result<ComputedExpr, ConstEvalError> {
|
||||||
|
let def = variant_id.into();
|
||||||
|
let body = db.body(def);
|
||||||
|
let infer = &db.infer(def);
|
||||||
|
eval_const(
|
||||||
|
body.body_expr,
|
||||||
|
&mut ConstEvalCtx {
|
||||||
|
db,
|
||||||
|
owner: def,
|
||||||
|
exprs: &body.exprs,
|
||||||
|
pats: &body.pats,
|
||||||
|
local_data: HashMap::default(),
|
||||||
|
infer,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn eval_to_const<'a>(
|
pub(crate) fn eval_to_const<'a>(
|
||||||
expr: Idx<Expr>,
|
expr: Idx<Expr>,
|
||||||
mode: ParamLoweringMode,
|
mode: ParamLoweringMode,
|
||||||
|
|
|
@ -6,8 +6,9 @@ use std::sync::Arc;
|
||||||
use arrayvec::ArrayVec;
|
use arrayvec::ArrayVec;
|
||||||
use base_db::{impl_intern_key, salsa, CrateId, Upcast};
|
use base_db::{impl_intern_key, salsa, CrateId, Upcast};
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
db::DefDatabase, expr::ExprId, BlockId, ConstId, ConstParamId, DefWithBodyId, FunctionId,
|
db::DefDatabase, expr::ExprId, BlockId, ConstId, ConstParamId, DefWithBodyId, EnumVariantId,
|
||||||
GenericDefId, ImplId, LifetimeParamId, LocalFieldId, TypeOrConstParamId, VariantId,
|
FunctionId, GenericDefId, ImplId, LifetimeParamId, LocalFieldId, Lookup, TypeOrConstParamId,
|
||||||
|
VariantId,
|
||||||
};
|
};
|
||||||
use la_arena::ArenaMap;
|
use la_arena::ArenaMap;
|
||||||
|
|
||||||
|
@ -47,6 +48,10 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||||
#[salsa::cycle(crate::consteval::const_eval_recover)]
|
#[salsa::cycle(crate::consteval::const_eval_recover)]
|
||||||
fn const_eval(&self, def: ConstId) -> Result<ComputedExpr, ConstEvalError>;
|
fn const_eval(&self, def: ConstId) -> Result<ComputedExpr, ConstEvalError>;
|
||||||
|
|
||||||
|
#[salsa::invoke(crate::consteval::const_eval_query_variant)]
|
||||||
|
#[salsa::cycle(crate::consteval::const_eval_recover_variant)]
|
||||||
|
fn const_eval_variant(&self, def: EnumVariantId) -> Result<ComputedExpr, ConstEvalError>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::lower::impl_trait_query)]
|
#[salsa::invoke(crate::lower::impl_trait_query)]
|
||||||
fn impl_trait(&self, def: ImplId) -> Option<Binders<TraitRef>>;
|
fn impl_trait(&self, def: ImplId) -> Option<Binders<TraitRef>>;
|
||||||
|
|
||||||
|
@ -188,6 +193,13 @@ fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult>
|
||||||
DefWithBodyId::ConstId(it) => {
|
DefWithBodyId::ConstId(it) => {
|
||||||
db.const_data(it).name.clone().unwrap_or_else(Name::missing).to_string()
|
db.const_data(it).name.clone().unwrap_or_else(Name::missing).to_string()
|
||||||
}
|
}
|
||||||
|
DefWithBodyId::VariantId(it) => {
|
||||||
|
let up_db: &dyn DefDatabase = db.upcast();
|
||||||
|
let loc = it.parent.lookup(up_db);
|
||||||
|
let item_tree = loc.id.item_tree(up_db);
|
||||||
|
let konst = &item_tree[loc.id.value];
|
||||||
|
konst.name.to_string()
|
||||||
|
}
|
||||||
});
|
});
|
||||||
db.infer_query(def)
|
db.infer_query(def)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,9 @@ pub fn missing_unsafe(db: &dyn HirDatabase, def: DefWithBodyId) -> Vec<ExprId> {
|
||||||
|
|
||||||
let is_unsafe = match def {
|
let is_unsafe = match def {
|
||||||
DefWithBodyId::FunctionId(it) => db.function_data(it).has_unsafe_kw(),
|
DefWithBodyId::FunctionId(it) => db.function_data(it).has_unsafe_kw(),
|
||||||
DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) => false,
|
DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) | DefWithBodyId::VariantId(_) => {
|
||||||
|
false
|
||||||
|
}
|
||||||
};
|
};
|
||||||
if is_unsafe {
|
if is_unsafe {
|
||||||
return res;
|
return res;
|
||||||
|
|
|
@ -67,6 +67,14 @@ 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::FunctionId(f) => ctx.collect_fn(f),
|
DefWithBodyId::FunctionId(f) => ctx.collect_fn(f),
|
||||||
DefWithBodyId::StaticId(s) => ctx.collect_static(&db.static_data(s)),
|
DefWithBodyId::StaticId(s) => ctx.collect_static(&db.static_data(s)),
|
||||||
|
DefWithBodyId::VariantId(v) => {
|
||||||
|
//let def = AttrDefId::EnumVariantId(v);
|
||||||
|
//let attrs = db.attrs(def);
|
||||||
|
//let repr = attrs.by_key("repr").attrs().next().unwrap();
|
||||||
|
//let ident = repr.single_ident_value().unwrap().text;
|
||||||
|
// TODO(ole): Get the real type
|
||||||
|
ctx.return_ty = TyBuilder::def_ty(db, v.parent.into()).fill_with_unknown().build()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.infer_body();
|
ctx.infer_body();
|
||||||
|
|
|
@ -16,7 +16,7 @@ use base_db::{fixture::WithFixture, 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,
|
db::{DefDatabase, InternDatabase},
|
||||||
expr::{ExprId, PatId},
|
expr::{ExprId, PatId},
|
||||||
item_scope::ItemScope,
|
item_scope::ItemScope,
|
||||||
nameres::DefMap,
|
nameres::DefMap,
|
||||||
|
@ -135,6 +135,10 @@ fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_sour
|
||||||
let loc = it.lookup(&db);
|
let loc = it.lookup(&db);
|
||||||
loc.source(&db).value.syntax().text_range().start()
|
loc.source(&db).value.syntax().text_range().start()
|
||||||
}
|
}
|
||||||
|
DefWithBodyId::VariantId(it) => {
|
||||||
|
let loc = db.lookup_intern_enum(it.parent);
|
||||||
|
loc.source(&db).value.syntax().text_range().start()
|
||||||
|
}
|
||||||
});
|
});
|
||||||
let mut unexpected_type_mismatches = String::new();
|
let mut unexpected_type_mismatches = String::new();
|
||||||
for def in defs {
|
for def in defs {
|
||||||
|
@ -388,6 +392,10 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
|
||||||
let loc = it.lookup(&db);
|
let loc = it.lookup(&db);
|
||||||
loc.source(&db).value.syntax().text_range().start()
|
loc.source(&db).value.syntax().text_range().start()
|
||||||
}
|
}
|
||||||
|
DefWithBodyId::VariantId(it) => {
|
||||||
|
let loc = db.lookup_intern_enum(it.parent);
|
||||||
|
loc.source(&db).value.syntax().text_range().start()
|
||||||
|
}
|
||||||
});
|
});
|
||||||
for def in defs {
|
for def in defs {
|
||||||
let (_body, source_map) = db.body_with_source_map(def);
|
let (_body, source_map) = db.body_with_source_map(def);
|
||||||
|
|
|
@ -140,6 +140,7 @@ impl From<DefWithBody> for DefWithBodyId {
|
||||||
DefWithBody::Function(it) => DefWithBodyId::FunctionId(it.id),
|
DefWithBody::Function(it) => DefWithBodyId::FunctionId(it.id),
|
||||||
DefWithBody::Static(it) => DefWithBodyId::StaticId(it.id),
|
DefWithBody::Static(it) => DefWithBodyId::StaticId(it.id),
|
||||||
DefWithBody::Const(it) => DefWithBodyId::ConstId(it.id),
|
DefWithBody::Const(it) => DefWithBodyId::ConstId(it.id),
|
||||||
|
DefWithBody::Variant(it) => DefWithBodyId::VariantId(it.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,6 +151,7 @@ impl From<DefWithBodyId> for DefWithBody {
|
||||||
DefWithBodyId::FunctionId(it) => DefWithBody::Function(it.into()),
|
DefWithBodyId::FunctionId(it) => DefWithBody::Function(it.into()),
|
||||||
DefWithBodyId::StaticId(it) => DefWithBody::Static(it.into()),
|
DefWithBodyId::StaticId(it) => DefWithBody::Static(it.into()),
|
||||||
DefWithBodyId::ConstId(it) => DefWithBody::Const(it.into()),
|
DefWithBodyId::ConstId(it) => DefWithBody::Const(it.into()),
|
||||||
|
DefWithBodyId::VariantId(it) => DefWithBody::Variant(it.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,9 +174,7 @@ impl From<GenericDef> for GenericDefId {
|
||||||
GenericDef::Trait(it) => GenericDefId::TraitId(it.id),
|
GenericDef::Trait(it) => GenericDefId::TraitId(it.id),
|
||||||
GenericDef::TypeAlias(it) => GenericDefId::TypeAliasId(it.id),
|
GenericDef::TypeAlias(it) => GenericDefId::TypeAliasId(it.id),
|
||||||
GenericDef::Impl(it) => GenericDefId::ImplId(it.id),
|
GenericDef::Impl(it) => GenericDefId::ImplId(it.id),
|
||||||
GenericDef::Variant(it) => {
|
GenericDef::Variant(it) => GenericDefId::EnumVariantId(it.into()),
|
||||||
GenericDefId::EnumVariantId(EnumVariantId { parent: it.parent.id, local_id: it.id })
|
|
||||||
}
|
|
||||||
GenericDef::Const(it) => GenericDefId::ConstId(it.id),
|
GenericDef::Const(it) => GenericDefId::ConstId(it.id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,9 +188,7 @@ impl From<GenericDefId> for GenericDef {
|
||||||
GenericDefId::TraitId(it) => GenericDef::Trait(it.into()),
|
GenericDefId::TraitId(it) => GenericDef::Trait(it.into()),
|
||||||
GenericDefId::TypeAliasId(it) => GenericDef::TypeAlias(it.into()),
|
GenericDefId::TypeAliasId(it) => GenericDef::TypeAlias(it.into()),
|
||||||
GenericDefId::ImplId(it) => GenericDef::Impl(it.into()),
|
GenericDefId::ImplId(it) => GenericDef::Impl(it.into()),
|
||||||
GenericDefId::EnumVariantId(it) => {
|
GenericDefId::EnumVariantId(it) => GenericDef::Variant(it.into()),
|
||||||
GenericDef::Variant(Variant { parent: it.parent.into(), id: it.local_id })
|
|
||||||
}
|
|
||||||
GenericDefId::ConstId(it) => GenericDef::Const(it.into()),
|
GenericDefId::ConstId(it) => GenericDef::Const(it.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ use once_cell::unsync::Lazy;
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use stdx::{impl_from, never};
|
use stdx::{impl_from, never};
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, HasAttrs as _, HasDocComments, HasName},
|
ast::{self, Expr, HasAttrs as _, HasDocComments, HasName},
|
||||||
AstNode, AstPtr, SmolStr, SyntaxNodePtr, TextRange, T,
|
AstNode, AstPtr, SmolStr, SyntaxNodePtr, TextRange, T,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -962,11 +962,16 @@ impl HasVisibility for Enum {
|
||||||
|
|
||||||
#[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 parent: Enum,
|
||||||
pub(crate) id: LocalEnumVariantId,
|
pub id: LocalEnumVariantId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Variant {
|
impl Variant {
|
||||||
|
pub fn value(self, db: &dyn HirDatabase) -> Option<Expr> {
|
||||||
|
// TODO(ole): Handle missing exprs (+1 to the prev)
|
||||||
|
self.source(db)?.value.expr()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
||||||
self.parent.module(db)
|
self.parent.module(db)
|
||||||
}
|
}
|
||||||
|
@ -1129,6 +1134,7 @@ pub enum DefWithBody {
|
||||||
Function(Function),
|
Function(Function),
|
||||||
Static(Static),
|
Static(Static),
|
||||||
Const(Const),
|
Const(Const),
|
||||||
|
Variant(Variant),
|
||||||
}
|
}
|
||||||
impl_from!(Function, Const, Static for DefWithBody);
|
impl_from!(Function, Const, Static for DefWithBody);
|
||||||
|
|
||||||
|
@ -1138,6 +1144,7 @@ impl DefWithBody {
|
||||||
DefWithBody::Const(c) => c.module(db),
|
DefWithBody::Const(c) => c.module(db),
|
||||||
DefWithBody::Function(f) => f.module(db),
|
DefWithBody::Function(f) => f.module(db),
|
||||||
DefWithBody::Static(s) => s.module(db),
|
DefWithBody::Static(s) => s.module(db),
|
||||||
|
DefWithBody::Variant(v) => v.module(db),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1146,6 +1153,7 @@ impl DefWithBody {
|
||||||
DefWithBody::Function(f) => Some(f.name(db)),
|
DefWithBody::Function(f) => Some(f.name(db)),
|
||||||
DefWithBody::Static(s) => Some(s.name(db)),
|
DefWithBody::Static(s) => Some(s.name(db)),
|
||||||
DefWithBody::Const(c) => c.name(db),
|
DefWithBody::Const(c) => c.name(db),
|
||||||
|
DefWithBody::Variant(v) => Some(v.name(db)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1155,6 +1163,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.ty(db),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1379,6 +1388,7 @@ impl DefWithBody {
|
||||||
DefWithBody::Function(it) => it.into(),
|
DefWithBody::Function(it) => it.into(),
|
||||||
DefWithBody::Static(it) => it.into(),
|
DefWithBody::Static(it) => it.into(),
|
||||||
DefWithBody::Const(it) => it.into(),
|
DefWithBody::Const(it) => it.into(),
|
||||||
|
DefWithBody::Variant(it) => it.into(),
|
||||||
};
|
};
|
||||||
for diag in hir_ty::diagnostics::incorrect_case(db, krate, def.into()) {
|
for diag in hir_ty::diagnostics::incorrect_case(db, krate, def.into()) {
|
||||||
acc.push(diag.into())
|
acc.push(diag.into())
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//! File symbol extraction.
|
//! File symbol extraction.
|
||||||
|
|
||||||
use base_db::FileRange;
|
use base_db::FileRange;
|
||||||
|
use hir_def::db::DefDatabase;
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
item_tree::ItemTreeNode, src::HasSource, AdtId, AssocItemId, AssocItemLoc, DefWithBodyId,
|
item_tree::ItemTreeNode, src::HasSource, AdtId, AssocItemId, AssocItemLoc, DefWithBodyId,
|
||||||
HasModule, ImplId, ItemContainerId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId,
|
HasModule, ImplId, ItemContainerId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId,
|
||||||
|
@ -244,6 +245,10 @@ impl<'a> SymbolCollector<'a> {
|
||||||
DefWithBodyId::ConstId(id) => Some(
|
DefWithBodyId::ConstId(id) => Some(
|
||||||
id.lookup(self.db.upcast()).source(self.db.upcast()).value.name()?.text().into(),
|
id.lookup(self.db.upcast()).source(self.db.upcast()).value.name()?.text().into(),
|
||||||
),
|
),
|
||||||
|
DefWithBodyId::VariantId(id) => Some({
|
||||||
|
let up_db: &dyn DefDatabase = self.db.upcast();
|
||||||
|
up_db.lookup_intern_enum(id.parent).source(up_db).value.name()?.text().into()
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -236,6 +236,7 @@ impl Definition {
|
||||||
DefWithBody::Function(f) => f.source(db).map(|src| src.syntax().cloned()),
|
DefWithBody::Function(f) => f.source(db).map(|src| src.syntax().cloned()),
|
||||||
DefWithBody::Const(c) => c.source(db).map(|src| src.syntax().cloned()),
|
DefWithBody::Const(c) => c.source(db).map(|src| src.syntax().cloned()),
|
||||||
DefWithBody::Static(s) => s.source(db).map(|src| src.syntax().cloned()),
|
DefWithBody::Static(s) => s.source(db).map(|src| src.syntax().cloned()),
|
||||||
|
DefWithBody::Variant(v) => v.source(db).map(|src| src.syntax().cloned()),
|
||||||
};
|
};
|
||||||
return match def {
|
return match def {
|
||||||
Some(def) => SearchScope::file_range(def.as_ref().original_file_range(db)),
|
Some(def) => SearchScope::file_range(def.as_ref().original_file_range(db)),
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use hir::{AsAssocItem, AttributeTemplate, HasAttrs, HasSource, HirDisplay, Semantics, TypeInfo};
|
use hir::{
|
||||||
|
db::HirDatabase, AsAssocItem, AttributeTemplate, HasAttrs, HasSource, HirDisplay, Semantics, TypeInfo,
|
||||||
|
};
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
base_db::SourceDatabase,
|
base_db::SourceDatabase,
|
||||||
defs::Definition,
|
defs::Definition,
|
||||||
|
@ -346,7 +348,14 @@ pub(super) fn definition(
|
||||||
Definition::Module(it) => label_and_docs(db, it),
|
Definition::Module(it) => label_and_docs(db, it),
|
||||||
Definition::Function(it) => label_and_docs(db, it),
|
Definition::Function(it) => label_and_docs(db, it),
|
||||||
Definition::Adt(it) => label_and_docs(db, it),
|
Definition::Adt(it) => label_and_docs(db, it),
|
||||||
Definition::Variant(it) => label_and_docs(db, it),
|
Definition::Variant(it) => label_value_and_docs(db, it, |&it| {
|
||||||
|
let hir_db: &dyn HirDatabase = db;
|
||||||
|
let body = hir_db.const_eval_variant(it.into());
|
||||||
|
match body {
|
||||||
|
Ok(x) => Some(format!("{}", x)),
|
||||||
|
Err(_) => it.value(db).map(|s| format!("{}", s)),
|
||||||
|
}
|
||||||
|
}),
|
||||||
Definition::Const(it) => label_value_and_docs(db, it, |it| {
|
Definition::Const(it) => label_value_and_docs(db, it, |it| {
|
||||||
let body = it.eval(db);
|
let body = it.eval(db);
|
||||||
match body {
|
match body {
|
||||||
|
|
|
@ -3527,6 +3527,86 @@ impl<const LEN: usize> Foo<LEN$0> {}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hover_const_eval_variant() {
|
||||||
|
// show hex for <10
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
#[repr(u8)]
|
||||||
|
enum E {
|
||||||
|
/// This is a doc
|
||||||
|
A$0 = 1 << 3,
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
*A*
|
||||||
|
|
||||||
|
```rust
|
||||||
|
test::E
|
||||||
|
```
|
||||||
|
|
||||||
|
```rust
|
||||||
|
A = 8
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
This is a doc
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
// show hex for >10
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
#[repr(u8)]
|
||||||
|
enum E {
|
||||||
|
/// This is a doc
|
||||||
|
A$0 = (1 << 3) + (1 << 2),
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
*A*
|
||||||
|
|
||||||
|
```rust
|
||||||
|
test::E
|
||||||
|
```
|
||||||
|
|
||||||
|
```rust
|
||||||
|
A = 12 (0xC)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
This is a doc
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
// enums in const eval
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
#[repr(u8)]
|
||||||
|
enum E {
|
||||||
|
A = 1,
|
||||||
|
/// This is a doc
|
||||||
|
B$0 = E::A + 1,
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
*B*
|
||||||
|
|
||||||
|
```rust
|
||||||
|
test::E
|
||||||
|
```
|
||||||
|
|
||||||
|
```rust
|
||||||
|
B = 2
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
This is a doc
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn hover_const_eval() {
|
fn hover_const_eval() {
|
||||||
// show hex for <10
|
// show hex for <10
|
||||||
|
@ -3820,6 +3900,35 @@ fn foo() {
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
This is a doc
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
enum E {
|
||||||
|
/// This is a doc
|
||||||
|
A = 3,
|
||||||
|
}
|
||||||
|
fn foo(e: E) {
|
||||||
|
match e {
|
||||||
|
E::A$0 => (),
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
*A*
|
||||||
|
|
||||||
|
```rust
|
||||||
|
test::E
|
||||||
|
```
|
||||||
|
|
||||||
|
```rust
|
||||||
|
A = 3
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
This is a doc
|
This is a doc
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue