diff options
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 113 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 39 |
2 files changed, 71 insertions, 81 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 66b204dcd..88bce1960 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -2,24 +2,21 @@ mod primitive; | |||
2 | #[cfg(test)] | 2 | #[cfg(test)] |
3 | mod tests; | 3 | mod tests; |
4 | 4 | ||
5 | use rustc_hash::{FxHashMap, FxHashSet}; | ||
6 | |||
7 | use std::sync::Arc; | 5 | use std::sync::Arc; |
8 | use std::collections::HashMap; | ||
9 | use std::fmt; | 6 | use std::fmt; |
10 | 7 | ||
8 | use rustc_hash::{FxHashMap}; | ||
9 | |||
11 | use ra_db::LocalSyntaxPtr; | 10 | use ra_db::LocalSyntaxPtr; |
12 | use ra_syntax::{ | 11 | use ra_syntax::{ |
13 | TextRange, TextUnit, SmolStr, | 12 | SmolStr, |
14 | algo::visit::{visitor, Visitor}, | 13 | ast::{self, AstNode, LoopBodyOwner, ArgListOwner}, |
15 | ast::{self, AstNode, DocCommentsOwner, NameOwner, LoopBodyOwner, ArgListOwner}, | ||
16 | SyntaxNodeRef | 14 | SyntaxNodeRef |
17 | }; | 15 | }; |
18 | 16 | ||
19 | use crate::{ | 17 | use crate::{ |
20 | FnScopes, | 18 | FnScopes, |
21 | db::HirDatabase, | 19 | db::HirDatabase, |
22 | arena::{Arena, Id}, | ||
23 | }; | 20 | }; |
24 | 21 | ||
25 | // pub(crate) type TypeId = Id<Ty>; | 22 | // pub(crate) type TypeId = Id<Ty>; |
@@ -150,9 +147,17 @@ impl Ty { | |||
150 | TupleType(_inner) => Ty::Unknown, // TODO | 147 | TupleType(_inner) => Ty::Unknown, // TODO |
151 | NeverType(..) => Ty::Never, | 148 | NeverType(..) => Ty::Never, |
152 | PathType(inner) => { | 149 | PathType(inner) => { |
153 | let path = if let Some(p) = inner.path() { p } else { return Ty::Unknown }; | 150 | let path = if let Some(p) = inner.path() { |
151 | p | ||
152 | } else { | ||
153 | return Ty::Unknown; | ||
154 | }; | ||
154 | if path.qualifier().is_none() { | 155 | if path.qualifier().is_none() { |
155 | let name = path.segment().and_then(|s| s.name_ref()).map(|n| n.text()).unwrap_or(SmolStr::new("")); | 156 | let name = path |
157 | .segment() | ||
158 | .and_then(|s| s.name_ref()) | ||
159 | .map(|n| n.text()) | ||
160 | .unwrap_or(SmolStr::new("")); | ||
156 | if let Some(int_ty) = primitive::IntTy::from_string(&name) { | 161 | if let Some(int_ty) = primitive::IntTy::from_string(&name) { |
157 | Ty::Int(int_ty) | 162 | Ty::Int(int_ty) |
158 | } else if let Some(uint_ty) = primitive::UintTy::from_string(&name) { | 163 | } else if let Some(uint_ty) = primitive::UintTy::from_string(&name) { |
@@ -167,16 +172,16 @@ impl Ty { | |||
167 | // TODO | 172 | // TODO |
168 | Ty::Unknown | 173 | Ty::Unknown |
169 | } | 174 | } |
170 | }, | 175 | } |
171 | PointerType(_inner) => Ty::Unknown, // TODO | 176 | PointerType(_inner) => Ty::Unknown, // TODO |
172 | ArrayType(_inner) => Ty::Unknown, // TODO | 177 | ArrayType(_inner) => Ty::Unknown, // TODO |
173 | SliceType(_inner) => Ty::Unknown, // TODO | 178 | SliceType(_inner) => Ty::Unknown, // TODO |
174 | ReferenceType(_inner) => Ty::Unknown, // TODO | 179 | ReferenceType(_inner) => Ty::Unknown, // TODO |
175 | PlaceholderType(_inner) => Ty::Unknown, // TODO | 180 | PlaceholderType(_inner) => Ty::Unknown, // TODO |
176 | FnPointerType(_inner) => Ty::Unknown, // TODO | 181 | FnPointerType(_inner) => Ty::Unknown, // TODO |
177 | ForType(_inner) => Ty::Unknown, // TODO | 182 | ForType(_inner) => Ty::Unknown, // TODO |
178 | ImplTraitType(_inner) => Ty::Unknown, // TODO | 183 | ImplTraitType(_inner) => Ty::Unknown, // TODO |
179 | DynTraitType(_inner) => Ty::Unknown, // TODO | 184 | DynTraitType(_inner) => Ty::Unknown, // TODO |
180 | } | 185 | } |
181 | } | 186 | } |
182 | 187 | ||
@@ -203,7 +208,7 @@ impl fmt::Display for Ty { | |||
203 | } | 208 | } |
204 | write!(f, ")") | 209 | write!(f, ")") |
205 | } | 210 | } |
206 | Ty::Unknown => write!(f, "[unknown]") | 211 | Ty::Unknown => write!(f, "[unknown]"), |
207 | } | 212 | } |
208 | } | 213 | } |
209 | } | 214 | } |
@@ -230,7 +235,7 @@ impl InferenceContext { | |||
230 | fn new(scopes: Arc<FnScopes>) -> Self { | 235 | fn new(scopes: Arc<FnScopes>) -> Self { |
231 | InferenceContext { | 236 | InferenceContext { |
232 | type_for: FxHashMap::default(), | 237 | type_for: FxHashMap::default(), |
233 | scopes | 238 | scopes, |
234 | } | 239 | } |
235 | } | 240 | } |
236 | 241 | ||
@@ -238,7 +243,7 @@ impl InferenceContext { | |||
238 | self.type_for.insert(LocalSyntaxPtr::new(node), ty); | 243 | self.type_for.insert(LocalSyntaxPtr::new(node), ty); |
239 | } | 244 | } |
240 | 245 | ||
241 | fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { | 246 | fn unify(&mut self, _ty1: &Ty, _ty2: &Ty) -> bool { |
242 | unimplemented!() | 247 | unimplemented!() |
243 | } | 248 | } |
244 | 249 | ||
@@ -303,7 +308,7 @@ impl InferenceContext { | |||
303 | if let Some(expr) = e.iterable() { | 308 | if let Some(expr) = e.iterable() { |
304 | self.infer_expr(expr); | 309 | self.infer_expr(expr); |
305 | } | 310 | } |
306 | if let Some(pat) = e.pat() { | 311 | if let Some(_pat) = e.pat() { |
307 | // TODO write type for pat | 312 | // TODO write type for pat |
308 | } | 313 | } |
309 | if let Some(block) = e.loop_body() { | 314 | if let Some(block) = e.loop_body() { |
@@ -313,7 +318,7 @@ impl InferenceContext { | |||
313 | Ty::Unknown | 318 | Ty::Unknown |
314 | } | 319 | } |
315 | ast::Expr::LambdaExpr(e) => { | 320 | ast::Expr::LambdaExpr(e) => { |
316 | let body_ty = if let Some(body) = e.body() { | 321 | let _body_ty = if let Some(body) = e.body() { |
317 | self.infer_expr(body) | 322 | self.infer_expr(body) |
318 | } else { | 323 | } else { |
319 | Ty::Unknown | 324 | Ty::Unknown |
@@ -339,7 +344,7 @@ impl InferenceContext { | |||
339 | Ty::Unknown | 344 | Ty::Unknown |
340 | } | 345 | } |
341 | ast::Expr::MatchExpr(e) => { | 346 | ast::Expr::MatchExpr(e) => { |
342 | let ty = if let Some(match_expr) = e.expr() { | 347 | let _ty = if let Some(match_expr) = e.expr() { |
343 | self.infer_expr(match_expr) | 348 | self.infer_expr(match_expr) |
344 | } else { | 349 | } else { |
345 | Ty::Unknown | 350 | Ty::Unknown |
@@ -348,7 +353,7 @@ impl InferenceContext { | |||
348 | for arm in match_arm_list.arms() { | 353 | for arm in match_arm_list.arms() { |
349 | // TODO type the bindings in pat | 354 | // TODO type the bindings in pat |
350 | // TODO type the guard | 355 | // TODO type the guard |
351 | let ty = if let Some(e) = arm.expr() { | 356 | let _ty = if let Some(e) = arm.expr() { |
352 | self.infer_expr(e) | 357 | self.infer_expr(e) |
353 | } else { | 358 | } else { |
354 | Ty::Unknown | 359 | Ty::Unknown |
@@ -360,12 +365,8 @@ impl InferenceContext { | |||
360 | Ty::Unknown | 365 | Ty::Unknown |
361 | } | 366 | } |
362 | } | 367 | } |
363 | ast::Expr::TupleExpr(e) => { | 368 | ast::Expr::TupleExpr(_e) => Ty::Unknown, |
364 | Ty::Unknown | 369 | ast::Expr::ArrayExpr(_e) => Ty::Unknown, |
365 | } | ||
366 | ast::Expr::ArrayExpr(e) => { | ||
367 | Ty::Unknown | ||
368 | } | ||
369 | ast::Expr::PathExpr(e) => { | 370 | ast::Expr::PathExpr(e) => { |
370 | if let Some(p) = e.path() { | 371 | if let Some(p) = e.path() { |
371 | if p.qualifier().is_none() { | 372 | if p.qualifier().is_none() { |
@@ -392,12 +393,8 @@ impl InferenceContext { | |||
392 | Ty::Unknown | 393 | Ty::Unknown |
393 | } | 394 | } |
394 | } | 395 | } |
395 | ast::Expr::ContinueExpr(e) => { | 396 | ast::Expr::ContinueExpr(_e) => Ty::Never, |
396 | Ty::Never | 397 | ast::Expr::BreakExpr(_e) => Ty::Never, |
397 | } | ||
398 | ast::Expr::BreakExpr(e) => { | ||
399 | Ty::Never | ||
400 | } | ||
401 | ast::Expr::ParenExpr(e) => { | 398 | ast::Expr::ParenExpr(e) => { |
402 | if let Some(e) = e.expr() { | 399 | if let Some(e) = e.expr() { |
403 | self.infer_expr(e) | 400 | self.infer_expr(e) |
@@ -405,9 +402,7 @@ impl InferenceContext { | |||
405 | Ty::Unknown | 402 | Ty::Unknown |
406 | } | 403 | } |
407 | } | 404 | } |
408 | ast::Expr::Label(e) => { | 405 | ast::Expr::Label(_e) => Ty::Unknown, |
409 | Ty::Unknown | ||
410 | } | ||
411 | ast::Expr::ReturnExpr(e) => { | 406 | ast::Expr::ReturnExpr(e) => { |
412 | if let Some(e) = e.expr() { | 407 | if let Some(e) = e.expr() { |
413 | // TODO unify with return type | 408 | // TODO unify with return type |
@@ -419,21 +414,15 @@ impl InferenceContext { | |||
419 | // Can this even occur outside of a match expression? | 414 | // Can this even occur outside of a match expression? |
420 | Ty::Unknown | 415 | Ty::Unknown |
421 | } | 416 | } |
422 | ast::Expr::StructLit(e) => { | 417 | ast::Expr::StructLit(_e) => Ty::Unknown, |
423 | Ty::Unknown | ||
424 | } | ||
425 | ast::Expr::NamedFieldList(_) | ast::Expr::NamedField(_) => { | 418 | ast::Expr::NamedFieldList(_) | ast::Expr::NamedField(_) => { |
426 | // Can this even occur outside of a struct literal? | 419 | // Can this even occur outside of a struct literal? |
427 | Ty::Unknown | 420 | Ty::Unknown |
428 | } | 421 | } |
429 | ast::Expr::IndexExpr(e) => { | 422 | ast::Expr::IndexExpr(_e) => Ty::Unknown, |
430 | Ty::Unknown | 423 | ast::Expr::FieldExpr(_e) => Ty::Unknown, |
431 | } | ||
432 | ast::Expr::FieldExpr(e) => { | ||
433 | Ty::Unknown | ||
434 | } | ||
435 | ast::Expr::TryExpr(e) => { | 424 | ast::Expr::TryExpr(e) => { |
436 | let inner_ty = if let Some(e) = e.expr() { | 425 | let _inner_ty = if let Some(e) = e.expr() { |
437 | self.infer_expr(e) | 426 | self.infer_expr(e) |
438 | } else { | 427 | } else { |
439 | Ty::Unknown | 428 | Ty::Unknown |
@@ -441,7 +430,7 @@ impl InferenceContext { | |||
441 | Ty::Unknown | 430 | Ty::Unknown |
442 | } | 431 | } |
443 | ast::Expr::CastExpr(e) => { | 432 | ast::Expr::CastExpr(e) => { |
444 | let inner_ty = if let Some(e) = e.expr() { | 433 | let _inner_ty = if let Some(e) = e.expr() { |
445 | self.infer_expr(e) | 434 | self.infer_expr(e) |
446 | } else { | 435 | } else { |
447 | Ty::Unknown | 436 | Ty::Unknown |
@@ -451,7 +440,7 @@ impl InferenceContext { | |||
451 | cast_ty | 440 | cast_ty |
452 | } | 441 | } |
453 | ast::Expr::RefExpr(e) => { | 442 | ast::Expr::RefExpr(e) => { |
454 | let inner_ty = if let Some(e) = e.expr() { | 443 | let _inner_ty = if let Some(e) = e.expr() { |
455 | self.infer_expr(e) | 444 | self.infer_expr(e) |
456 | } else { | 445 | } else { |
457 | Ty::Unknown | 446 | Ty::Unknown |
@@ -459,22 +448,16 @@ impl InferenceContext { | |||
459 | Ty::Unknown | 448 | Ty::Unknown |
460 | } | 449 | } |
461 | ast::Expr::PrefixExpr(e) => { | 450 | ast::Expr::PrefixExpr(e) => { |
462 | let inner_ty = if let Some(e) = e.expr() { | 451 | let _inner_ty = if let Some(e) = e.expr() { |
463 | self.infer_expr(e) | 452 | self.infer_expr(e) |
464 | } else { | 453 | } else { |
465 | Ty::Unknown | 454 | Ty::Unknown |
466 | }; | 455 | }; |
467 | Ty::Unknown | 456 | Ty::Unknown |
468 | } | 457 | } |
469 | ast::Expr::RangeExpr(e) => { | 458 | ast::Expr::RangeExpr(_e) => Ty::Unknown, |
470 | Ty::Unknown | 459 | ast::Expr::BinExpr(_e) => Ty::Unknown, |
471 | } | 460 | ast::Expr::Literal(_e) => Ty::Unknown, |
472 | ast::Expr::BinExpr(e) => { | ||
473 | Ty::Unknown | ||
474 | } | ||
475 | ast::Expr::Literal(e) => { | ||
476 | Ty::Unknown | ||
477 | } | ||
478 | }; | 461 | }; |
479 | self.write_ty(expr.syntax(), ty.clone()); | 462 | self.write_ty(expr.syntax(), ty.clone()); |
480 | ty | 463 | ty |
@@ -505,7 +488,7 @@ impl InferenceContext { | |||
505 | } | 488 | } |
506 | } | 489 | } |
507 | 490 | ||
508 | pub fn infer(db: &impl HirDatabase, node: ast::FnDef, scopes: Arc<FnScopes>) -> InferenceResult { | 491 | pub fn infer(_db: &impl HirDatabase, node: ast::FnDef, scopes: Arc<FnScopes>) -> InferenceResult { |
509 | let mut ctx = InferenceContext::new(scopes); | 492 | let mut ctx = InferenceContext::new(scopes); |
510 | 493 | ||
511 | for param in node.param_list().unwrap().params() { | 494 | for param in node.param_list().unwrap().params() { |
@@ -522,5 +505,7 @@ pub fn infer(db: &impl HirDatabase, node: ast::FnDef, scopes: Arc<FnScopes>) -> | |||
522 | 505 | ||
523 | // TODO 'resolve' the types: replace inference variables by their inferred results | 506 | // TODO 'resolve' the types: replace inference variables by their inferred results |
524 | 507 | ||
525 | InferenceResult { type_for: ctx.type_for } | 508 | InferenceResult { |
509 | type_for: ctx.type_for, | ||
510 | } | ||
526 | } | 511 | } |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 98eedaa3f..0880b51bc 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -1,31 +1,38 @@ | |||
1 | use std::fmt::Write; | 1 | use std::fmt::Write; |
2 | use std::sync::Arc; | 2 | use std::path::{PathBuf}; |
3 | use std::path::{Path, PathBuf}; | ||
4 | 3 | ||
5 | use salsa::Database; | 4 | use ra_db::{SyntaxDatabase}; |
6 | use ra_db::{FilesDatabase, CrateGraph, SyntaxDatabase}; | 5 | use ra_syntax::ast::{self, AstNode}; |
7 | use ra_syntax::{SmolStr, algo::visit::{visitor, Visitor}, ast::{self, AstNode}}; | ||
8 | use test_utils::{project_dir, dir_tests}; | 6 | use test_utils::{project_dir, dir_tests}; |
9 | use relative_path::RelativePath; | ||
10 | |||
11 | use crate::{source_binder, mock::WORKSPACE, module::ModuleSourceNode}; | ||
12 | 7 | ||
13 | use crate::{ | 8 | use crate::{ |
14 | self as hir, | 9 | source_binder, |
15 | db::HirDatabase, | ||
16 | mock::MockDatabase, | 10 | mock::MockDatabase, |
17 | }; | 11 | }; |
18 | 12 | ||
19 | fn infer_file(content: &str) -> String { | 13 | fn infer_file(content: &str) -> String { |
20 | let (db, source_root, file_id) = MockDatabase::with_single_file(content); | 14 | let (db, _, file_id) = MockDatabase::with_single_file(content); |
21 | let source_file = db.source_file(file_id); | 15 | let source_file = db.source_file(file_id); |
22 | let mut acc = String::new(); | 16 | let mut acc = String::new(); |
23 | for fn_def in source_file.syntax().descendants().filter_map(ast::FnDef::cast) { | 17 | for fn_def in source_file |
24 | let func = source_binder::function_from_source(&db, file_id, fn_def).unwrap().unwrap(); | 18 | .syntax() |
19 | .descendants() | ||
20 | .filter_map(ast::FnDef::cast) | ||
21 | { | ||
22 | let func = source_binder::function_from_source(&db, file_id, fn_def) | ||
23 | .unwrap() | ||
24 | .unwrap(); | ||
25 | let inference_result = func.infer(&db); | 25 | let inference_result = func.infer(&db); |
26 | for (syntax_ptr, ty) in &inference_result.type_for { | 26 | for (syntax_ptr, ty) in &inference_result.type_for { |
27 | let node = syntax_ptr.resolve(&source_file); | 27 | let node = syntax_ptr.resolve(&source_file); |
28 | write!(acc, "{} '{}': {}\n", syntax_ptr.range(), ellipsize(node.text().to_string().replace("\n", " "), 15), ty); | 28 | write!( |
29 | acc, | ||
30 | "{} '{}': {}\n", | ||
31 | syntax_ptr.range(), | ||
32 | ellipsize(node.text().to_string().replace("\n", " "), 15), | ||
33 | ty | ||
34 | ) | ||
35 | .unwrap(); | ||
29 | } | 36 | } |
30 | } | 37 | } |
31 | acc | 38 | acc |
@@ -51,9 +58,7 @@ fn ellipsize(mut text: String, max_len: usize) -> String { | |||
51 | 58 | ||
52 | #[test] | 59 | #[test] |
53 | pub fn infer_tests() { | 60 | pub fn infer_tests() { |
54 | dir_tests(&test_data_dir(), &["."], |text, _path| { | 61 | dir_tests(&test_data_dir(), &["."], |text, _path| infer_file(text)); |
55 | infer_file(text) | ||
56 | }); | ||
57 | } | 62 | } |
58 | 63 | ||
59 | fn test_data_dir() -> PathBuf { | 64 | fn test_data_dir() -> PathBuf { |