aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2018-12-29 22:20:12 +0000
committerFlorian Diebold <[email protected]>2019-01-04 18:13:50 +0000
commit538147bf94b4c52a945c975b67e8d557998f9052 (patch)
tree667dc8e07cc92335de0ae1ca6e5ddcba7db1fa11
parentd4db61b9a151a2a46c4067e61b0a4b1a9e3c73ec (diff)
Resolve the Self type
-rw-r--r--crates/ra_hir/src/name.rs5
-rw-r--r--crates/ra_hir/src/ty.rs86
-rw-r--r--crates/ra_hir/src/ty/tests/data/0007_self.txt4
3 files changed, 71 insertions, 24 deletions
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 {
51 "u128" => KnownName::U128, 51 "u128" => KnownName::U128,
52 "f32" => KnownName::F32, 52 "f32" => KnownName::F32,
53 "f64" => KnownName::F64, 53 "f64" => KnownName::F64,
54 "Self" => KnownName::Self_,
54 _ => return None, 55 _ => return None,
55 }; 56 };
56 Some(name) 57 Some(name)
@@ -84,7 +85,7 @@ impl AsName for ra_db::Dependency {
84// const ISIZE: Name = Name::new("isize") 85// const ISIZE: Name = Name::new("isize")
85// ``` 86// ```
86// but const-fn is not that powerful yet. 87// but const-fn is not that powerful yet.
87#[derive(Debug)] 88#[derive(Debug, PartialEq, Eq)]
88pub(crate) enum KnownName { 89pub(crate) enum KnownName {
89 Isize, 90 Isize,
90 I8, 91 I8,
@@ -102,4 +103,6 @@ pub(crate) enum KnownName {
102 103
103 F32, 104 F32,
104 F64, 105 F64,
106
107 Self_,
105} 108}
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::{
31}; 31};
32 32
33use crate::{ 33use crate::{
34 Def, DefId, FnScopes, Module, Function, Struct, Enum, Path, Name, AsName, 34 Def, DefId, FnScopes, Module, Function, Struct, Enum, Path, Name, AsName, ImplBlock,
35 db::HirDatabase, 35 db::HirDatabase,
36 type_ref::{TypeRef, Mutability}, 36 type_ref::{TypeRef, Mutability},
37 name::KnownName,
37}; 38};
38 39
39/// The ID of a type variable. 40/// The ID of a type variable.
@@ -235,6 +236,7 @@ impl Ty {
235 pub(crate) fn from_hir( 236 pub(crate) fn from_hir(
236 db: &impl HirDatabase, 237 db: &impl HirDatabase,
237 module: &Module, 238 module: &Module,
239 impl_block: Option<&ImplBlock>,
238 type_ref: &TypeRef, 240 type_ref: &TypeRef,
239 ) -> Cancelable<Self> { 241 ) -> Cancelable<Self> {
240 Ok(match type_ref { 242 Ok(match type_ref {
@@ -242,29 +244,29 @@ impl Ty {
242 TypeRef::Tuple(inner) => { 244 TypeRef::Tuple(inner) => {
243 let inner_tys = inner 245 let inner_tys = inner
244 .iter() 246 .iter()
245 .map(|tr| Ty::from_hir(db, module, tr)) 247 .map(|tr| Ty::from_hir(db, module, impl_block, tr))
246 .collect::<Cancelable<Vec<_>>>()?; 248 .collect::<Cancelable<Vec<_>>>()?;
247 Ty::Tuple(inner_tys.into()) 249 Ty::Tuple(inner_tys.into())
248 } 250 }
249 TypeRef::Path(path) => Ty::from_hir_path(db, module, path)?, 251 TypeRef::Path(path) => Ty::from_hir_path(db, module, impl_block, path)?,
250 TypeRef::RawPtr(inner, mutability) => { 252 TypeRef::RawPtr(inner, mutability) => {
251 let inner_ty = Ty::from_hir(db, module, inner)?; 253 let inner_ty = Ty::from_hir(db, module, impl_block, inner)?;
252 Ty::RawPtr(Arc::new(inner_ty), *mutability) 254 Ty::RawPtr(Arc::new(inner_ty), *mutability)
253 } 255 }
254 TypeRef::Array(_inner) => Ty::Unknown, // TODO 256 TypeRef::Array(_inner) => Ty::Unknown, // TODO
255 TypeRef::Slice(inner) => { 257 TypeRef::Slice(inner) => {
256 let inner_ty = Ty::from_hir(db, module, inner)?; 258 let inner_ty = Ty::from_hir(db, module, impl_block, inner)?;
257 Ty::Slice(Arc::new(inner_ty)) 259 Ty::Slice(Arc::new(inner_ty))
258 } 260 }
259 TypeRef::Reference(inner, mutability) => { 261 TypeRef::Reference(inner, mutability) => {
260 let inner_ty = Ty::from_hir(db, module, inner)?; 262 let inner_ty = Ty::from_hir(db, module, impl_block, inner)?;
261 Ty::Ref(Arc::new(inner_ty), *mutability) 263 Ty::Ref(Arc::new(inner_ty), *mutability)
262 } 264 }
263 TypeRef::Placeholder => Ty::Unknown, 265 TypeRef::Placeholder => Ty::Unknown,
264 TypeRef::Fn(params) => { 266 TypeRef::Fn(params) => {
265 let mut inner_tys = params 267 let mut inner_tys = params
266 .iter() 268 .iter()
267 .map(|tr| Ty::from_hir(db, module, tr)) 269 .map(|tr| Ty::from_hir(db, module, impl_block, tr))
268 .collect::<Cancelable<Vec<_>>>()?; 270 .collect::<Cancelable<Vec<_>>>()?;
269 let return_ty = inner_tys 271 let return_ty = inner_tys
270 .pop() 272 .pop()
@@ -279,9 +281,21 @@ impl Ty {
279 }) 281 })
280 } 282 }
281 283
284 pub(crate) fn from_hir_opt(
285 db: &impl HirDatabase,
286 module: &Module,
287 impl_block: Option<&ImplBlock>,
288 type_ref: Option<&TypeRef>,
289 ) -> Cancelable<Self> {
290 type_ref
291 .map(|t| Ty::from_hir(db, module, impl_block, t))
292 .unwrap_or(Ok(Ty::Unknown))
293 }
294
282 pub(crate) fn from_hir_path( 295 pub(crate) fn from_hir_path(
283 db: &impl HirDatabase, 296 db: &impl HirDatabase,
284 module: &Module, 297 module: &Module,
298 impl_block: Option<&ImplBlock>,
285 path: &Path, 299 path: &Path,
286 ) -> Cancelable<Self> { 300 ) -> Cancelable<Self> {
287 if let Some(name) = path.as_ident() { 301 if let Some(name) = path.as_ident() {
@@ -291,6 +305,8 @@ impl Ty {
291 return Ok(Ty::Uint(uint_ty)); 305 return Ok(Ty::Uint(uint_ty));
292 } else if let Some(float_ty) = primitive::FloatTy::from_name(name) { 306 } else if let Some(float_ty) = primitive::FloatTy::from_name(name) {
293 return Ok(Ty::Float(float_ty)); 307 return Ok(Ty::Float(float_ty));
308 } else if name.as_known_name() == Some(KnownName::Self_) {
309 return Ty::from_hir_opt(db, module, None, impl_block.map(|i| i.target()));
294 } 310 }
295 } 311 }
296 312
@@ -308,18 +324,20 @@ impl Ty {
308 pub(crate) fn from_ast_opt( 324 pub(crate) fn from_ast_opt(
309 db: &impl HirDatabase, 325 db: &impl HirDatabase,
310 module: &Module, 326 module: &Module,
327 impl_block: Option<&ImplBlock>,
311 node: Option<ast::TypeRef>, 328 node: Option<ast::TypeRef>,
312 ) -> Cancelable<Self> { 329 ) -> Cancelable<Self> {
313 node.map(|n| Ty::from_ast(db, module, n)) 330 node.map(|n| Ty::from_ast(db, module, impl_block, n))
314 .unwrap_or(Ok(Ty::Unknown)) 331 .unwrap_or(Ok(Ty::Unknown))
315 } 332 }
316 333
317 pub(crate) fn from_ast( 334 pub(crate) fn from_ast(
318 db: &impl HirDatabase, 335 db: &impl HirDatabase,
319 module: &Module, 336 module: &Module,
337 impl_block: Option<&ImplBlock>,
320 node: ast::TypeRef, 338 node: ast::TypeRef,
321 ) -> Cancelable<Self> { 339 ) -> Cancelable<Self> {
322 Ty::from_hir(db, module, &TypeRef::from_ast(node)) 340 Ty::from_hir(db, module, impl_block, &TypeRef::from_ast(node))
323 } 341 }
324 342
325 pub fn unit() -> Self { 343 pub fn unit() -> Self {
@@ -402,18 +420,19 @@ impl fmt::Display for Ty {
402fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> { 420fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> {
403 let syntax = f.syntax(db); 421 let syntax = f.syntax(db);
404 let module = f.module(db)?; 422 let module = f.module(db)?;
423 let impl_block = f.impl_block(db)?;
405 let node = syntax.borrowed(); 424 let node = syntax.borrowed();
406 // TODO we ignore type parameters for now 425 // TODO we ignore type parameters for now
407 let input = node 426 let input = node
408 .param_list() 427 .param_list()
409 .map(|pl| { 428 .map(|pl| {
410 pl.params() 429 pl.params()
411 .map(|p| Ty::from_ast_opt(db, &module, p.type_ref())) 430 .map(|p| Ty::from_ast_opt(db, &module, impl_block.as_ref(), p.type_ref()))
412 .collect() 431 .collect()
413 }) 432 })
414 .unwrap_or_else(|| Ok(Vec::new()))?; 433 .unwrap_or_else(|| Ok(Vec::new()))?;
415 let output = if let Some(type_ref) = node.ret_type().and_then(|rt| rt.type_ref()) { 434 let output = if let Some(type_ref) = node.ret_type().and_then(|rt| rt.type_ref()) {
416 Ty::from_ast(db, &module, type_ref)? 435 Ty::from_ast(db, &module, impl_block.as_ref(), type_ref)?
417 } else { 436 } else {
418 Ty::unit() 437 Ty::unit()
419 }; 438 };
@@ -467,12 +486,13 @@ pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name)
467 ), 486 ),
468 }; 487 };
469 let module = def_id.module(db)?; 488 let module = def_id.module(db)?;
489 let impl_block = def_id.impl_block(db)?;
470 let type_ref = if let Some(tr) = variant_data.get_field_type_ref(&field) { 490 let type_ref = if let Some(tr) = variant_data.get_field_type_ref(&field) {
471 tr 491 tr
472 } else { 492 } else {
473 return Ok(Ty::Unknown); 493 return Ok(Ty::Unknown);
474 }; 494 };
475 Ty::from_hir(db, &module, &type_ref) 495 Ty::from_hir(db, &module, impl_block.as_ref(), &type_ref)
476} 496}
477 497
478/// The result of type inference: A mapping from expressions and patterns to types. 498/// The result of type inference: A mapping from expressions and patterns to types.
@@ -499,12 +519,18 @@ struct InferenceContext<'a, D: HirDatabase> {
499 /// The self param for the current method, if it exists. 519 /// The self param for the current method, if it exists.
500 self_param: Option<LocalSyntaxPtr>, 520 self_param: Option<LocalSyntaxPtr>,
501 module: Module, 521 module: Module,
522 impl_block: Option<ImplBlock>,
502 var_unification_table: InPlaceUnificationTable<TypeVarId>, 523 var_unification_table: InPlaceUnificationTable<TypeVarId>,
503 type_of: FxHashMap<LocalSyntaxPtr, Ty>, 524 type_of: FxHashMap<LocalSyntaxPtr, Ty>,
504} 525}
505 526
506impl<'a, D: HirDatabase> InferenceContext<'a, D> { 527impl<'a, D: HirDatabase> InferenceContext<'a, D> {
507 fn new(db: &'a D, scopes: Arc<FnScopes>, module: Module) -> Self { 528 fn new(
529 db: &'a D,
530 scopes: Arc<FnScopes>,
531 module: Module,
532 impl_block: Option<ImplBlock>,
533 ) -> Self {
508 InferenceContext { 534 InferenceContext {
509 type_of: FxHashMap::default(), 535 type_of: FxHashMap::default(),
510 var_unification_table: InPlaceUnificationTable::new(), 536 var_unification_table: InPlaceUnificationTable::new(),
@@ -512,6 +538,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
512 db, 538 db,
513 scopes, 539 scopes,
514 module, 540 module,
541 impl_block,
515 } 542 }
516 } 543 }
517 544
@@ -835,7 +862,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
835 } 862 }
836 ast::Expr::CastExpr(e) => { 863 ast::Expr::CastExpr(e) => {
837 let _inner_ty = self.infer_expr_opt(e.expr(), &Expectation::none())?; 864 let _inner_ty = self.infer_expr_opt(e.expr(), &Expectation::none())?;
838 let cast_ty = Ty::from_ast_opt(self.db, &self.module, e.type_ref())?; 865 let cast_ty = Ty::from_ast_opt(
866 self.db,
867 &self.module,
868 self.impl_block.as_ref(),
869 e.type_ref(),
870 )?;
839 let cast_ty = self.insert_type_vars(cast_ty); 871 let cast_ty = self.insert_type_vars(cast_ty);
840 // TODO do the coercion... 872 // TODO do the coercion...
841 cast_ty 873 cast_ty
@@ -889,7 +921,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
889 for stmt in node.statements() { 921 for stmt in node.statements() {
890 match stmt { 922 match stmt {
891 ast::Stmt::LetStmt(stmt) => { 923 ast::Stmt::LetStmt(stmt) => {
892 let decl_ty = Ty::from_ast_opt(self.db, &self.module, stmt.type_ref())?; 924 let decl_ty = Ty::from_ast_opt(
925 self.db,
926 &self.module,
927 self.impl_block.as_ref(),
928 stmt.type_ref(),
929 )?;
893 let decl_ty = self.insert_type_vars(decl_ty); 930 let decl_ty = self.insert_type_vars(decl_ty);
894 let ty = if let Some(expr) = stmt.initializer() { 931 let ty = if let Some(expr) = stmt.initializer() {
895 let expr_ty = self.infer_expr(expr, &Expectation::has_type(decl_ty))?; 932 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<Arc<InferenceRe
921 let function = Function::new(def_id); // TODO: consts also need inference 958 let function = Function::new(def_id); // TODO: consts also need inference
922 let scopes = function.scopes(db); 959 let scopes = function.scopes(db);
923 let module = function.module(db)?; 960 let module = function.module(db)?;
924 let mut ctx = InferenceContext::new(db, scopes, module); 961 let impl_block = function.impl_block(db)?;
962 let mut ctx = InferenceContext::new(db, scopes, module, impl_block);
925 963
926 let syntax = function.syntax(db); 964 let syntax = function.syntax(db);
927 let node = syntax.borrowed(); 965 let node = syntax.borrowed();
928 966
929 if let Some(param_list) = node.param_list() { 967 if let Some(param_list) = node.param_list() {
930 if let Some(self_param) = param_list.self_param() { 968 if let Some(self_param) = param_list.self_param() {
931 let self_type = if let Some(impl_block) = function.impl_block(db)? { 969 let self_type = if let Some(impl_block) = &ctx.impl_block {
932 if let Some(type_ref) = self_param.type_ref() { 970 if let Some(type_ref) = self_param.type_ref() {
933 let ty = Ty::from_ast(db, &ctx.module, type_ref)?; 971 let ty = Ty::from_ast(db, &ctx.module, ctx.impl_block.as_ref(), type_ref)?;
934 ctx.insert_type_vars(ty) 972 ctx.insert_type_vars(ty)
935 } else { 973 } else {
936 let ty = Ty::from_hir(db, &ctx.module, impl_block.target())?; 974 // TODO this should be handled by desugaring during HIR conversion
975 let ty = Ty::from_hir(
976 db,
977 &ctx.module,
978 ctx.impl_block.as_ref(),
979 impl_block.target(),
980 )?;
937 let ty = match self_param.flavor() { 981 let ty = match self_param.flavor() {
938 ast::SelfParamFlavor::Owned => ty, 982 ast::SelfParamFlavor::Owned => ty,
939 ast::SelfParamFlavor::Ref => Ty::Ref(Arc::new(ty), Mutability::Shared), 983 ast::SelfParamFlavor::Ref => Ty::Ref(Arc::new(ty), Mutability::Shared),
@@ -961,7 +1005,7 @@ pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<InferenceRe
961 continue; 1005 continue;
962 }; 1006 };
963 let ty = if let Some(type_ref) = param.type_ref() { 1007 let ty = if let Some(type_ref) = param.type_ref() {
964 let ty = Ty::from_ast(db, &ctx.module, type_ref)?; 1008 let ty = Ty::from_ast(db, &ctx.module, ctx.impl_block.as_ref(), type_ref)?;
965 ctx.insert_type_vars(ty) 1009 ctx.insert_type_vars(ty)
966 } else { 1010 } else {
967 // missing type annotation 1011 // missing type annotation
@@ -972,7 +1016,7 @@ pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<InferenceRe
972 } 1016 }
973 1017
974 let ret_ty = if let Some(type_ref) = node.ret_type().and_then(|n| n.type_ref()) { 1018 let ret_ty = if let Some(type_ref) = node.ret_type().and_then(|n| n.type_ref()) {
975 let ty = Ty::from_ast(db, &ctx.module, type_ref)?; 1019 let ty = Ty::from_ast(db, &ctx.module, ctx.impl_block.as_ref(), type_ref)?;
976 ctx.insert_type_vars(ty) 1020 ctx.insert_type_vars(ty)
977 } else { 1021 } else {
978 Ty::unit() 1022 Ty::unit()
diff --git a/crates/ra_hir/src/ty/tests/data/0007_self.txt b/crates/ra_hir/src/ty/tests/data/0007_self.txt
index 0dd61da55..db4ba17d0 100644
--- a/crates/ra_hir/src/ty/tests/data/0007_self.txt
+++ b/crates/ra_hir/src/ty/tests/data/0007_self.txt
@@ -2,5 +2,5 @@
2[34; 38) 'self': &S 2[34; 38) 'self': &S
3[40; 61) '{ ... }': () 3[40; 61) '{ ... }': ()
4[88; 109) '{ ... }': () 4[88; 109) '{ ... }': ()
5[98; 102) 'self': &[unknown] 5[98; 102) 'self': &S
6[75; 79) 'self': &[unknown] 6[75; 79) 'self': &S