From 538147bf94b4c52a945c975b67e8d557998f9052 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 29 Dec 2018 23:20:12 +0100 Subject: Resolve the Self type --- crates/ra_hir/src/name.rs | 5 +- crates/ra_hir/src/ty.rs | 86 ++++++++++++++++++++------- crates/ra_hir/src/ty/tests/data/0007_self.txt | 4 +- 3 files changed, 71 insertions(+), 24 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs index 51e8b3da8..017caf442 100644 --- a/crates/ra_hir/src/name.rs +++ b/crates/ra_hir/src/name.rs @@ -51,6 +51,7 @@ impl Name { "u128" => KnownName::U128, "f32" => KnownName::F32, "f64" => KnownName::F64, + "Self" => KnownName::Self_, _ => return None, }; Some(name) @@ -84,7 +85,7 @@ impl AsName for ra_db::Dependency { // const ISIZE: Name = Name::new("isize") // ``` // but const-fn is not that powerful yet. -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] pub(crate) enum KnownName { Isize, I8, @@ -102,4 +103,6 @@ pub(crate) enum KnownName { F32, F64, + + Self_, } diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 5ea62a14c..d11f80cff 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -31,9 +31,10 @@ use ra_syntax::{ }; use crate::{ - Def, DefId, FnScopes, Module, Function, Struct, Enum, Path, Name, AsName, + Def, DefId, FnScopes, Module, Function, Struct, Enum, Path, Name, AsName, ImplBlock, db::HirDatabase, type_ref::{TypeRef, Mutability}, + name::KnownName, }; /// The ID of a type variable. @@ -235,6 +236,7 @@ impl Ty { pub(crate) fn from_hir( db: &impl HirDatabase, module: &Module, + impl_block: Option<&ImplBlock>, type_ref: &TypeRef, ) -> Cancelable { Ok(match type_ref { @@ -242,29 +244,29 @@ impl Ty { TypeRef::Tuple(inner) => { let inner_tys = inner .iter() - .map(|tr| Ty::from_hir(db, module, tr)) + .map(|tr| Ty::from_hir(db, module, impl_block, tr)) .collect::>>()?; Ty::Tuple(inner_tys.into()) } - TypeRef::Path(path) => Ty::from_hir_path(db, module, path)?, + TypeRef::Path(path) => Ty::from_hir_path(db, module, impl_block, path)?, TypeRef::RawPtr(inner, mutability) => { - let inner_ty = Ty::from_hir(db, module, inner)?; + let inner_ty = Ty::from_hir(db, module, impl_block, inner)?; Ty::RawPtr(Arc::new(inner_ty), *mutability) } TypeRef::Array(_inner) => Ty::Unknown, // TODO TypeRef::Slice(inner) => { - let inner_ty = Ty::from_hir(db, module, inner)?; + let inner_ty = Ty::from_hir(db, module, impl_block, inner)?; Ty::Slice(Arc::new(inner_ty)) } TypeRef::Reference(inner, mutability) => { - let inner_ty = Ty::from_hir(db, module, inner)?; + let inner_ty = Ty::from_hir(db, module, impl_block, inner)?; Ty::Ref(Arc::new(inner_ty), *mutability) } TypeRef::Placeholder => Ty::Unknown, TypeRef::Fn(params) => { let mut inner_tys = params .iter() - .map(|tr| Ty::from_hir(db, module, tr)) + .map(|tr| Ty::from_hir(db, module, impl_block, tr)) .collect::>>()?; let return_ty = inner_tys .pop() @@ -279,9 +281,21 @@ impl Ty { }) } + pub(crate) fn from_hir_opt( + db: &impl HirDatabase, + module: &Module, + impl_block: Option<&ImplBlock>, + type_ref: Option<&TypeRef>, + ) -> Cancelable { + type_ref + .map(|t| Ty::from_hir(db, module, impl_block, t)) + .unwrap_or(Ok(Ty::Unknown)) + } + pub(crate) fn from_hir_path( db: &impl HirDatabase, module: &Module, + impl_block: Option<&ImplBlock>, path: &Path, ) -> Cancelable { if let Some(name) = path.as_ident() { @@ -291,6 +305,8 @@ impl Ty { return Ok(Ty::Uint(uint_ty)); } else if let Some(float_ty) = primitive::FloatTy::from_name(name) { return Ok(Ty::Float(float_ty)); + } else if name.as_known_name() == Some(KnownName::Self_) { + return Ty::from_hir_opt(db, module, None, impl_block.map(|i| i.target())); } } @@ -308,18 +324,20 @@ impl Ty { pub(crate) fn from_ast_opt( db: &impl HirDatabase, module: &Module, + impl_block: Option<&ImplBlock>, node: Option, ) -> Cancelable { - node.map(|n| Ty::from_ast(db, module, n)) + node.map(|n| Ty::from_ast(db, module, impl_block, n)) .unwrap_or(Ok(Ty::Unknown)) } pub(crate) fn from_ast( db: &impl HirDatabase, module: &Module, + impl_block: Option<&ImplBlock>, node: ast::TypeRef, ) -> Cancelable { - Ty::from_hir(db, module, &TypeRef::from_ast(node)) + Ty::from_hir(db, module, impl_block, &TypeRef::from_ast(node)) } pub fn unit() -> Self { @@ -402,18 +420,19 @@ impl fmt::Display for Ty { fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable { let syntax = f.syntax(db); let module = f.module(db)?; + let impl_block = f.impl_block(db)?; let node = syntax.borrowed(); // TODO we ignore type parameters for now let input = node .param_list() .map(|pl| { pl.params() - .map(|p| Ty::from_ast_opt(db, &module, p.type_ref())) + .map(|p| Ty::from_ast_opt(db, &module, impl_block.as_ref(), p.type_ref())) .collect() }) .unwrap_or_else(|| Ok(Vec::new()))?; let output = if let Some(type_ref) = node.ret_type().and_then(|rt| rt.type_ref()) { - Ty::from_ast(db, &module, type_ref)? + Ty::from_ast(db, &module, impl_block.as_ref(), type_ref)? } else { Ty::unit() }; @@ -467,12 +486,13 @@ pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name) ), }; let module = def_id.module(db)?; + let impl_block = def_id.impl_block(db)?; let type_ref = if let Some(tr) = variant_data.get_field_type_ref(&field) { tr } else { return Ok(Ty::Unknown); }; - Ty::from_hir(db, &module, &type_ref) + Ty::from_hir(db, &module, impl_block.as_ref(), &type_ref) } /// The result of type inference: A mapping from expressions and patterns to types. @@ -499,12 +519,18 @@ struct InferenceContext<'a, D: HirDatabase> { /// The self param for the current method, if it exists. self_param: Option, module: Module, + impl_block: Option, var_unification_table: InPlaceUnificationTable, type_of: FxHashMap, } impl<'a, D: HirDatabase> InferenceContext<'a, D> { - fn new(db: &'a D, scopes: Arc, module: Module) -> Self { + fn new( + db: &'a D, + scopes: Arc, + module: Module, + impl_block: Option, + ) -> Self { InferenceContext { type_of: FxHashMap::default(), var_unification_table: InPlaceUnificationTable::new(), @@ -512,6 +538,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { db, scopes, module, + impl_block, } } @@ -835,7 +862,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } ast::Expr::CastExpr(e) => { let _inner_ty = self.infer_expr_opt(e.expr(), &Expectation::none())?; - let cast_ty = Ty::from_ast_opt(self.db, &self.module, e.type_ref())?; + let cast_ty = Ty::from_ast_opt( + self.db, + &self.module, + self.impl_block.as_ref(), + e.type_ref(), + )?; let cast_ty = self.insert_type_vars(cast_ty); // TODO do the coercion... cast_ty @@ -889,7 +921,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { for stmt in node.statements() { match stmt { ast::Stmt::LetStmt(stmt) => { - let decl_ty = Ty::from_ast_opt(self.db, &self.module, stmt.type_ref())?; + let decl_ty = Ty::from_ast_opt( + self.db, + &self.module, + self.impl_block.as_ref(), + stmt.type_ref(), + )?; let decl_ty = self.insert_type_vars(decl_ty); let ty = if let Some(expr) = stmt.initializer() { let expr_ty = self.infer_expr(expr, &Expectation::has_type(decl_ty))?; @@ -921,19 +958,26 @@ pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Cancelable ty, ast::SelfParamFlavor::Ref => Ty::Ref(Arc::new(ty), Mutability::Shared), @@ -961,7 +1005,7 @@ pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Cancelable Cancelable