Skip to content

Commit fdbebcc

Browse files
bors[bot]Lapz
andcommitted
Merge #1076
1076: Const body inference r=flodiebold a=Lapz This is the second part of #887. I've added type inference on const bodies and introduced the DefWithBody containing Function, Const and Static. I want to add tests but im unsure on how I would go about testing that completions work. Co-authored-by: Lenard Pratt <[email protected]>
2 parents 01a54f0 + b9d2c2c commit fdbebcc

File tree

10 files changed

+231
-49
lines changed

10 files changed

+231
-49
lines changed

crates/ra_hir/src/code_model_api.rs

+60-5
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,45 @@ impl Docs for EnumVariant {
429429
}
430430
}
431431

432+
/// The defs which have a body.
433+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
434+
pub enum DefWithBody {
435+
Function(Function),
436+
Const(Const),
437+
Static(Static),
438+
}
439+
440+
impl_froms!(DefWithBody: Function, Const, Static);
441+
442+
impl DefWithBody {
443+
pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> {
444+
db.infer(*self)
445+
}
446+
447+
pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
448+
db.body_with_source_map(*self).1
449+
}
450+
451+
pub fn body(&self, db: &impl HirDatabase) -> Arc<Body> {
452+
db.body_hir(*self)
453+
}
454+
455+
/// Builds a resolver for code inside this item.
456+
pub fn resolver(&self, db: &impl HirDatabase) -> Resolver {
457+
match *self {
458+
DefWithBody::Const(ref c) => c.resolver(db),
459+
DefWithBody::Function(ref f) => f.resolver(db),
460+
DefWithBody::Static(ref s) => s.resolver(db),
461+
}
462+
}
463+
464+
pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSourceMap {
465+
let scopes = db.expr_scopes(*self);
466+
let source_map = db.body_with_source_map(*self).1;
467+
ScopesWithSourceMap { scopes, source_map }
468+
}
469+
}
470+
432471
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
433472
pub struct Function {
434473
pub(crate) id: FunctionId,
@@ -479,20 +518,20 @@ impl Function {
479518
}
480519

481520
pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
482-
db.body_with_source_map(*self).1
521+
db.body_with_source_map((*self).into()).1
483522
}
484523

485524
pub fn body(&self, db: &impl HirDatabase) -> Arc<Body> {
486-
db.body_hir(*self)
525+
db.body_hir((*self).into())
487526
}
488527

489528
pub fn ty(&self, db: &impl HirDatabase) -> Ty {
490529
db.type_for_def((*self).into(), Namespace::Values)
491530
}
492531

493532
pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSourceMap {
494-
let scopes = db.expr_scopes(*self);
495-
let source_map = db.body_with_source_map(*self).1;
533+
let scopes = db.expr_scopes((*self).into());
534+
let source_map = db.body_with_source_map((*self).into()).1;
496535
ScopesWithSourceMap { scopes, source_map }
497536
}
498537

@@ -501,7 +540,7 @@ impl Function {
501540
}
502541

503542
pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> {
504-
db.infer(*self)
543+
db.infer((*self).into())
505544
}
506545

507546
pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> {
@@ -557,6 +596,14 @@ impl Const {
557596
db.const_signature(*self)
558597
}
559598

599+
pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> {
600+
db.infer((*self).into())
601+
}
602+
603+
pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
604+
db.body_with_source_map((*self).into()).1
605+
}
606+
560607
/// The containing impl block, if this is a method.
561608
pub fn impl_block(&self, db: &impl DefDatabase) -> Option<ImplBlock> {
562609
let module_impls = db.impls_in_module(self.module(db));
@@ -621,6 +668,14 @@ impl Static {
621668
// take the outer scope...
622669
self.module(db).resolver(db)
623670
}
671+
672+
pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> {
673+
db.infer((*self).into())
674+
}
675+
676+
pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
677+
db.body_with_source_map((*self).into()).1
678+
}
624679
}
625680

