Skip to content

Commit 081596d

Browse files
bors[bot]matklad
andauthored
Merge #5413
5413: Semantical call info r=matklad a=matklad Co-authored-by: Aleksey Kladov <[email protected]>
2 parents 9210fcc + e1e79cf commit 081596d

18 files changed

+452
-313
lines changed

crates/ra_hir/src/code_model.rs

+79-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//! FIXME: write short doc here
2-
use std::sync::Arc;
2+
use std::{iter, sync::Arc};
33

44
use arrayvec::ArrayVec;
55
use either::Either;
@@ -12,6 +12,7 @@ use hir_def::{
1212
import_map,
1313
per_ns::PerNs,
1414
resolver::{HasResolver, Resolver},
15+
src::HasSource as _,
1516
type_ref::{Mutability, TypeRef},
1617
AdtId, AssocContainerId, ConstId, DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule,
1718
ImplId, LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StaticId, StructId,
@@ -25,8 +26,8 @@ use hir_expand::{
2526
use hir_ty::{
2627
autoderef,
2728
display::{HirDisplayError, HirFormatter},
28-
method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, Substs,
29-
TraitEnvironment, Ty, TyDefId, TypeCtor,
29+
method_resolution, ApplicationTy, CallableDefId, Canonical, FnSig, GenericPredicate,
30+
InEnvironment, Substs, TraitEnvironment, Ty, TyDefId, TypeCtor,
3031
};
3132
use ra_db::{CrateId, Edition, FileId};
3233
use ra_prof::profile;
@@ -40,7 +41,7 @@ use stdx::impl_from;
4041
use crate::{
4142
db::{DefDatabase, HirDatabase},
4243
has_source::HasSource,
43-
CallableDefId, HirDisplay, InFile, Name,
44+
HirDisplay, InFile, Name,
4445
};
4546

4647
/// hir::Crate describes a single crate. It's the main interface with which
@@ -1168,6 +1169,12 @@ impl Type {
11681169
Type::new(db, krate, def, ty)
11691170
}
11701171

1172+
pub fn is_unit(&self) -> bool {
1173+
matches!(
1174+
self.ty.value,
1175+
Ty::Apply(ApplicationTy { ctor: TypeCtor::Tuple { cardinality: 0 }, .. })
1176+
)
1177+
}
11711178
pub fn is_bool(&self) -> bool {
11721179
matches!(self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. }))
11731180
}
@@ -1225,9 +1232,10 @@ impl Type {
12251232
db.trait_solve(self.krate, goal).is_some()
12261233
}
12271234

1228-
// FIXME: this method is broken, as it doesn't take closures into account.
1229-
pub fn as_callable(&self) -> Option<CallableDefId> {
1230-
Some(self.ty.value.as_callable()?.0)
1235+
pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
1236+
let (id, substs) = self.ty.value.as_callable()?;
1237+
let sig = db.callable_item_signature(id).subst(substs);
1238+
Some(Callable { ty: self.clone(), sig, id, is_bound_method: false })
12311239
}
12321240

12331241
pub fn is_closure(&self) -> bool {
@@ -1512,6 +1520,70 @@ impl HirDisplay for Type {
15121520
}
15131521
}
15141522

