aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_analysis/src/imp.rs10
-rw-r--r--crates/ra_hir/src/ty.rs113
-rw-r--r--crates/ra_hir/src/ty/tests.rs39
-rw-r--r--crates/ra_syntax/tests/test.rs56
4 files changed, 110 insertions, 108 deletions
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs
index 4e0631679..f2912d235 100644
--- a/crates/ra_analysis/src/imp.rs
+++ b/crates/ra_analysis/src/imp.rs
@@ -516,8 +516,14 @@ impl AnalysisImpl {
516 let syntax = file.syntax(); 516 let syntax = file.syntax();
517 let node = find_covering_node(syntax, range); 517 let node = find_covering_node(syntax, range);
518 let parent_fn = node.ancestors().filter_map(FnDef::cast).next(); 518 let parent_fn = node.ancestors().filter_map(FnDef::cast).next();
519 let parent_fn = if let Some(p) = parent_fn { p } else { return Ok(None) }; 519 let parent_fn = if let Some(p) = parent_fn {
520 let function = ctry!(source_binder::function_from_source(&*self.db, file_id, parent_fn)?); 520 p
521 } else {
522 return Ok(None);
523 };
524 let function = ctry!(source_binder::function_from_source(
525 &*self.db, file_id, parent_fn
526 )?);
521 let infer = function.infer(&*self.db); 527 let infer = function.infer(&*self.db);
522 Ok(infer.type_of_node(node).map(|t| t.to_string())) 528 Ok(infer.type_of_node(node).map(|t| t.to_string()))
523 } 529 }
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)]
3mod tests; 3mod tests;
4 4
5use rustc_hash::{FxHashMap, FxHashSet};
6
7use std::sync::Arc; 5use std::sync::Arc;
8use std::collections::HashMap;
9use std::fmt; 6use std::fmt;
10 7
8use rustc_hash::{FxHashMap};
9
11use ra_db::LocalSyntaxPtr; 10use ra_db::LocalSyntaxPtr;
12use ra_syntax::{ 11use 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
19use crate::{ 17use 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
508pub fn infer(db: &impl HirDatabase, node: ast::FnDef, scopes: Arc<FnScopes>) -> InferenceResult { 491pub 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 @@
1use std::fmt::Write; 1use std::fmt::Write;
2use std::sync::Arc; 2use std::path::{PathBuf};
3use std::path::{Path, PathBuf};
4 3
5use salsa::Database; 4use ra_db::{SyntaxDatabase};
6use ra_db::{FilesDatabase, CrateGraph, SyntaxDatabase}; 5use ra_syntax::ast::{self, AstNode};
7use ra_syntax::{SmolStr, algo::visit::{visitor, Visitor}, ast::{self, AstNode}};
8use test_utils::{project_dir, dir_tests}; 6use test_utils::{project_dir, dir_tests};
9use relative_path::RelativePath;
10
11use crate::{source_binder, mock::WORKSPACE, module::ModuleSourceNode};
12 7
13use crate::{ 8use crate::{
14 self as hir, 9 source_binder,
15 db::HirDatabase,
16 mock::MockDatabase, 10 mock::MockDatabase,
17}; 11};
18 12
19fn infer_file(content: &str) -> String { 13fn 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]
53pub fn infer_tests() { 60pub 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
59fn test_data_dir() -> PathBuf { 64fn test_data_dir() -> PathBuf {
diff --git a/crates/ra_syntax/tests/test.rs b/crates/ra_syntax/tests/test.rs
index 9d94a1a23..2235dc401 100644
--- a/crates/ra_syntax/tests/test.rs
+++ b/crates/ra_syntax/tests/test.rs
@@ -1,12 +1,10 @@
1extern crate ra_syntax; 1extern crate ra_syntax;
2#[macro_use]
3extern crate test_utils; 2extern crate test_utils;
4extern crate walkdir; 3extern crate walkdir;
5 4
6use std::{ 5use std::{
7 fmt::Write, 6 fmt::Write,
8 fs, 7 path::{PathBuf, Component},
9 path::{Path, PathBuf, Component},
10}; 8};
11 9
12use test_utils::{project_dir, dir_tests, read_text, collect_tests}; 10use test_utils::{project_dir, dir_tests, read_text, collect_tests};
@@ -25,28 +23,36 @@ fn lexer_tests() {
25 23
26#[test] 24#[test]
27fn parser_tests() { 25fn parser_tests() {
28 dir_tests(&test_data_dir(), &["parser/inline/ok", "parser/ok"], |text, path| { 26 dir_tests(
29 let file = SourceFileNode::parse(text); 27 &test_data_dir(),
30 let errors = file.errors(); 28 &["parser/inline/ok", "parser/ok"],
31 assert_eq!( 29 |text, path| {
32 &*errors, 30 let file = SourceFileNode::parse(text);
33 &[] as &[ra_syntax::SyntaxError], 31 let errors = file.errors();
34 "There should be no errors in the file {:?}", 32 assert_eq!(
35 path.display() 33 &*errors,
36 ); 34 &[] as &[ra_syntax::SyntaxError],
37 dump_tree(file.syntax()) 35 "There should be no errors in the file {:?}",
38 }); 36 path.display()
39 dir_tests(&test_data_dir(), &["parser/err", "parser/inline/err"], |text, path| { 37 );
40 let file = SourceFileNode::parse(text); 38 dump_tree(file.syntax())
41 let errors = file.errors(); 39 },
42 assert_ne!( 40 );
43 &*errors, 41 dir_tests(
44 &[] as &[ra_syntax::SyntaxError], 42 &test_data_dir(),
45 "There should be errors in the file {:?}", 43 &["parser/err", "parser/inline/err"],
46 path.display() 44 |text, path| {
47 ); 45 let file = SourceFileNode::parse(text);
48 dump_tree(file.syntax()) 46 let errors = file.errors();
49 }); 47 assert_ne!(
48 &*errors,
49 &[] as &[ra_syntax::SyntaxError],
50 "There should be errors in the file {:?}",
51 path.display()
52 );
53 dump_tree(file.syntax())
54 },
55 );
50} 56}
51 57
52#[test] 58#[test]