Type the self parameter

This commit is contained in:
Florian Diebold 2018-12-29 21:32:07 +01:00
parent ae9530addc
commit 111126ed3c
6 changed files with 116 additions and 9 deletions

View file

@ -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)
}

View file

@ -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);
}
}

View file

@ -1,4 +1,6 @@
[50; 54) 'self': [unknown]
[34; 38) 'self': &S
[40; 61) '{ ... }': ()
[88; 109) '{ ... }': ()
[98; 102) 'self': [unknown]
[75; 79) 'self': &[unknown]

View file

@ -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(

View file

@ -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,)]

View file

@ -534,7 +534,8 @@ Grammar(
["params", "Param"]
]
),
"SelfParam": (),
"SelfParam": (options: ["TypeRef", "SelfKw"]),
"SelfKw": (),
"Param": (
options: [ "Pat", "TypeRef" ],
),