1523+
// FIXME: closures
1524+
#[derive(Debug)]
1525+
pub struct Callable {
1526+
ty: Type,
1527+
sig: FnSig,
1528+
id: CallableDefId,
1529+
pub(crate) is_bound_method: bool,
1530+
}
1531+
1532+
pub enum CallableKind {
1533+
Function(Function),
1534+
TupleStruct(Struct),
1535+
TupleEnumVariant(EnumVariant),
1536+
}
1537+
1538+
impl Callable {
1539+
pub fn kind(&self) -> CallableKind {
1540+
match self.id {
1541+
CallableDefId::FunctionId(it) => CallableKind::Function(it.into()),
1542+
CallableDefId::StructId(it) => CallableKind::TupleStruct(it.into()),
1543+
CallableDefId::EnumVariantId(it) => CallableKind::TupleEnumVariant(it.into()),
1544+
}
1545+
}
1546+
pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<ast::SelfParam> {
1547+
let func = match self.id {
1548+
CallableDefId::FunctionId(it) if self.is_bound_method => it,
1549+
_ => return None,
1550+
};
1551+
let src = func.lookup(db.upcast()).source(db.upcast());
1552+
let param_list = src.value.param_list()?;
1553+
param_list.self_param()
1554+
}
1555+
pub fn params(
1556+
&self,
1557+
db: &dyn HirDatabase,
1558+
) -> Vec<(Option<Either<ast::SelfParam, ast::Pat>>, Type)> {
1559+
let types = self
1560+
.sig
1561+
.params()
1562+
.iter()
1563+
.skip(if self.is_bound_method { 1 } else { 0 })
1564+
.map(|ty| self.ty.derived(ty.clone()));
1565+
let patterns = match self.id {
1566+
CallableDefId::FunctionId(func) => {
1567+
let src = func.lookup(db.upcast()).source(db.upcast());
1568+
src.value.param_list().map(|param_list| {
1569+
param_list
1570+
.self_param()
1571+
.map(|it| Some(Either::Left(it)))
1572+
.filter(|_| !self.is_bound_method)
1573+
.into_iter()
1574+
.chain(param_list.params().map(|it| it.pat().map(Either::Right)))
1575+
})
1576+
}
1577+
CallableDefId::StructId(_) => None,
1578+
CallableDefId::EnumVariantId(_) => None,
1579+
};
1580+
patterns.into_iter().flatten().chain(iter::repeat(None)).zip(types).collect()
1581+
}
1582+
pub fn return_type(&self) -> Type {
1583+
self.ty.derived(self.sig.ret().clone())
1584+
}
1585+
}
1586+
15151587
/// For IDE only
15161588
#[derive(Debug)]
15171589
pub enum ScopeDef {

crates/ra_hir/src/lib.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ mod has_source;
3232

3333
pub use crate::{
3434
code_model::{
35-
Adt, AsAssocItem, AssocItem, AssocItemContainer, AttrDef, Const, Crate, CrateDependency,
36-
DefWithBody, Docs, Enum, EnumVariant, Field, FieldSource, Function, GenericDef, HasAttrs,
37-
HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, ScopeDef, Static, Struct,
38-
Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility,
35+
Adt, AsAssocItem, AssocItem, AssocItemContainer, AttrDef, Callable, CallableKind, Const,
36+
Crate, CrateDependency, DefWithBody, Docs, Enum, EnumVariant, Field, FieldSource, Function,
37+
GenericDef, HasAttrs, HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, ScopeDef,
38+
Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility,
3939
},
4040
has_source::HasSource,
4141
semantics::{original_range, PathResolution, Semantics, SemanticsScope},
@@ -52,7 +52,8 @@ pub use hir_def::{
5252
type_ref::Mutability,
5353
};
5454
pub use hir_expand::{
55-
hygiene::Hygiene, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId,
55+
hygiene::Hygiene, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc,
56+
MacroDefId, /* FIXME */
5657
MacroFile, Origin,
5758
};
58-
pub use hir_ty::{display::HirDisplay, CallableDefId};
59+
pub use hir_ty::display::HirDisplay;

crates/ra_hir/src/semantics.rs

+20-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::{cell::RefCell, fmt, iter::successors};
66

77
use hir_def::{
88
resolver::{self, HasResolver, Resolver},
9-
AsMacroCall, TraitId, VariantId,
9+
AsMacroCall, FunctionId, TraitId, VariantId,
1010
};
1111
use hir_expand::{diagnostics::AstDiagnostic, hygiene::Hygiene, ExpansionInfo};
1212
use hir_ty::associated_type_shorthand_candidates;
@@ -24,8 +24,8 @@ use crate::{
2424
diagnostics::Diagnostic,
2525
semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
2626
source_analyzer::{resolve_hir_path, resolve_hir_path_qualifier, SourceAnalyzer},
27-
AssocItem, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module, ModuleDef,
28-
Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, VariantDef,
27+
AssocItem, Callable, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module,
28+
ModuleDef, Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, VariantDef,
2929
};
3030
use resolver::TypeNs;
3131

@@ -197,7 +197,11 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
197197
}
198198

199199
pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> {
200-
self.imp.resolve_method_call(call)
200+
self.imp.resolve_method_call(call).map(Function::from)
201+
}
202+
203+
pub fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> {
204+
self.imp.resolve_method_call_as_callable(call)
201205
}
202206

203207
pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Field> {
@@ -385,10 +389,21 @@ impl<'db> SemanticsImpl<'db> {
385389
self.analyze(param.syntax()).type_of_self(self.db, &param)
386390
}
387391

388-
fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> {
392+
fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> {
389393
self.analyze(call.syntax()).resolve_method_call(self.db, call)
390394
}
391395

396+
fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> {
397+
// FIXME: this erases Substs
398+
let func = self.resolve_method_call(call)?;
399+
let ty = self.db.value_ty(func.into());
400+
let resolver = self.analyze(call.syntax()).resolver;
401+
let ty = Type::new_with_resolver(self.db, &resolver, ty.value)?;
402+
let mut res = ty.as_callable(self.db)?;
403+
res.is_bound_method = true;
404+
Some(res)
405+
}
406+
392407
fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Field> {
393408
self.analyze(field.syntax()).resolve_field(self.db, field)
394409
}

crates/ra_hir/src/source_analyzer.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use hir_def::{
1414
},
1515
expr::{ExprId, Pat, PatId},
1616
resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs},
17-
AsMacroCall, DefWithBodyId, FieldId, LocalFieldId, VariantId,
17+
AsMacroCall, DefWithBodyId, FieldId, FunctionId, LocalFieldId, VariantId,
1818
};
1919
use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile};
2020
use hir_ty::{
@@ -142,9 +142,9 @@ impl SourceAnalyzer {
142142
&self,
143143
db: &dyn HirDatabase,
144144
call: &ast::MethodCallExpr,
145-
) -> Option<Function> {
145+
) -> Option<FunctionId> {
146146
let expr_id = self.expr_id(db, &call.clone().into())?;
147-
self.infer.as_ref()?.method_resolution(expr_id).map(Function::from)
147+
self.infer.as_ref()?.method_resolution(expr_id)
148148
}
149149

150150
pub(crate) fn resolve_field(

crates/ra_hir_def/src/nameres/path_resolution.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,15 @@ impl CrateDefMap {
226226
match enum_data.variant(&segment) {
227227
Some(local_id) => {
228228
let variant = EnumVariantId { parent: e, local_id };
229-
PerNs::both(variant.into(), variant.into(), Visibility::Public)
229+
match &*enum_data.variants[local_id].variant_data {
230+
crate::adt::VariantData::Record(_) => {
231+
PerNs::types(variant.into(), Visibility::Public)
232+
}
233+
crate::adt::VariantData::Tuple(_)
234+
| crate::adt::VariantData::Unit => {
235+
PerNs::both(variant.into(), variant.into(), Visibility::Public)
236+
}
237+
}
230238
}
231239
None => {
232240
return ResolvePathResult::with(

crates/ra_ide/src/call_hierarchy.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,9 @@ pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Optio
9595
if let Some(func_target) = match &call_node {
9696
FnCallNode::CallExpr(expr) => {
9797
//FIXME: Type::as_callable is broken
98-
let callable_def = sema.type_of_expr(&expr.expr()?)?.as_callable()?;
99-
match callable_def {
100-
hir::CallableDefId::FunctionId(it) => {
98+
let callable = sema.type_of_expr(&expr.expr()?)?.as_callable(db)?;
99+
match callable.kind() {
100+
hir::CallableKind::Function(it) => {
101101
let fn_def: hir::Function = it.into();
102102
let nav = fn_def.to_nav(db);
103103
Some(nav)
@@ -109,10 +109,6 @@ pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Optio
109109
let function = sema.resolve_method_call(&expr)?;
110110
Some(function.to_nav(db))
111111
}
112-
FnCallNode::MacroCallExpr(macro_call) => {
113-
let macro_def = sema.resolve_macro_call(&macro_call)?;
114-
Some(macro_def.to_nav(db))
115-
}
116112
} {
117113
Some((func_target, name_ref.syntax().text_range()))
118114
} else {

0 commit comments

Comments
 (0)