Type the self parameter
This commit is contained in:
parent
ae9530addc
commit
111126ed3c
@ -30,6 +30,10 @@ impl MockDatabase {
|
||||
let file_id = db.add_file(&mut source_root, "/main.rs", text);
|
||||
db.query_mut(ra_db::SourceRootQuery)
|
||||
.set(WORKSPACE, Arc::new(source_root.clone()));
|
||||
|
||||
let mut crate_graph = CrateGraph::default();
|
||||
crate_graph.add_crate_root(file_id);
|
||||
db.set_crate_graph(crate_graph);
|
||||
(db, source_root, file_id)
|
||||
}
|
||||
|
||||
|
@ -918,22 +918,46 @@ pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<InferenceRe
|
||||
let node = syntax.borrowed();
|
||||
|
||||
if let Some(param_list) = node.param_list() {
|
||||
if let Some(self_param) = param_list.self_param() {
|
||||
let self_type = if let Some(impl_block) = function.impl_block(db)? {
|
||||
if let Some(type_ref) = self_param.type_ref() {
|
||||
let ty = Ty::from_ast(db, &ctx.module, type_ref)?;
|
||||
ctx.insert_type_vars(ty)
|
||||
} else {
|
||||
let ty = Ty::from_hir(db, &ctx.module, impl_block.target())?;
|
||||
let ty = match self_param.flavor() {
|
||||
ast::SelfParamFlavor::Owned => ty,
|
||||
ast::SelfParamFlavor::Ref => Ty::Ref(Arc::new(ty), Mutability::Shared),
|
||||
ast::SelfParamFlavor::MutRef => Ty::Ref(Arc::new(ty), Mutability::Mut),
|
||||
};
|
||||
ctx.insert_type_vars(ty)
|
||||
}
|
||||
} else {
|
||||
log::debug!(
|
||||
"No impl block found, but self param for function {:?}",
|
||||
def_id
|
||||
);
|
||||
ctx.new_type_var()
|
||||
};
|
||||
if let Some(self_kw) = self_param.self_kw() {
|
||||
ctx.type_of
|
||||
.insert(LocalSyntaxPtr::new(self_kw.syntax()), self_type);
|
||||
}
|
||||
}
|
||||
for param in param_list.params() {
|
||||
let pat = if let Some(pat) = param.pat() {
|
||||
pat
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
if let Some(type_ref) = param.type_ref() {
|
||||
let ty = if let Some(type_ref) = param.type_ref() {
|
||||
let ty = Ty::from_ast(db, &ctx.module, type_ref)?;
|
||||
let ty = ctx.insert_type_vars(ty);
|
||||
ctx.type_of.insert(LocalSyntaxPtr::new(pat.syntax()), ty);
|
||||
ctx.insert_type_vars(ty)
|
||||
} else {
|
||||
// TODO self param
|
||||
let type_var = ctx.new_type_var();
|
||||
ctx.type_of
|
||||
.insert(LocalSyntaxPtr::new(pat.syntax()), type_var);
|
||||
// missing type annotation
|
||||
ctx.new_type_var()
|
||||
};
|
||||
ctx.type_of.insert(LocalSyntaxPtr::new(pat.syntax()), ty);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,6 @@
|
||||
[50; 54) 'self': [unknown]
|
||||
[34; 38) 'self': &S
|
||||
[40; 61) '{ ... }': ()
|
||||
[88; 109) '{ ... }': ()
|
||||
[98; 102) 'self': [unknown]
|
||||
[75; 79) 'self': &[unknown]
|
||||
|
@ -482,6 +482,37 @@ impl<'a> PrefixExpr<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum SelfParamFlavor {
|
||||
/// self
|
||||
Owned,
|
||||
/// &self
|
||||
Ref,
|
||||
/// &mut self
|
||||
MutRef,
|
||||
}
|
||||
|
||||
impl<'a> SelfParam<'a> {
|
||||
pub fn flavor(&self) -> SelfParamFlavor {
|
||||
let borrowed = self.syntax().children().any(|n| n.kind() == AMP);
|
||||
if borrowed {
|
||||
// check for a `mut` coming after the & -- `mut &self` != `&mut self`
|
||||
if self
|
||||
.syntax()
|
||||
.children()
|
||||
.skip_while(|n| n.kind() != AMP)
|
||||
.any(|n| n.kind() == MUT_KW)
|
||||
{
|
||||
SelfParamFlavor::MutRef
|
||||
} else {
|
||||
SelfParamFlavor::Ref
|
||||
}
|
||||
} else {
|
||||
SelfParamFlavor::Owned
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_doc_comment_of_items() {
|
||||
let file = SourceFileNode::parse(
|
||||
|
@ -3488,6 +3488,43 @@ impl<'a> ReturnExpr<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
// SelfKw
|
||||
#[derive(Debug, Clone, Copy,)]
|
||||
pub struct SelfKwNode<R: TreeRoot<RaTypes> = OwnedRoot> {
|
||||
pub(crate) syntax: SyntaxNode<R>,
|
||||
}
|
||||
pub type SelfKw<'a> = SelfKwNode<RefRoot<'a>>;
|
||||
|
||||
impl<R1: TreeRoot<RaTypes>, R2: TreeRoot<RaTypes>> PartialEq<SelfKwNode<R1>> for SelfKwNode<R2> {
|
||||
fn eq(&self, other: &SelfKwNode<R1>) -> bool { self.syntax == other.syntax }
|
||||
}
|
||||
impl<R: TreeRoot<RaTypes>> Eq for SelfKwNode<R> {}
|
||||
impl<R: TreeRoot<RaTypes>> Hash for SelfKwNode<R> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) { self.syntax.hash(state) }
|
||||
}
|
||||
|
||||
impl<'a> AstNode<'a> for SelfKw<'a> {
|
||||
fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
|
||||
match syntax.kind() {
|
||||
SELF_KW => Some(SelfKw { syntax }),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
|
||||
}
|
||||
|
||||
impl<R: TreeRoot<RaTypes>> SelfKwNode<R> {
|
||||
pub fn borrowed(&self) -> SelfKw {
|
||||
SelfKwNode { syntax: self.syntax.borrowed() }
|
||||
}
|
||||
pub fn owned(&self) -> SelfKwNode {
|
||||
SelfKwNode { syntax: self.syntax.owned() }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'a> SelfKw<'a> {}
|
||||
|
||||
// SelfParam
|
||||
#[derive(Debug, Clone, Copy,)]
|
||||
pub struct SelfParamNode<R: TreeRoot<RaTypes> = OwnedRoot> {
|
||||
@ -3523,7 +3560,15 @@ impl<R: TreeRoot<RaTypes>> SelfParamNode<R> {
|
||||
}
|
||||
|
||||
|
||||
impl<'a> SelfParam<'a> {}
|
||||
impl<'a> SelfParam<'a> {
|
||||
pub fn type_ref(self) -> Option<TypeRef<'a>> {
|
||||
super::child_opt(self)
|
||||
}
|
||||
|
||||
pub fn self_kw(self) -> Option<SelfKw<'a>> {
|
||||
super::child_opt(self)
|
||||
}
|
||||
}
|
||||
|
||||
// SlicePat
|
||||
#[derive(Debug, Clone, Copy,)]
|
||||
|
@ -534,7 +534,8 @@ Grammar(
|
||||
["params", "Param"]
|
||||
]
|
||||
),
|
||||
"SelfParam": (),
|
||||
"SelfParam": (options: ["TypeRef", "SelfKw"]),
|
||||
"SelfKw": (),
|
||||
"Param": (
|
||||
options: [ "Pat", "TypeRef" ],
|
||||
),
|
||||
|
Loading…
x
Reference in New Issue
Block a user