626681
impl Docs for Static {

crates/ra_hir/src/db.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::{
88
Function, FnSignature, ExprScopes, TypeAlias,
99
Struct, Enum, StructField,
1010
Const, ConstSignature, Static,
11+
DefWithBody,
1112
nameres::{Namespace, ImportSourceMap, RawItems, CrateDefMap},
1213
ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef, CallableDef, FnSig},
1314
adt::{StructData, EnumData},
@@ -83,10 +84,10 @@ pub trait DefDatabase: SourceDatabase + AsRef<HirInterner> {
8384
#[salsa::query_group(HirDatabaseStorage)]
8485
pub trait HirDatabase: DefDatabase {
8586
#[salsa::invoke(ExprScopes::expr_scopes_query)]
86-
fn expr_scopes(&self, func: Function) -> Arc<ExprScopes>;
87+
fn expr_scopes(&self, def: DefWithBody) -> Arc<ExprScopes>;
8788

8889
#[salsa::invoke(crate::ty::infer)]
89-
fn infer(&self, func: Function) -> Arc<InferenceResult>;
90+
fn infer(&self, def: DefWithBody) -> Arc<InferenceResult>;
9091

9192
#[salsa::invoke(crate::ty::type_for_def)]
9293
fn type_for_def(&self, def: TypableDef, ns: Namespace) -> Ty;
@@ -100,11 +101,11 @@ pub trait HirDatabase: DefDatabase {
100101
#[salsa::invoke(crate::expr::body_with_source_map_query)]
101102
fn body_with_source_map(
102103
&self,
103-
func: Function,
104+
def: DefWithBody,
104105
) -> (Arc<crate::expr::Body>, Arc<crate::expr::BodySourceMap>);
105106

106107
#[salsa::invoke(crate::expr::body_hir_query)]
107-
fn body_hir(&self, func: Function) -> Arc<crate::expr::Body>;
108+
fn body_hir(&self, def: DefWithBody) -> Arc<crate::expr::Body>;
108109

109110
#[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)]
110111
fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>;

crates/ra_hir/src/expr.rs

+26-21
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use ra_syntax::{
1010
};
1111

1212
use crate::{
13-
Path, Name, HirDatabase, Function, Resolver,
13+
Path, Name, HirDatabase, Resolver,DefWithBody,
1414
name::AsName,
1515
type_ref::{Mutability, TypeRef},
1616
};
@@ -27,9 +27,8 @@ impl_arena_id!(ExprId);
2727
/// The body of an item (function, const etc.).
2828
#[derive(Debug, Eq, PartialEq)]
2929
pub struct Body {
30-
// FIXME: this should be more general, consts & statics also have bodies
31-
/// The Function of the item this body belongs to
32-
owner: Function,
30+
/// The def of the item this body belongs to
31+
owner: DefWithBody,
3332
exprs: Arena<ExprId, Expr>,
3433
pats: Arena<PatId, Pat>,
3534
/// The patterns for the function's parameters. While the parameter types are
@@ -66,7 +65,7 @@ impl Body {
6665
self.body_expr
6766
}
6867

69-
pub fn owner(&self) -> Function {
68+
pub fn owner(&self) -> DefWithBody {
7069
self.owner
7170
}
7271

@@ -463,8 +462,8 @@ impl Pat {
463462

464463
// Queries
465464

466-
struct ExprCollector {
467-
owner: Function,
465+
pub(crate) struct ExprCollector {
466+
owner: DefWithBody,
468467
exprs: Arena<ExprId, Expr>,
469468
pats: Arena<PatId, Pat>,
470469
source_map: BodySourceMap,
@@ -473,7 +472,7 @@ struct ExprCollector {
473472
}
474473

475474
impl ExprCollector {
476-
fn new(owner: Function) -> Self {
475+
fn new(owner: DefWithBody) -> Self {
477476
ExprCollector {
478477
owner,
479478
exprs: Arena::default(),
@@ -866,6 +865,16 @@ impl ExprCollector {
866865
}
867866
}
868867

868+
fn collect_const_body(&mut self, node: &ast::ConstDef) {
869+
let body = self.collect_expr_opt(node.body());
870+
self.body_expr = Some(body);
871+
}
872+
873+
fn collect_static_body(&mut self, node: &ast::StaticDef) {
874+
let body = self.collect_expr_opt(node.body());
875+
self.body_expr = Some(body);
876+
}
877+
869878
fn collect_fn_body(&mut self, node: &ast::FnDef) {
870879
if let Some(param_list) = node.param_list() {
871880
if let Some(self_param) = param_list.self_param() {
@@ -910,24 +919,20 @@ impl ExprCollector {
910919

911920
pub(crate) fn body_with_source_map_query(
912921
db: &impl HirDatabase,
913-
func: Function,
922+
def: DefWithBody,
914923
) -> (Arc<Body>, Arc<BodySourceMap>) {
915-
let mut collector = ExprCollector::new(func);
924+
let mut collector = ExprCollector::new(def);
916925

917-
// FIXME: consts, etc.
918-
collector.collect_fn_body(&func.source(db).1);
926+
match def {
927+
DefWithBody::Const(ref c) => collector.collect_const_body(&c.source(db).1),
928+
DefWithBody::Function(ref f) => collector.collect_fn_body(&f.source(db).1),
929+
DefWithBody::Static(ref s) => collector.collect_static_body(&s.source(db).1),
930+
}
919931

920932
let (body, source_map) = collector.finish();
921933
(Arc::new(body), Arc::new(source_map))
922934
}
923935

924-
pub(crate) fn body_hir_query(db: &impl HirDatabase, func: Function) -> Arc<Body> {
925-
db.body_with_source_map(func).0
926-
}
927-
928-
#[cfg(test)]
929-
fn collect_fn_body_syntax(function: Function, node: &ast::FnDef) -> (Body, BodySourceMap) {
930-
let mut collector = ExprCollector::new(function);
931-
collector.collect_fn_body(node);
932-
collector.finish()
936+
pub(crate) fn body_hir_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<Body> {
937+
db.body_with_source_map(def).0
933938
}

crates/ra_hir/src/expr/scope.rs

+13-6
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use ra_syntax::{
1010
use ra_arena::{Arena, RawId, impl_arena_id};
1111

1212
use crate::{
13-
Name, AsName, Function,
13+
Name, AsName,DefWithBody,
1414
expr::{PatId, ExprId, Pat, Expr, Body, Statement, BodySourceMap},
1515
HirDatabase,
1616
};
@@ -40,8 +40,8 @@ pub struct ScopeData {
4040

4141
impl ExprScopes {
4242
// FIXME: This should take something more general than Function
43-
pub(crate) fn expr_scopes_query(db: &impl HirDatabase, function: Function) -> Arc<ExprScopes> {
44-
let body = db.body_hir(function);
43+
pub(crate) fn expr_scopes_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<ExprScopes> {
44+
let body = db.body_hir(def);
4545
let res = ExprScopes::new(body);
4646
Arc::new(res)
4747
}
@@ -297,8 +297,9 @@ mod tests {
297297
use ra_syntax::{SourceFile, algo::find_node_at_offset};
298298
use test_utils::{extract_offset, assert_eq_text};
299299
use ra_arena::ArenaId;
300+
use crate::Function;
300301

301-
use crate::expr;
302+
use crate::expr::{ExprCollector};
302303

303304
use super::*;
304305

@@ -316,7 +317,7 @@ mod tests {
316317
let marker: &ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap();
317318
let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap();
318319
let irrelevant_function = Function { id: crate::ids::FunctionId::from_raw(0.into()) };
319-
let (body, source_map) = expr::collect_fn_body_syntax(irrelevant_function, fn_def);
320+
let (body, source_map) = collect_fn_body_syntax(irrelevant_function, fn_def);
320321
let scopes = ExprScopes::new(Arc::new(body));
321322
let scopes =
322323
ScopesWithSourceMap { scopes: Arc::new(scopes), source_map: Arc::new(source_map) };
@@ -405,6 +406,12 @@ mod tests {
405406
);
406407
}
407408

409+
fn collect_fn_body_syntax(function: Function, node: &ast::FnDef) -> (Body, BodySourceMap) {
410+
let mut collector = ExprCollector::new(DefWithBody::Function(function));
411+
collector.collect_fn_body(node);
412+
collector.finish()
413+
}
414+
408415
fn do_check_local_name(code: &str, expected_offset: u32) {
409416
let (off, code) = extract_offset(code);
410417
let file = SourceFile::parse(&code);
@@ -415,7 +422,7 @@ mod tests {
415422
let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap();
416423

417424
let irrelevant_function = Function { id: crate::ids::FunctionId::from_raw(0.into()) };
418-
let (body, source_map) = expr::collect_fn_body_syntax(irrelevant_function, fn_def);
425+
let (body, source_map) = collect_fn_body_syntax(irrelevant_function, fn_def);
419426
let scopes = ExprScopes::new(Arc::new(body));
420427
let scopes =
421428
ScopesWithSourceMap { scopes: Arc::new(scopes), source_map: Arc::new(source_map) };

crates/ra_hir/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ pub use self::{
6767

6868
pub use self::code_model_api::{
6969
Crate, CrateDependency,
70+
DefWithBody,
7071
Module, ModuleDef, ModuleSource,
7172
Struct, Enum, EnumVariant,
7273
Function, FnSignature,

crates/ra_hir/src/source_binder.rs

+43-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use ra_syntax::{
1313
};
1414

1515
use crate::{
16-
HirDatabase, Function, Struct, Enum,
16+
HirDatabase, Function, Struct, Enum,Const,Static,
1717
AsName, Module, HirFileId, Crate, Trait, Resolver,
1818
ids::LocationCtx,
1919
expr, AstId
@@ -87,6 +87,27 @@ fn module_from_source(
8787
)
8888
}
8989

90+
pub fn const_from_source(
91+
db: &impl HirDatabase,
92+
file_id: FileId,
93+
const_def: &ast::ConstDef,
94+
) -> Option<Const> {
95+
let module = module_from_child_node(db, file_id, const_def.syntax())?;
96+
let res = const_from_module(db, module, const_def);
97+
Some(res)
98+
}
99+
100+
pub fn const_from_module(
101+
db: &impl HirDatabase,
102+
module: Module,
103+
const_def: &ast::ConstDef,
104+
) -> Const {
105+
let (file_id, _) = module.definition_source(db);
106+
let file_id = file_id.into();
107+
let ctx = LocationCtx::new(db, module, file_id);
108+
Const { id: ctx.to_def(const_def) }
109+
}
110+
90111
pub fn function_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Function> {
91112
let file = db.parse(position.file_id);
92113
let fn_def = find_node_at_offset::<ast::FnDef>(file.syntax(), position.offset)?;
@@ -134,6 +155,27 @@ pub fn struct_from_module(
134155
Struct { id: ctx.to_def(struct_def) }
135156
}
136157

158+
pub fn static_from_source(
159+
db: &impl HirDatabase,
160+
file_id: FileId,
161+
static_def: &ast::StaticDef,
162+
) -> Option<Static> {
163+
let module = module_from_child_node(db, file_id, static_def.syntax())?;
164+
let res = static_from_module(db, module, static_def);
165+
Some(res)
166+
}
167+
168+
pub fn static_from_module(
169+
db: &impl HirDatabase,
170+
module: Module,
171+
static_def: &ast::StaticDef,
172+
) -> Static {
173+
let (file_id, _) = module.definition_source(db);
174+
let file_id = file_id.into();
175+
let ctx = LocationCtx::new(db, module, file_id);
176+
Static { id: ctx.to_def(static_def) }
177+
}
178+
137179
pub fn enum_from_module(db: &impl HirDatabase, module: Module, enum_def: &ast::EnumDef) -> Enum {
138180
let (file_id, _) = module.definition_source(db);
139181
let file_id = file_id.into();

0 commit comments

Comments
 (0)