aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock8
-rw-r--r--crates/ra_assists/src/handlers/reorder_fields.rs6
-rw-r--r--crates/ra_hir/src/code_model.rs9
-rw-r--r--crates/ra_hir_ty/src/db.rs4
-rw-r--r--crates/ra_hir_ty/src/display.rs18
-rw-r--r--crates/ra_hir_ty/src/lower.rs43
-rw-r--r--crates/ra_hir_ty/src/test_db.rs13
-rw-r--r--crates/ra_hir_ty/src/tests.rs50
-rw-r--r--crates/ra_hir_ty/src/tests/coercion.rs3
-rw-r--r--crates/ra_hir_ty/src/tests/display_source_code.rs49
-rw-r--r--crates/ra_hir_ty/src/tests/macros.rs116
-rw-r--r--crates/ra_hir_ty/src/tests/method_resolution.rs158
-rw-r--r--crates/ra_hir_ty/src/tests/never_type.rs118
-rw-r--r--crates/ra_hir_ty/src/tests/regression.rs21
-rw-r--r--crates/ra_hir_ty/src/tests/simple.rs134
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs342
-rw-r--r--crates/ra_ssr/src/lib.rs3
-rw-r--r--crates/ra_ssr/src/matching.rs2
-rw-r--r--crates/ra_ssr/src/parsing.rs2
-rw-r--r--crates/ra_ssr/src/replacing.rs33
-rw-r--r--crates/ra_ssr/src/tests.rs17
-rw-r--r--crates/ra_syntax/src/algo.rs4
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs10
-rw-r--r--crates/rust-analyzer/src/cli/diagnostics.rs7
-rw-r--r--crates/rust-analyzer/src/diagnostics.rs10
-rw-r--r--crates/rust-analyzer/src/handlers.rs2
-rw-r--r--crates/test_utils/src/lib.rs36
-rw-r--r--docs/dev/README.md5
-rw-r--r--editors/code/src/commands.ts12
29 files changed, 608 insertions, 627 deletions
diff --git a/Cargo.lock b/Cargo.lock
index cf0479f0b..ca3d14a09 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -123,9 +123,9 @@ dependencies = [
123 123
124[[package]] 124[[package]]
125name = "cc" 125name = "cc"
126version = "1.0.55" 126version = "1.0.56"
127source = "registry+https://github.com/rust-lang/crates.io-index" 127source = "registry+https://github.com/rust-lang/crates.io-index"
128checksum = "b1be3409f94d7bdceeb5f5fac551039d9b3f00e25da7a74fc4d33400a0d96368" 128checksum = "77c1f1d60091c1b73e2b1f4560ab419204b178e625fa945ded7b660becd2bd46"
129 129
130[[package]] 130[[package]]
131name = "cfg-if" 131name = "cfg-if"
@@ -1621,9 +1621,9 @@ dependencies = [
1621 1621
1622[[package]] 1622[[package]]
1623name = "serde_json" 1623name = "serde_json"
1624version = "1.0.55" 1624version = "1.0.56"
1625source = "registry+https://github.com/rust-lang/crates.io-index" 1625source = "registry+https://github.com/rust-lang/crates.io-index"
1626checksum = "ec2c5d7e739bc07a3e73381a39d61fdb5f671c60c1df26a130690665803d8226" 1626checksum = "3433e879a558dde8b5e8feb2a04899cf34fdde1fafb894687e52105fc1162ac3"
1627dependencies = [ 1627dependencies = [
1628 "itoa", 1628 "itoa",
1629 "ryu", 1629 "ryu",
diff --git a/crates/ra_assists/src/handlers/reorder_fields.rs b/crates/ra_assists/src/handlers/reorder_fields.rs
index 897da2832..bc58ce5fe 100644
--- a/crates/ra_assists/src/handlers/reorder_fields.rs
+++ b/crates/ra_assists/src/handlers/reorder_fields.rs
@@ -1,7 +1,7 @@
1use std::collections::HashMap; 1use itertools::Itertools;
2use rustc_hash::FxHashMap;
2 3
3use hir::{Adt, ModuleDef, PathResolution, Semantics, Struct}; 4use hir::{Adt, ModuleDef, PathResolution, Semantics, Struct};
4use itertools::Itertools;
5use ra_ide_db::RootDatabase; 5use ra_ide_db::RootDatabase;
6use ra_syntax::{algo, ast, match_ast, AstNode, SyntaxKind, SyntaxKind::*, SyntaxNode}; 6use ra_syntax::{algo, ast, match_ast, AstNode, SyntaxKind, SyntaxKind::*, SyntaxNode};
7 7
@@ -87,7 +87,7 @@ fn struct_definition(path: &ast::Path, sema: &Semantics<RootDatabase>) -> Option
87 } 87 }
88} 88}
89 89
90fn compute_fields_ranks(path: &ast::Path, ctx: &AssistContext) -> Option<HashMap<String, usize>> { 90fn compute_fields_ranks(path: &ast::Path, ctx: &AssistContext) -> Option<FxHashMap<String, usize>> {
91 Some( 91 Some(
92 struct_definition(path, &ctx.sema)? 92 struct_definition(path, &ctx.sema)?
93 .fields(ctx.db) 93 .fields(ctx.db)
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 27e94b7fe..e86077dd6 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -543,7 +543,7 @@ impl_froms!(Adt: Struct, Union, Enum);
543impl Adt { 543impl Adt {
544 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { 544 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
545 let subst = db.generic_defaults(self.into()); 545 let subst = db.generic_defaults(self.into());
546 subst.iter().any(|ty| ty == &Ty::Unknown) 546 subst.iter().any(|ty| &ty.value == &Ty::Unknown)
547 } 547 }
548 548
549 /// Turns this ADT into a type. Any type parameters of the ADT will be 549 /// Turns this ADT into a type. Any type parameters of the ADT will be
@@ -775,7 +775,7 @@ pub struct TypeAlias {
775impl TypeAlias { 775impl TypeAlias {
776 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { 776 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
777 let subst = db.generic_defaults(self.id.into()); 777 let subst = db.generic_defaults(self.id.into());
778 subst.iter().any(|ty| ty == &Ty::Unknown) 778 subst.iter().any(|ty| &ty.value == &Ty::Unknown)
779 } 779 }
780 780
781 pub fn module(self, db: &dyn HirDatabase) -> Module { 781 pub fn module(self, db: &dyn HirDatabase) -> Module {
@@ -1035,7 +1035,10 @@ impl TypeParam {
1035 let local_idx = hir_ty::param_idx(db, self.id)?; 1035 let local_idx = hir_ty::param_idx(db, self.id)?;
1036 let resolver = self.id.parent.resolver(db.upcast()); 1036 let resolver = self.id.parent.resolver(db.upcast());
1037 let environment = TraitEnvironment::lower(db, &resolver); 1037 let environment = TraitEnvironment::lower(db, &resolver);
1038 params.get(local_idx).cloned().map(|ty| Type { 1038 let ty = params.get(local_idx)?.clone();
1039 let subst = Substs::type_params(db, self.id.parent);
1040 let ty = ty.subst(&subst.prefix(local_idx));
1041 Some(Type {
1039 krate: self.id.parent.module(db.upcast()).krate, 1042 krate: self.id.parent.module(db.upcast()).krate,
1040 ty: InEnvironment { value: ty, environment }, 1043 ty: InEnvironment { value: ty, environment },
1041 }) 1044 })
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs
index 7889b8d2c..cad553273 100644
--- a/crates/ra_hir_ty/src/db.rs
+++ b/crates/ra_hir_ty/src/db.rs
@@ -14,7 +14,7 @@ use crate::{
14 method_resolution::CrateImplDefs, 14 method_resolution::CrateImplDefs,
15 traits::{chalk, AssocTyValue, Impl}, 15 traits::{chalk, AssocTyValue, Impl},
16 Binders, CallableDef, GenericPredicate, InferenceResult, OpaqueTyId, PolyFnSig, 16 Binders, CallableDef, GenericPredicate, InferenceResult, OpaqueTyId, PolyFnSig,
17 ReturnTypeImplTraits, Substs, TraitRef, Ty, TyDefId, TypeCtor, ValueTyDefId, 17 ReturnTypeImplTraits, TraitRef, Ty, TyDefId, TypeCtor, ValueTyDefId,
18}; 18};
19use hir_expand::name::Name; 19use hir_expand::name::Name;
20 20
@@ -65,7 +65,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
65 fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<GenericPredicate>]>; 65 fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<GenericPredicate>]>;
66 66
67 #[salsa::invoke(crate::lower::generic_defaults_query)] 67 #[salsa::invoke(crate::lower::generic_defaults_query)]
68 fn generic_defaults(&self, def: GenericDefId) -> Substs; 68 fn generic_defaults(&self, def: GenericDefId) -> Arc<[Binders<Ty>]>;
69 69
70 #[salsa::invoke(crate::method_resolution::CrateImplDefs::impls_in_crate_query)] 70 #[salsa::invoke(crate::method_resolution::CrateImplDefs::impls_in_crate_query)]
71 fn impls_in_crate(&self, krate: CrateId) -> Arc<CrateImplDefs>; 71 fn impls_in_crate(&self, krate: CrateId) -> Arc<CrateImplDefs>;
diff --git a/crates/ra_hir_ty/src/display.rs b/crates/ra_hir_ty/src/display.rs
index 3c97e1354..23cea1a2a 100644
--- a/crates/ra_hir_ty/src/display.rs
+++ b/crates/ra_hir_ty/src/display.rs
@@ -308,7 +308,6 @@ impl HirDisplay for ApplicationTy {
308 } 308 }
309 309
310 if self.parameters.len() > 0 { 310 if self.parameters.len() > 0 {
311 let mut non_default_parameters = Vec::with_capacity(self.parameters.len());
312 let parameters_to_write = 311 let parameters_to_write =
313 if f.display_target.is_source_code() || f.omit_verbose_types() { 312 if f.display_target.is_source_code() || f.omit_verbose_types() {
314 match self 313 match self
@@ -319,20 +318,23 @@ impl HirDisplay for ApplicationTy {
319 { 318 {
320 None => self.parameters.0.as_ref(), 319 None => self.parameters.0.as_ref(),
321 Some(default_parameters) => { 320 Some(default_parameters) => {
321 let mut default_from = 0;
322 for (i, parameter) in self.parameters.iter().enumerate() { 322 for (i, parameter) in self.parameters.iter().enumerate() {
323 match (parameter, default_parameters.get(i)) { 323 match (parameter, default_parameters.get(i)) {
324 (&Ty::Unknown, _) | (_, None) => { 324 (&Ty::Unknown, _) | (_, None) => {
325 non_default_parameters.push(parameter.clone()) 325 default_from = i + 1;
326 } 326 }
327 (_, Some(default_parameter)) 327 (_, Some(default_parameter)) => {
328 if parameter != default_parameter => 328 let actual_default = default_parameter
329 { 329 .clone()
330 non_default_parameters.push(parameter.clone()) 330 .subst(&self.parameters.prefix(i));
331 if parameter != &actual_default {
332 default_from = i + 1;
333 }
331 } 334 }
332 _ => (),
333 } 335 }
334 } 336 }
335 &non_default_parameters 337 &self.parameters.0[0..default_from]
336 } 338 }
337 } 339 }
338 } else { 340 } else {
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index d5154f436..3dc154e92 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -578,11 +578,13 @@ fn substs_from_path_segment(
578 // (i.e. defaults aren't used). 578 // (i.e. defaults aren't used).
579 if !infer_args || had_explicit_args { 579 if !infer_args || had_explicit_args {
580 if let Some(def_generic) = def_generic { 580 if let Some(def_generic) = def_generic {
581 let default_substs = ctx.db.generic_defaults(def_generic); 581 let defaults = ctx.db.generic_defaults(def_generic);
582 assert_eq!(total_len, default_substs.len()); 582 assert_eq!(total_len, defaults.len());
583 583
584 for default_ty in default_substs.iter().skip(substs.len()) { 584 for default_ty in defaults.iter().skip(substs.len()) {
585 substs.push(default_ty.clone()); 585 // each default can depend on the previous parameters
586 let substs_so_far = Substs(substs.clone().into());
587 substs.push(default_ty.clone().subst(&substs_so_far));
586 } 588 }
587 } 589 }
588 } 590 }
@@ -945,17 +947,42 @@ pub(crate) fn generic_predicates_query(
945} 947}
946 948
947/// Resolve the default type params from generics 949/// Resolve the default type params from generics
948pub(crate) fn generic_defaults_query(db: &dyn HirDatabase, def: GenericDefId) -> Substs { 950pub(crate) fn generic_defaults_query(
951 db: &dyn HirDatabase,
952 def: GenericDefId,
953) -> Arc<[Binders<Ty>]> {
949 let resolver = def.resolver(db.upcast()); 954 let resolver = def.resolver(db.upcast());
950 let ctx = TyLoweringContext::new(db, &resolver); 955 let ctx =
956 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
951 let generic_params = generics(db.upcast(), def); 957 let generic_params = generics(db.upcast(), def);
952 958
953 let defaults = generic_params 959 let defaults = generic_params
954 .iter() 960 .iter()
955 .map(|(_idx, p)| p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(&ctx, t))) 961 .enumerate()
962 .map(|(idx, (_, p))| {
963 let mut ty = p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(&ctx, t));
964
965 // Each default can only refer to previous parameters.
966 ty.walk_mut_binders(
967 &mut |ty, binders| match ty {
968 Ty::Bound(BoundVar { debruijn, index }) if *debruijn == binders => {
969 if *index >= idx {
970 // type variable default referring to parameter coming
971 // after it. This is forbidden (FIXME: report
972 // diagnostic)
973 *ty = Ty::Unknown;
974 }
975 }
976 _ => {}
977 },
978 DebruijnIndex::INNERMOST,
979 );
980
981 Binders::new(idx, ty)
982 })
956 .collect(); 983 .collect();
957 984
958 Substs(defaults) 985 defaults
959} 986}
960 987
961fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig { 988fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
diff --git a/crates/ra_hir_ty/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs
index 9c2c6959d..0481a7b12 100644
--- a/crates/ra_hir_ty/src/test_db.rs
+++ b/crates/ra_hir_ty/src/test_db.rs
@@ -154,6 +154,19 @@ impl TestDB {
154 }); 154 });
155 (buf, count) 155 (buf, count)
156 } 156 }
157
158 pub fn all_files(&self) -> Vec<FileId> {
159 let mut res = Vec::new();
160 let crate_graph = self.crate_graph();
161 for krate in crate_graph.iter() {
162 let crate_def_map = self.crate_def_map(krate);
163 for (module_id, _) in crate_def_map.modules.iter() {
164 let file_id = crate_def_map[module_id].origin.file_id();
165 res.extend(file_id)
166 }
167 }
168 res
169 }
157} 170}
158 171
159impl TestDB { 172impl TestDB {
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs
index 2a85ce85d..5424e6bb1 100644
--- a/crates/ra_hir_ty/src/tests.rs
+++ b/crates/ra_hir_ty/src/tests.rs
@@ -17,17 +17,18 @@ use hir_def::{
17 item_scope::ItemScope, 17 item_scope::ItemScope,
18 keys, 18 keys,
19 nameres::CrateDefMap, 19 nameres::CrateDefMap,
20 AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId, ModuleId, 20 AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId,
21}; 21};
22use hir_expand::{db::AstDatabase, InFile}; 22use hir_expand::{db::AstDatabase, InFile};
23use insta::assert_snapshot; 23use insta::assert_snapshot;
24use ra_db::{fixture::WithFixture, salsa::Database, FilePosition, SourceDatabase}; 24use ra_db::{fixture::WithFixture, salsa::Database, FileRange, SourceDatabase};
25use ra_syntax::{ 25use ra_syntax::{
26 algo, 26 algo,
27 ast::{self, AstNode}, 27 ast::{self, AstNode},
28 SyntaxNode, 28 SyntaxNode,
29}; 29};
30use stdx::format_to; 30use stdx::format_to;
31use test_utils::extract_annotations;
31 32
32use crate::{ 33use crate::{
33 db::HirDatabase, display::HirDisplay, infer::TypeMismatch, test_db::TestDB, InferenceResult, Ty, 34 db::HirDatabase, display::HirDisplay, infer::TypeMismatch, test_db::TestDB, InferenceResult, Ty,
@@ -37,21 +38,38 @@ use crate::{
37// against snapshots of the expected results using insta. Use cargo-insta to 38// against snapshots of the expected results using insta. Use cargo-insta to
38// update the snapshots. 39// update the snapshots.
39 40
40fn type_at_pos(db: &TestDB, pos: FilePosition) -> String { 41fn check_types(ra_fixture: &str) {
41 type_at_pos_displayed(db, pos, |ty, _| ty.display(db).to_string()) 42 check_types_impl(ra_fixture, false)
42} 43}
43 44
44fn displayed_source_at_pos(db: &TestDB, pos: FilePosition) -> String { 45fn check_types_source_code(ra_fixture: &str) {
45 type_at_pos_displayed(db, pos, |ty, module_id| ty.display_source_code(db, module_id).unwrap()) 46 check_types_impl(ra_fixture, true)
46} 47}
47 48
48fn type_at_pos_displayed( 49fn check_types_impl(ra_fixture: &str, display_source: bool) {
49 db: &TestDB, 50 let db = TestDB::with_files(ra_fixture);
50 pos: FilePosition, 51 let mut checked_one = false;
51 display_fn: impl FnOnce(&Ty, ModuleId) -> String, 52 for file_id in db.all_files() {
52) -> String { 53 let text = db.parse(file_id).syntax_node().to_string();
54 let annotations = extract_annotations(&text);
55 for (range, expected) in annotations {
56 let ty = type_at_range(&db, FileRange { file_id, range });
57 let actual = if display_source {
58 let module = db.module_for_file(file_id);
59 ty.display_source_code(&db, module).unwrap()
60 } else {
61 ty.display(&db).to_string()
62 };
63 assert_eq!(expected, actual);
64 checked_one = true;
65 }
66 }
67 assert!(checked_one, "no `//^` annotations found");
68}
69
70fn type_at_range(db: &TestDB, pos: FileRange) -> Ty {
53 let file = db.parse(pos.file_id).ok().unwrap(); 71 let file = db.parse(pos.file_id).ok().unwrap();
54 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); 72 let expr = algo::find_node_at_range::<ast::Expr>(file.syntax(), pos.range).unwrap();
55 let fn_def = expr.syntax().ancestors().find_map(ast::FnDef::cast).unwrap(); 73 let fn_def = expr.syntax().ancestors().find_map(ast::FnDef::cast).unwrap();
56 let module = db.module_for_file(pos.file_id); 74 let module = db.module_for_file(pos.file_id);
57 let func = *module.child_by_source(db)[keys::FUNCTION] 75 let func = *module.child_by_source(db)[keys::FUNCTION]
@@ -61,17 +79,11 @@ fn type_at_pos_displayed(
61 let (_body, source_map) = db.body_with_source_map(func.into()); 79 let (_body, source_map) = db.body_with_source_map(func.into());
62 if let Some(expr_id) = source_map.node_expr(InFile::new(pos.file_id.into(), &expr)) { 80 if let Some(expr_id) = source_map.node_expr(InFile::new(pos.file_id.into(), &expr)) {
63 let infer = db.infer(func.into()); 81 let infer = db.infer(func.into());
64 let ty = &infer[expr_id]; 82 return infer[expr_id].clone();
65 return display_fn(ty, module);
66 } 83 }
67 panic!("Can't find expression") 84 panic!("Can't find expression")
68} 85}
69 86
70fn type_at(ra_fixture: &str) -> String {
71 let (db, file_pos) = TestDB::with_position(ra_fixture);
72 type_at_pos(&db, file_pos)
73}
74
75fn infer(ra_fixture: &str) -> String { 87fn infer(ra_fixture: &str) -> String {
76 infer_with_mismatches(ra_fixture, false) 88 infer_with_mismatches(ra_fixture, false)
77} 89}
diff --git a/crates/ra_hir_ty/src/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs
index 5a1c6ccc3..136d28a91 100644
--- a/crates/ra_hir_ty/src/tests/coercion.rs
+++ b/crates/ra_hir_ty/src/tests/coercion.rs
@@ -1,7 +1,8 @@
1use super::infer_with_mismatches;
2use insta::assert_snapshot; 1use insta::assert_snapshot;
3use test_utils::mark; 2use test_utils::mark;
4 3
4use super::infer_with_mismatches;
5
5// Infer with some common definitions and impls. 6// Infer with some common definitions and impls.
6fn infer(source: &str) -> String { 7fn infer(source: &str) -> String {
7 let defs = r#" 8 let defs = r#"
diff --git a/crates/ra_hir_ty/src/tests/display_source_code.rs b/crates/ra_hir_ty/src/tests/display_source_code.rs
index 5dfa0a014..b502135d8 100644
--- a/crates/ra_hir_ty/src/tests/display_source_code.rs
+++ b/crates/ra_hir_ty/src/tests/display_source_code.rs
@@ -1,50 +1,41 @@
1use super::displayed_source_at_pos; 1use super::check_types_source_code;
2use crate::test_db::TestDB;
3use ra_db::fixture::WithFixture;
4 2
5#[test] 3#[test]
6fn qualify_path_to_submodule() { 4fn qualify_path_to_submodule() {
7 let (db, pos) = TestDB::with_position( 5 check_types_source_code(
8 r#" 6 r#"
9//- /main.rs
10
11mod foo { 7mod foo {
12 pub struct Foo; 8 pub struct Foo;
13} 9}
14 10
15fn bar() { 11fn bar() {
16 let foo: foo::Foo = foo::Foo; 12 let foo: foo::Foo = foo::Foo;
17 foo<|> 13 foo
18} 14} //^ foo::Foo
19 15
20"#, 16"#,
21 ); 17 );
22 assert_eq!("foo::Foo", displayed_source_at_pos(&db, pos));
23} 18}
24 19
25#[test] 20#[test]
26fn omit_default_type_parameters() { 21fn omit_default_type_parameters() {
27 let (db, pos) = TestDB::with_position( 22 check_types_source_code(
28 r" 23 r#"
29 //- /main.rs 24struct Foo<T = u8> { t: T }
30 struct Foo<T = u8> { t: T } 25fn main() {
31 fn main() { 26 let foo = Foo { t: 5u8 };
32 let foo = Foo { t: 5u8 }; 27 foo;
33 foo<|>; 28} //^ Foo
34 } 29"#,
35 ",
36 ); 30 );
37 assert_eq!("Foo", displayed_source_at_pos(&db, pos));
38 31
39 let (db, pos) = TestDB::with_position( 32 check_types_source_code(
40 r" 33 r#"
41 //- /main.rs 34struct Foo<K, T = u8> { k: K, t: T }
42 struct Foo<K, T = u8> { k: K, t: T } 35fn main() {
43 fn main() { 36 let foo = Foo { k: 400, t: 5u8 };
44 let foo = Foo { k: 400, t: 5u8 }; 37 foo;
45 foo<|>; 38} //^ Foo<i32>
46 } 39"#,
47 ",
48 ); 40 );
49 assert_eq!("Foo<i32>", displayed_source_at_pos(&db, pos));
50} 41}
diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs
index be2b48dcc..45c4e309e 100644
--- a/crates/ra_hir_ty/src/tests/macros.rs
+++ b/crates/ra_hir_ty/src/tests/macros.rs
@@ -1,16 +1,13 @@
1use std::fs; 1use std::fs;
2 2
3use insta::assert_snapshot; 3use insta::assert_snapshot;
4use ra_db::fixture::WithFixture;
5use test_utils::project_dir; 4use test_utils::project_dir;
6 5
7use crate::test_db::TestDB; 6use super::{check_types, infer};
8
9use super::{infer, type_at, type_at_pos};
10 7
11#[test] 8#[test]
12fn cfg_impl_def() { 9fn cfg_impl_def() {
13 let (db, pos) = TestDB::with_position( 10 check_types(
14 r#" 11 r#"
15//- /main.rs crate:main deps:foo cfg:test 12//- /main.rs crate:main deps:foo cfg:test
16use foo::S as T; 13use foo::S as T;
@@ -28,8 +25,8 @@ impl S {
28 25
29fn test() { 26fn test() {
30 let t = (S.foo1(), S.foo2(), T.foo3(), T.foo4()); 27 let t = (S.foo1(), S.foo2(), T.foo3(), T.foo4());
31 t<|>; 28 t;
32} 29} //^ (i32, {unknown}, i32, {unknown})
33 30
34//- /foo.rs crate:foo 31//- /foo.rs crate:foo
35struct S; 32struct S;
@@ -45,7 +42,6 @@ impl S {
45} 42}
46"#, 43"#,
47 ); 44 );
48 assert_eq!("(i32, {unknown}, i32, {unknown})", type_at_pos(&db, pos));
49} 45}
50 46
51#[test] 47#[test]
@@ -253,26 +249,24 @@ fn foo() {
253 249
254#[test] 250#[test]
255fn processes_impls_generated_by_macros() { 251fn processes_impls_generated_by_macros() {
256 let t = type_at( 252 check_types(
257 r#" 253 r#"
258//- /main.rs
259macro_rules! m { 254macro_rules! m {
260 ($ident:ident) => (impl Trait for $ident {}) 255 ($ident:ident) => (impl Trait for $ident {})
261} 256}
262trait Trait { fn foo(self) -> u128 {} } 257trait Trait { fn foo(self) -> u128 {} }
263struct S; 258struct S;
264m!(S); 259m!(S);
265fn test() { S.foo()<|>; } 260fn test() { S.foo(); }
261 //^ u128
266"#, 262"#,
267 ); 263 );
268 assert_eq!(t, "u128");
269} 264}
270 265
271#[test] 266#[test]
272fn infer_assoc_items_generated_by_macros() { 267fn infer_assoc_items_generated_by_macros() {
273 let t = type_at( 268 check_types(
274 r#" 269 r#"
275//- /main.rs
276macro_rules! m { 270macro_rules! m {
277 () => (fn foo(&self) -> u128 {0}) 271 () => (fn foo(&self) -> u128 {0})
278} 272}
@@ -281,17 +275,16 @@ impl S {
281 m!(); 275 m!();
282} 276}
283 277
284fn test() { S.foo()<|>; } 278fn test() { S.foo(); }
279 //^ u128
285"#, 280"#,
286 ); 281 );
287 assert_eq!(t, "u128");
288} 282}
289 283
290#[test] 284#[test]
291fn infer_assoc_items_generated_by_macros_chain() { 285fn infer_assoc_items_generated_by_macros_chain() {
292 let t = type_at( 286 check_types(
293 r#" 287 r#"
294//- /main.rs
295macro_rules! m_inner { 288macro_rules! m_inner {
296 () => {fn foo(&self) -> u128 {0}} 289 () => {fn foo(&self) -> u128 {0}}
297} 290}
@@ -304,21 +297,21 @@ impl S {
304 m!(); 297 m!();
305} 298}
306 299
307fn test() { S.foo()<|>; } 300fn test() { S.foo(); }
301 //^ u128
308"#, 302"#,
309 ); 303 );
310 assert_eq!(t, "u128");
311} 304}
312 305
313#[test] 306#[test]
314fn infer_macro_with_dollar_crate_is_correct_in_expr() { 307fn infer_macro_with_dollar_crate_is_correct_in_expr() {
315 let (db, pos) = TestDB::with_position( 308 check_types(
316 r#" 309 r#"
317//- /main.rs crate:main deps:foo 310//- /main.rs crate:main deps:foo
318fn test() { 311fn test() {
319 let x = (foo::foo!(1), foo::foo!(2)); 312 let x = (foo::foo!(1), foo::foo!(2));
320 x<|>; 313 x;
321} 314} //^ (i32, usize)
322 315
323//- /lib.rs crate:foo 316//- /lib.rs crate:foo
324#[macro_export] 317#[macro_export]
@@ -335,12 +328,11 @@ macro_rules! bar {
335pub fn baz() -> usize { 31usize } 328pub fn baz() -> usize { 31usize }
336"#, 329"#,
337 ); 330 );
338 assert_eq!("(i32, usize)", type_at_pos(&db, pos));
339} 331}
340 332
341#[test] 333#[test]
342fn infer_macro_with_dollar_crate_is_correct_in_trait_associate_type() { 334fn infer_macro_with_dollar_crate_is_correct_in_trait_associate_type() {
343 let (db, pos) = TestDB::with_position( 335 check_types(
344 r#" 336 r#"
345//- /main.rs crate:main deps:foo 337//- /main.rs crate:main deps:foo
346use foo::Trait; 338use foo::Trait;
@@ -348,7 +340,8 @@ use foo::Trait;
348fn test() { 340fn test() {
349 let msg = foo::Message(foo::MessageRef); 341 let msg = foo::Message(foo::MessageRef);
350 let r = msg.deref(); 342 let r = msg.deref();
351 r<|>; 343 r;
344 //^ &MessageRef
352} 345}
353 346
354//- /lib.rs crate:foo 347//- /lib.rs crate:foo
@@ -375,7 +368,6 @@ macro_rules! expand {
375expand!(); 368expand!();
376"#, 369"#,
377 ); 370 );
378 assert_eq!("&MessageRef", type_at_pos(&db, pos));
379} 371}
380 372
381#[test] 373#[test]
@@ -429,13 +421,13 @@ fn main() {
429 421
430#[test] 422#[test]
431fn infer_local_inner_macros() { 423fn infer_local_inner_macros() {
432 let (db, pos) = TestDB::with_position( 424 check_types(
433 r#" 425 r#"
434//- /main.rs crate:main deps:foo 426//- /main.rs crate:main deps:foo
435fn test() { 427fn test() {
436 let x = foo::foo!(1); 428 let x = foo::foo!(1);
437 x<|>; 429 x;
438} 430} //^ i32
439 431
440//- /lib.rs crate:foo 432//- /lib.rs crate:foo
441#[macro_export(local_inner_macros)] 433#[macro_export(local_inner_macros)]
@@ -450,7 +442,6 @@ macro_rules! bar {
450 442
451"#, 443"#,
452 ); 444 );
453 assert_eq!("i32", type_at_pos(&db, pos));
454} 445}
455 446
456#[test] 447#[test]
@@ -531,7 +522,7 @@ fn main() {
531 522
532#[test] 523#[test]
533fn infer_builtin_macros_include() { 524fn infer_builtin_macros_include() {
534 let (db, pos) = TestDB::with_position( 525 check_types(
535 r#" 526 r#"
536//- /main.rs 527//- /main.rs
537#[rustc_builtin_macro] 528#[rustc_builtin_macro]
@@ -540,14 +531,13 @@ macro_rules! include {() => {}}
540include!("foo.rs"); 531include!("foo.rs");
541 532
542fn main() { 533fn main() {
543 bar()<|>; 534 bar();
544} 535} //^ u32
545 536
546//- /foo.rs 537//- /foo.rs
547fn bar() -> u32 {0} 538fn bar() -> u32 {0}
548"#, 539"#,
549 ); 540 );
550 assert_eq!("u32", type_at_pos(&db, pos));
551} 541}
552 542
553#[test] 543#[test]
@@ -565,18 +555,17 @@ macro_rules! include {() => {}}
565include!("foo.rs"); 555include!("foo.rs");
566 556
567fn main() { 557fn main() {
568 RegisterBlock { }<|>; 558 RegisterBlock { };
559 //^ RegisterBlock
569} 560}
570 "#; 561 "#;
571 let fixture = format!("{}\n//- /foo.rs\n{}", fixture, big_file); 562 let fixture = format!("{}\n//- /foo.rs\n{}", fixture, big_file);
572 563 check_types(&fixture);
573 let (db, pos) = TestDB::with_position(&fixture);
574 assert_eq!("RegisterBlock", type_at_pos(&db, pos));
575} 564}
576 565
577#[test] 566#[test]
578fn infer_builtin_macros_include_concat() { 567fn infer_builtin_macros_include_concat() {
579 let (db, pos) = TestDB::with_position( 568 check_types(
580 r#" 569 r#"
581//- /main.rs 570//- /main.rs
582#[rustc_builtin_macro] 571#[rustc_builtin_macro]
@@ -588,19 +577,18 @@ macro_rules! concat {() => {}}
588include!(concat!("f", "oo.rs")); 577include!(concat!("f", "oo.rs"));
589 578
590fn main() { 579fn main() {
591 bar()<|>; 580 bar();
592} 581} //^ u32
593 582
594//- /foo.rs 583//- /foo.rs
595fn bar() -> u32 {0} 584fn bar() -> u32 {0}
596"#, 585"#,
597 ); 586 );
598 assert_eq!("u32", type_at_pos(&db, pos));
599} 587}
600 588
601#[test] 589#[test]
602fn infer_builtin_macros_include_concat_with_bad_env_should_failed() { 590fn infer_builtin_macros_include_concat_with_bad_env_should_failed() {
603 let (db, pos) = TestDB::with_position( 591 check_types(
604 r#" 592 r#"
605//- /main.rs 593//- /main.rs
606#[rustc_builtin_macro] 594#[rustc_builtin_macro]
@@ -615,32 +603,29 @@ macro_rules! env {() => {}}
615include!(concat!(env!("OUT_DIR"), "/foo.rs")); 603include!(concat!(env!("OUT_DIR"), "/foo.rs"));
616 604
617fn main() { 605fn main() {
618 bar()<|>; 606 bar();
619} 607} //^ {unknown}
620 608
621//- /foo.rs 609//- /foo.rs
622fn bar() -> u32 {0} 610fn bar() -> u32 {0}
623"#, 611"#,
624 ); 612 );
625 assert_eq!("{unknown}", type_at_pos(&db, pos));
626} 613}
627 614
628#[test] 615#[test]
629fn infer_builtin_macros_include_itself_should_failed() { 616fn infer_builtin_macros_include_itself_should_failed() {
630 let (db, pos) = TestDB::with_position( 617 check_types(
631 r#" 618 r#"
632//- /main.rs
633#[rustc_builtin_macro] 619#[rustc_builtin_macro]
634macro_rules! include {() => {}} 620macro_rules! include {() => {}}
635 621
636include!("main.rs"); 622include!("main.rs");
637 623
638fn main() { 624fn main() {
639 0<|> 625 0
640} 626} //^ i32
641"#, 627"#,
642 ); 628 );
643 assert_eq!("i32", type_at_pos(&db, pos));
644} 629}
645 630
646#[test] 631#[test]
@@ -686,14 +671,14 @@ fn main() {
686 671
687#[test] 672#[test]
688fn infer_derive_clone_simple() { 673fn infer_derive_clone_simple() {
689 let (db, pos) = TestDB::with_position( 674 check_types(
690 r#" 675 r#"
691//- /main.rs crate:main deps:core 676//- /main.rs crate:main deps:core
692#[derive(Clone)] 677#[derive(Clone)]
693struct S; 678struct S;
694fn test() { 679fn test() {
695 S.clone()<|>; 680 S.clone();
696} 681} //^ S
697 682
698//- /lib.rs crate:core 683//- /lib.rs crate:core
699#[prelude_import] 684#[prelude_import]
@@ -705,12 +690,11 @@ mod clone {
705} 690}
706"#, 691"#,
707 ); 692 );
708 assert_eq!("S", type_at_pos(&db, pos));
709} 693}
710 694
711#[test] 695#[test]
712fn infer_derive_clone_in_core() { 696fn infer_derive_clone_in_core() {
713 let (db, pos) = TestDB::with_position( 697 check_types(
714 r#" 698 r#"
715//- /lib.rs crate:core 699//- /lib.rs crate:core
716#[prelude_import] 700#[prelude_import]
@@ -726,16 +710,15 @@ pub struct S;
726//- /main.rs crate:main deps:core 710//- /main.rs crate:main deps:core
727use core::S; 711use core::S;
728fn test() { 712fn test() {
729 S.clone()<|>; 713 S.clone();
730} 714} //^ S
731"#, 715"#,
732 ); 716 );
733 assert_eq!("S", type_at_pos(&db, pos));
734} 717}
735 718
736#[test] 719#[test]
737fn infer_derive_clone_with_params() { 720fn infer_derive_clone_with_params() {
738 let (db, pos) = TestDB::with_position( 721 check_types(
739 r#" 722 r#"
740//- /main.rs crate:main deps:core 723//- /main.rs crate:main deps:core
741#[derive(Clone)] 724#[derive(Clone)]
@@ -744,7 +727,8 @@ struct S;
744struct Wrapper<T>(T); 727struct Wrapper<T>(T);
745struct NonClone; 728struct NonClone;
746fn test() { 729fn test() {
747 (Wrapper(S).clone(), Wrapper(NonClone).clone())<|>; 730 (Wrapper(S).clone(), Wrapper(NonClone).clone());
731 //^ (Wrapper<S>, {unknown})
748} 732}
749 733
750//- /lib.rs crate:core 734//- /lib.rs crate:core
@@ -757,13 +741,12 @@ mod clone {
757} 741}
758"#, 742"#,
759 ); 743 );
760 assert_eq!("(Wrapper<S>, {unknown})", type_at_pos(&db, pos));
761} 744}
762 745
763#[test] 746#[test]
764fn infer_custom_derive_simple() { 747fn infer_custom_derive_simple() {
765 // FIXME: this test current now do nothing 748 // FIXME: this test current now do nothing
766 let (db, pos) = TestDB::with_position( 749 check_types(
767 r#" 750 r#"
768//- /main.rs crate:main 751//- /main.rs crate:main
769use foo::Foo; 752use foo::Foo;
@@ -772,11 +755,10 @@ use foo::Foo;
772struct S{} 755struct S{}
773 756
774fn test() { 757fn test() {
775 S{}<|>; 758 S{};
776} 759} //^ S
777"#, 760"#,
778 ); 761 );
779 assert_eq!("S", type_at_pos(&db, pos));
780} 762}
781 763
782#[test] 764#[test]
diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs
index 20329bae4..9c8f22314 100644
--- a/crates/ra_hir_ty/src/tests/method_resolution.rs
+++ b/crates/ra_hir_ty/src/tests/method_resolution.rs
@@ -1,7 +1,6 @@
1use super::{infer, type_at, type_at_pos};
2use crate::test_db::TestDB;
3use insta::assert_snapshot; 1use insta::assert_snapshot;
4use ra_db::fixture::WithFixture; 2
3use super::{check_types, infer};
5 4
6#[test] 5#[test]
7fn infer_slice_method() { 6fn infer_slice_method() {
@@ -246,13 +245,13 @@ fn test() {
246 245
247#[test] 246#[test]
248fn cross_crate_associated_method_call() { 247fn cross_crate_associated_method_call() {
249 let (db, pos) = TestDB::with_position( 248 check_types(
250 r#" 249 r#"
251//- /main.rs crate:main deps:other_crate 250//- /main.rs crate:main deps:other_crate
252fn test() { 251fn test() {
253 let x = other_crate::foo::S::thing(); 252 let x = other_crate::foo::S::thing();
254 x<|>; 253 x;
255} 254} //^ i128
256 255
257//- /lib.rs crate:other_crate 256//- /lib.rs crate:other_crate
258mod foo { 257mod foo {
@@ -263,7 +262,6 @@ mod foo {
263} 262}
264"#, 263"#,
265 ); 264 );
266 assert_eq!("i128", type_at_pos(&db, pos));
267} 265}
268 266
269#[test] 267#[test]
@@ -684,135 +682,127 @@ fn test() {
684 682
685#[test] 683#[test]
686fn method_resolution_unify_impl_self_type() { 684fn method_resolution_unify_impl_self_type() {
687 let t = type_at( 685 check_types(
688 r#" 686 r#"
689//- /main.rs
690struct S<T>; 687struct S<T>;
691impl S<u32> { fn foo(&self) -> u8 {} } 688impl S<u32> { fn foo(&self) -> u8 {} }
692impl S<i32> { fn foo(&self) -> i8 {} } 689impl S<i32> { fn foo(&self) -> i8 {} }
693fn test() { (S::<u32>.foo(), S::<i32>.foo())<|>; } 690fn test() { (S::<u32>.foo(), S::<i32>.foo()); }
691 //^ (u8, i8)
694"#, 692"#,
695 ); 693 );
696 assert_eq!(t, "(u8, i8)");
697} 694}
698 695
699#[test] 696#[test]
700fn method_resolution_trait_before_autoref() { 697fn method_resolution_trait_before_autoref() {
701 let t = type_at( 698 check_types(
702 r#" 699 r#"
703//- /main.rs
704trait Trait { fn foo(self) -> u128; } 700trait Trait { fn foo(self) -> u128; }
705struct S; 701struct S;
706impl S { fn foo(&self) -> i8 { 0 } } 702impl S { fn foo(&self) -> i8 { 0 } }
707impl Trait for S { fn foo(self) -> u128 { 0 } } 703impl Trait for S { fn foo(self) -> u128 { 0 } }
708fn test() { S.foo()<|>; } 704fn test() { S.foo(); }
705 //^ u128
709"#, 706"#,
710 ); 707 );
711 assert_eq!(t, "u128");
712} 708}
713 709
714#[test] 710#[test]
715fn method_resolution_by_value_before_autoref() { 711fn method_resolution_by_value_before_autoref() {
716 let t = type_at( 712 check_types(
717 r#" 713 r#"
718//- /main.rs
719trait Clone { fn clone(&self) -> Self; } 714trait Clone { fn clone(&self) -> Self; }
720struct S; 715struct S;
721impl Clone for S {} 716impl Clone for S {}
722impl Clone for &S {} 717impl Clone for &S {}
723fn test() { (S.clone(), (&S).clone(), (&&S).clone())<|>; } 718fn test() { (S.clone(), (&S).clone(), (&&S).clone()); }
719 //^ (S, S, &S)
724"#, 720"#,
725 ); 721 );
726 assert_eq!(t, "(S, S, &S)");
727} 722}
728 723
729#[test] 724#[test]
730fn method_resolution_trait_before_autoderef() { 725fn method_resolution_trait_before_autoderef() {
731 let t = type_at( 726 check_types(
732 r#" 727 r#"
733//- /main.rs
734trait Trait { fn foo(self) -> u128; } 728trait Trait { fn foo(self) -> u128; }
735struct S; 729struct S;
736impl S { fn foo(self) -> i8 { 0 } } 730impl S { fn foo(self) -> i8 { 0 } }
737impl Trait for &S { fn foo(self) -> u128 { 0 } } 731impl Trait for &S { fn foo(self) -> u128 { 0 } }
738fn test() { (&S).foo()<|>; } 732fn test() { (&S).foo(); }
733 //^ u128
739"#, 734"#,
740 ); 735 );
741 assert_eq!(t, "u128");
742} 736}
743 737
744#[test] 738#[test]
745fn method_resolution_impl_before_trait() { 739fn method_resolution_impl_before_trait() {
746 let t = type_at( 740 check_types(
747 r#" 741 r#"
748//- /main.rs
749trait Trait { fn foo(self) -> u128; } 742trait Trait { fn foo(self) -> u128; }
750struct S; 743struct S;
751impl S { fn foo(self) -> i8 { 0 } } 744impl S { fn foo(self) -> i8 { 0 } }
752impl Trait for S { fn foo(self) -> u128 { 0 } } 745impl Trait for S { fn foo(self) -> u128 { 0 } }
753fn test() { S.foo()<|>; } 746fn test() { S.foo(); }
747 //^ i8
754"#, 748"#,
755 ); 749 );
756 assert_eq!(t, "i8");
757} 750}
758 751
759#[test] 752#[test]
760fn method_resolution_impl_ref_before_trait() { 753fn method_resolution_impl_ref_before_trait() {
761 let t = type_at( 754 check_types(
762 r#" 755 r#"
763//- /main.rs
764trait Trait { fn foo(self) -> u128; } 756trait Trait { fn foo(self) -> u128; }
765struct S; 757struct S;
766impl S { fn foo(&self) -> i8 { 0 } } 758impl S { fn foo(&self) -> i8 { 0 } }
767impl Trait for &S { fn foo(self) -> u128 { 0 } } 759impl Trait for &S { fn foo(self) -> u128 { 0 } }
768fn test() { S.foo()<|>; } 760fn test() { S.foo(); }
761 //^ i8
769"#, 762"#,
770 ); 763 );
771 assert_eq!(t, "i8");
772} 764}
773 765
774#[test] 766#[test]
775fn method_resolution_trait_autoderef() { 767fn method_resolution_trait_autoderef() {
776 let t = type_at( 768 check_types(
777 r#" 769 r#"
778//- /main.rs
779trait Trait { fn foo(self) -> u128; } 770trait Trait { fn foo(self) -> u128; }
780struct S; 771struct S;
781impl Trait for S { fn foo(self) -> u128 { 0 } } 772impl Trait for S { fn foo(self) -> u128 { 0 } }
782fn test() { (&S).foo()<|>; } 773fn test() { (&S).foo(); }
774 //^ u128
783"#, 775"#,
784 ); 776 );
785 assert_eq!(t, "u128");
786} 777}
787 778
788#[test] 779#[test]
789fn method_resolution_unsize_array() { 780fn method_resolution_unsize_array() {
790 let t = type_at( 781 check_types(
791 r#" 782 r#"
792//- /main.rs
793#[lang = "slice"] 783#[lang = "slice"]
794impl<T> [T] { 784impl<T> [T] {
795 fn len(&self) -> usize { loop {} } 785 fn len(&self) -> usize { loop {} }
796} 786}
797fn test() { 787fn test() {
798 let a = [1, 2, 3]; 788 let a = [1, 2, 3];
799 a.len()<|>; 789 a.len();
800} 790} //^ usize
801"#, 791"#,
802 ); 792 );
803 assert_eq!(t, "usize");
804} 793}
805 794
806#[test] 795#[test]
807fn method_resolution_trait_from_prelude() { 796fn method_resolution_trait_from_prelude() {
808 let (db, pos) = TestDB::with_position( 797 check_types(
809 r#" 798 r#"
810//- /main.rs crate:main deps:other_crate 799//- /main.rs crate:main deps:other_crate
811struct S; 800struct S;
812impl Clone for S {} 801impl Clone for S {}
813 802
814fn test() { 803fn test() {
815 S.clone()<|>; 804 S.clone();
805 //^ S
816} 806}
817 807
818//- /lib.rs crate:other_crate 808//- /lib.rs crate:other_crate
@@ -825,115 +815,107 @@ mod foo {
825} 815}
826"#, 816"#,
827 ); 817 );
828 assert_eq!("S", type_at_pos(&db, pos));
829} 818}
830 819
831#[test] 820#[test]
832fn method_resolution_where_clause_for_unknown_trait() { 821fn method_resolution_where_clause_for_unknown_trait() {
833 // The blanket impl currently applies because we ignore the unresolved where clause 822 // The blanket impl currently applies because we ignore the unresolved where clause
834 let t = type_at( 823 check_types(
835 r#" 824 r#"
836//- /main.rs
837trait Trait { fn foo(self) -> u128; } 825trait Trait { fn foo(self) -> u128; }
838struct S; 826struct S;
839impl<T> Trait for T where T: UnknownTrait {} 827impl<T> Trait for T where T: UnknownTrait {}
840fn test() { (&S).foo()<|>; } 828fn test() { (&S).foo(); }
829 //^ u128
841"#, 830"#,
842 ); 831 );
843 assert_eq!(t, "u128");
844} 832}
845 833
846#[test] 834#[test]
847fn method_resolution_where_clause_not_met() { 835fn method_resolution_where_clause_not_met() {
848 // The blanket impl shouldn't apply because we can't prove S: Clone 836 // The blanket impl shouldn't apply because we can't prove S: Clone
849 let t = type_at( 837 // This is also to make sure that we don't resolve to the foo method just
838 // because that's the only method named foo we can find, which would make
839 // the below tests not work
840 check_types(
850 r#" 841 r#"
851//- /main.rs
852trait Clone {} 842trait Clone {}
853trait Trait { fn foo(self) -> u128; } 843trait Trait { fn foo(self) -> u128; }
854struct S; 844struct S;
855impl<T> Trait for T where T: Clone {} 845impl<T> Trait for T where T: Clone {}
856fn test() { (&S).foo()<|>; } 846fn test() { (&S).foo(); }
847 //^ {unknown}
857"#, 848"#,
858 ); 849 );
859 // This is also to make sure that we don't resolve to the foo method just
860 // because that's the only method named foo we can find, which would make
861 // the below tests not work
862 assert_eq!(t, "{unknown}");
863} 850}
864 851
865#[test] 852#[test]
866fn method_resolution_where_clause_inline_not_met() { 853fn method_resolution_where_clause_inline_not_met() {
867 // The blanket impl shouldn't apply because we can't prove S: Clone 854 // The blanket impl shouldn't apply because we can't prove S: Clone
868 let t = type_at( 855 check_types(
869 r#" 856 r#"
870//- /main.rs
871trait Clone {} 857trait Clone {}
872trait Trait { fn foo(self) -> u128; } 858trait Trait { fn foo(self) -> u128; }
873struct S; 859struct S;
874impl<T: Clone> Trait for T {} 860impl<T: Clone> Trait for T {}
875fn test() { (&S).foo()<|>; } 861fn test() { (&S).foo(); }
862 //^ {unknown}
876"#, 863"#,
877 ); 864 );
878 assert_eq!(t, "{unknown}");
879} 865}
880 866
881#[test] 867#[test]
882fn method_resolution_where_clause_1() { 868fn method_resolution_where_clause_1() {
883 let t = type_at( 869 check_types(
884 r#" 870 r#"
885//- /main.rs
886trait Clone {} 871trait Clone {}
887trait Trait { fn foo(self) -> u128; } 872trait Trait { fn foo(self) -> u128; }
888struct S; 873struct S;
889impl Clone for S {} 874impl Clone for S {}
890impl<T> Trait for T where T: Clone {} 875impl<T> Trait for T where T: Clone {}
891fn test() { S.foo()<|>; } 876fn test() { S.foo(); }
877 //^ u128
892"#, 878"#,
893 ); 879 );
894 assert_eq!(t, "u128");
895} 880}
896 881
897#[test] 882#[test]
898fn method_resolution_where_clause_2() { 883fn method_resolution_where_clause_2() {
899 let t = type_at( 884 check_types(
900 r#" 885 r#"
901//- /main.rs
902trait Into<T> { fn into(self) -> T; } 886trait Into<T> { fn into(self) -> T; }
903trait From<T> { fn from(other: T) -> Self; } 887trait From<T> { fn from(other: T) -> Self; }
904struct S1; 888struct S1;
905struct S2; 889struct S2;
906impl From<S2> for S1 {} 890impl From<S2> for S1 {}
907impl<T, U> Into<U> for T where U: From<T> {} 891impl<T, U> Into<U> for T where U: From<T> {}
908fn test() { S2.into()<|>; } 892fn test() { S2.into(); }
893 //^ {unknown}
909"#, 894"#,
910 ); 895 );
911 assert_eq!(t, "{unknown}");
912} 896}
913 897
914#[test] 898#[test]
915fn method_resolution_where_clause_inline() { 899fn method_resolution_where_clause_inline() {
916 let t = type_at( 900 check_types(
917 r#" 901 r#"
918//- /main.rs
919trait Into<T> { fn into(self) -> T; } 902trait Into<T> { fn into(self) -> T; }
920trait From<T> { fn from(other: T) -> Self; } 903trait From<T> { fn from(other: T) -> Self; }
921struct S1; 904struct S1;
922struct S2; 905struct S2;
923impl From<S2> for S1 {} 906impl From<S2> for S1 {}
924impl<T, U: From<T>> Into<U> for T {} 907impl<T, U: From<T>> Into<U> for T {}
925fn test() { S2.into()<|>; } 908fn test() { S2.into(); }
909 //^ {unknown}
926"#, 910"#,
927 ); 911 );
928 assert_eq!(t, "{unknown}");
929} 912}
930 913
931#[test] 914#[test]
932fn method_resolution_overloaded_method() { 915fn method_resolution_overloaded_method() {
933 test_utils::mark::check!(impl_self_type_match_without_receiver); 916 test_utils::mark::check!(impl_self_type_match_without_receiver);
934 let t = type_at( 917 check_types(
935 r#" 918 r#"
936//- /main.rs
937struct Wrapper<T>(T); 919struct Wrapper<T>(T);
938struct Foo<T>(T); 920struct Foo<T>(T);
939struct Bar<T>(T); 921struct Bar<T>(T);
@@ -953,30 +935,30 @@ impl<T> Wrapper<Bar<T>> {
953fn main() { 935fn main() {
954 let a = Wrapper::<Foo<f32>>::new(1.0); 936 let a = Wrapper::<Foo<f32>>::new(1.0);
955 let b = Wrapper::<Bar<f32>>::new(1.0); 937 let b = Wrapper::<Bar<f32>>::new(1.0);
956 (a, b)<|>; 938 (a, b);
939 //^ (Wrapper<Foo<f32>>, Wrapper<Bar<f32>>)
957} 940}
958"#, 941"#,
959 ); 942 );
960 assert_eq!(t, "(Wrapper<Foo<f32>>, Wrapper<Bar<f32>>)")
961} 943}
962 944
963#[test] 945#[test]
964fn method_resolution_encountering_fn_type() { 946fn method_resolution_encountering_fn_type() {
965 type_at( 947 check_types(
966 r#" 948 r#"
967//- /main.rs 949//- /main.rs
968fn foo() {} 950fn foo() {}
969trait FnOnce { fn call(self); } 951trait FnOnce { fn call(self); }
970fn test() { foo.call()<|>; } 952fn test() { foo.call(); }
953 //^ {unknown}
971"#, 954"#,
972 ); 955 );
973} 956}
974 957
975#[test] 958#[test]
976fn method_resolution_non_parameter_type() { 959fn method_resolution_non_parameter_type() {
977 let t = type_at( 960 check_types(
978 r#" 961 r#"
979//- /main.rs
980mod a { 962mod a {
981 pub trait Foo { 963 pub trait Foo {
982 fn foo(&self); 964 fn foo(&self);
@@ -988,18 +970,16 @@ fn foo<T>(t: Wrapper<T>)
988where 970where
989 Wrapper<T>: a::Foo, 971 Wrapper<T>: a::Foo,
990{ 972{
991 t.foo()<|>; 973 t.foo();
992} 974} //^ {unknown}
993"#, 975"#,
994 ); 976 );
995 assert_eq!(t, "{unknown}");
996} 977}
997 978
998#[test] 979#[test]
999fn method_resolution_3373() { 980fn method_resolution_3373() {
1000 let t = type_at( 981 check_types(
1001 r#" 982 r#"
1002//- /main.rs
1003struct A<T>(T); 983struct A<T>(T);
1004 984
1005impl A<i32> { 985impl A<i32> {
@@ -1007,19 +987,17 @@ impl A<i32> {
1007} 987}
1008 988
1009fn main() { 989fn main() {
1010 A::from(3)<|>; 990 A::from(3);
1011} 991} //^ A<i32>
1012"#, 992"#,
1013 ); 993 );
1014 assert_eq!(t, "A<i32>");
1015} 994}
1016 995
1017#[test] 996#[test]
1018fn method_resolution_slow() { 997fn method_resolution_slow() {
1019 // this can get quite slow if we set the solver size limit too high 998 // this can get quite slow if we set the solver size limit too high
1020 let t = type_at( 999 check_types(
1021 r#" 1000 r#"
1022//- /main.rs
1023trait SendX {} 1001trait SendX {}
1024 1002
1025struct S1; impl SendX for S1 {} 1003struct S1; impl SendX for S1 {}
@@ -1037,10 +1015,10 @@ trait FnX {}
1037 1015
1038impl<B, C> Trait for S<B, C> where C: FnX, B: SendX {} 1016impl<B, C> Trait for S<B, C> where C: FnX, B: SendX {}
1039 1017
1040fn test() { (S {}).method()<|>; } 1018fn test() { (S {}).method(); }
1019 //^ ()
1041"#, 1020"#,
1042 ); 1021 );
1043 assert_eq!(t, "()");
1044} 1022}
1045 1023
1046#[test] 1024#[test]
diff --git a/crates/ra_hir_ty/src/tests/never_type.rs b/crates/ra_hir_ty/src/tests/never_type.rs
index ab9a990f5..64d421d40 100644
--- a/crates/ra_hir_ty/src/tests/never_type.rs
+++ b/crates/ra_hir_ty/src/tests/never_type.rs
@@ -1,99 +1,91 @@
1use insta::assert_snapshot; 1use insta::assert_snapshot;
2 2
3use super::{infer_with_mismatches, type_at}; 3use super::{check_types, infer_with_mismatches};
4 4
5#[test] 5#[test]
6fn infer_never1() { 6fn infer_never1() {
7 let t = type_at( 7 check_types(
8 r#" 8 r#"
9//- /main.rs
10fn test() { 9fn test() {
11 let t = return; 10 let t = return;
12 t<|>; 11 t;
13} 12} //^ !
14"#, 13"#,
15 ); 14 );
16 assert_eq!(t, "!");
17} 15}
18 16
19#[test] 17#[test]
20fn infer_never2() { 18fn infer_never2() {
21 let t = type_at( 19 check_types(
22 r#" 20 r#"
23//- /main.rs
24fn gen<T>() -> T { loop {} } 21fn gen<T>() -> T { loop {} }
25 22
26fn test() { 23fn test() {
27 let a = gen(); 24 let a = gen();
28 if false { a } else { loop {} }; 25 if false { a } else { loop {} };
29 a<|>; 26 a;
30} 27} //^ !
31"#, 28"#,
32 ); 29 );
33 assert_eq!(t, "!");
34} 30}
35 31
36#[test] 32#[test]
37fn infer_never3() { 33fn infer_never3() {
38 let t = type_at( 34 check_types(
39 r#" 35 r#"
40//- /main.rs
41fn gen<T>() -> T { loop {} } 36fn gen<T>() -> T { loop {} }
42 37
43fn test() { 38fn test() {
44 let a = gen(); 39 let a = gen();
45 if false { loop {} } else { a }; 40 if false { loop {} } else { a };
46 a<|>; 41 a;
42 //^ !
47} 43}
48"#, 44"#,
49 ); 45 );
50 assert_eq!(t, "!");
51} 46}
52 47
53#[test] 48#[test]
54fn never_type_in_generic_args() { 49fn never_type_in_generic_args() {
55 let t = type_at( 50 check_types(
56 r#" 51 r#"
57//- /main.rs
58enum Option<T> { None, Some(T) } 52enum Option<T> { None, Some(T) }
59 53
60fn test() { 54fn test() {
61 let a = if true { Option::None } else { Option::Some(return) }; 55 let a = if true { Option::None } else { Option::Some(return) };
62 a<|>; 56 a;
63} 57} //^ Option<!>
64"#, 58"#,
65 ); 59 );
66 assert_eq!(t, "Option<!>");
67} 60}
68 61
69#[test] 62#[test]
70fn never_type_can_be_reinferred1() { 63fn never_type_can_be_reinferred1() {
71 let t = type_at( 64 check_types(
72 r#" 65 r#"
73//- /main.rs
74fn gen<T>() -> T { loop {} } 66fn gen<T>() -> T { loop {} }
75 67
76fn test() { 68fn test() {
77 let a = gen(); 69 let a = gen();
78 if false { loop {} } else { a }; 70 if false { loop {} } else { a };
79 a<|>; 71 a;
72 //^ ()
80 if false { a }; 73 if false { a };
81} 74}
82"#, 75"#,
83 ); 76 );
84 assert_eq!(t, "()");
85} 77}
86 78
87#[test] 79#[test]
88fn never_type_can_be_reinferred2() { 80fn never_type_can_be_reinferred2() {
89 let t = type_at( 81 check_types(
90 r#" 82 r#"
91//- /main.rs
92enum Option<T> { None, Some(T) } 83enum Option<T> { None, Some(T) }
93 84
94fn test() { 85fn test() {
95 let a = if true { Option::None } else { Option::Some(return) }; 86 let a = if true { Option::None } else { Option::Some(return) };
96 a<|>; 87 a;
88 //^ Option<i32>
97 match 42 { 89 match 42 {
98 42 => a, 90 42 => a,
99 _ => Option::Some(42), 91 _ => Option::Some(42),
@@ -101,19 +93,18 @@ fn test() {
101} 93}
102"#, 94"#,
103 ); 95 );
104 assert_eq!(t, "Option<i32>");
105} 96}
106 97
107#[test] 98#[test]
108fn never_type_can_be_reinferred3() { 99fn never_type_can_be_reinferred3() {
109 let t = type_at( 100 check_types(
110 r#" 101 r#"
111//- /main.rs
112enum Option<T> { None, Some(T) } 102enum Option<T> { None, Some(T) }
113 103
114fn test() { 104fn test() {
115 let a = if true { Option::None } else { Option::Some(return) }; 105 let a = if true { Option::None } else { Option::Some(return) };
116 a<|>; 106 a;
107 //^ Option<&str>
117 match 42 { 108 match 42 {
118 42 => a, 109 42 => a,
119 _ => Option::Some("str"), 110 _ => Option::Some("str"),
@@ -121,82 +112,72 @@ fn test() {
121} 112}
122"#, 113"#,
123 ); 114 );
124 assert_eq!(t, "Option<&str>");
125} 115}
126 116
127#[test] 117#[test]
128fn match_no_arm() { 118fn match_no_arm() {
129 let t = type_at( 119 check_types(
130 r#" 120 r#"
131//- /main.rs
132enum Void {} 121enum Void {}
133 122
134fn test(a: Void) { 123fn test(a: Void) {
135 let t = match a {}; 124 let t = match a {};
136 t<|>; 125 t;
137} 126} //^ !
138"#, 127"#,
139 ); 128 );
140 assert_eq!(t, "!");
141} 129}
142 130
143#[test] 131#[test]
144fn match_unknown_arm() { 132fn match_unknown_arm() {
145 let t = type_at( 133 check_types(
146 r#" 134 r#"
147//- /main.rs
148fn test(a: Option) { 135fn test(a: Option) {
149 let t = match 0 { 136 let t = match 0 {
150 _ => unknown, 137 _ => unknown,
151 }; 138 };
152 t<|>; 139 t;
153} 140} //^ {unknown}
154"#, 141"#,
155 ); 142 );
156 assert_eq!(t, "{unknown}");
157} 143}
158 144
159#[test] 145#[test]
160fn if_never() { 146fn if_never() {
161 let t = type_at( 147 check_types(
162 r#" 148 r#"
163//- /main.rs
164fn test() { 149fn test() {
165 let i = if true { 150 let i = if true {
166 loop {} 151 loop {}
167 } else { 152 } else {
168 3.0 153 3.0
169 }; 154 };
170 i<|>; 155 i;
171} 156} //^ f64
172"#, 157"#,
173 ); 158 );
174 assert_eq!(t, "f64");
175} 159}
176 160
177#[test] 161#[test]
178fn if_else_never() { 162fn if_else_never() {
179 let t = type_at( 163 check_types(
180 r#" 164 r#"
181//- /main.rs
182fn test(input: bool) { 165fn test(input: bool) {
183 let i = if input { 166 let i = if input {
184 2.0 167 2.0
185 } else { 168 } else {
186 return 169 return
187 }; 170 };
188 i<|>; 171 i;
189} 172} //^ f64
190"#, 173"#,
191 ); 174 );
192 assert_eq!(t, "f64");
193} 175}
194 176
195#[test] 177#[test]
196fn match_first_arm_never() { 178fn match_first_arm_never() {
197 let t = type_at( 179 check_types(
198 r#" 180 r#"
199//- /main.rs
200fn test(a: i32) { 181fn test(a: i32) {
201 let i = match a { 182 let i = match a {
202 1 => return, 183 1 => return,
@@ -204,18 +185,16 @@ fn test(a: i32) {
204 3 => loop {}, 185 3 => loop {},
205 _ => 3.0, 186 _ => 3.0,
206 }; 187 };
207 i<|>; 188 i;
208} 189} //^ f64
209"#, 190"#,
210 ); 191 );
211 assert_eq!(t, "f64");
212} 192}
213 193
214#[test] 194#[test]
215fn match_second_arm_never() { 195fn match_second_arm_never() {
216 let t = type_at( 196 check_types(
217 r#" 197 r#"
218//- /main.rs
219fn test(a: i32) { 198fn test(a: i32) {
220 let i = match a { 199 let i = match a {
221 1 => 3.0, 200 1 => 3.0,
@@ -223,45 +202,40 @@ fn test(a: i32) {
223 3 => 3.0, 202 3 => 3.0,
224 _ => return, 203 _ => return,
225 }; 204 };
226 i<|>; 205 i;
227} 206} //^ f64
228"#, 207"#,
229 ); 208 );
230 assert_eq!(t, "f64");
231} 209}
232 210
233#[test] 211#[test]
234fn match_all_arms_never() { 212fn match_all_arms_never() {
235 let t = type_at( 213 check_types(
236 r#" 214 r#"
237//- /main.rs
238fn test(a: i32) { 215fn test(a: i32) {
239 let i = match a { 216 let i = match a {
240 2 => return, 217 2 => return,
241 _ => loop {}, 218 _ => loop {},
242 }; 219 };
243 i<|>; 220 i;
244} 221} //^ !
245"#, 222"#,
246 ); 223 );
247 assert_eq!(t, "!");
248} 224}
249 225
250#[test] 226#[test]
251fn match_no_never_arms() { 227fn match_no_never_arms() {
252 let t = type_at( 228 check_types(
253 r#" 229 r#"
254//- /main.rs
255fn test(a: i32) { 230fn test(a: i32) {
256 let i = match a { 231 let i = match a {
257 2 => 2.0, 232 2 => 2.0,
258 _ => 3.0, 233 _ => 3.0,
259 }; 234 };
260 i<|>; 235 i;
261} 236} //^ f64
262"#, 237"#,
263 ); 238 );
264 assert_eq!(t, "f64");
265} 239}
266 240
267#[test] 241#[test]
diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs
index aa37326df..d806e0ffb 100644
--- a/crates/ra_hir_ty/src/tests/regression.rs
+++ b/crates/ra_hir_ty/src/tests/regression.rs
@@ -1,10 +1,7 @@
1use insta::assert_snapshot; 1use insta::assert_snapshot;
2use ra_db::fixture::WithFixture;
3use test_utils::mark; 2use test_utils::mark;
4 3
5use crate::test_db::TestDB; 4use super::{check_types, infer};
6
7use super::infer;
8 5
9#[test] 6#[test]
10fn bug_484() { 7fn bug_484() {
@@ -404,13 +401,13 @@ fn test() {
404 401
405#[test] 402#[test]
406fn issue_2683_chars_impl() { 403fn issue_2683_chars_impl() {
407 let (db, pos) = TestDB::with_position( 404 check_types(
408 r#" 405 r#"
409//- /main.rs crate:main deps:std 406//- /main.rs crate:main deps:std
410fn test() { 407fn test() {
411 let chars: std::str::Chars<'_>; 408 let chars: std::str::Chars<'_>;
412 (chars.next(), chars.nth(1))<|>; 409 (chars.next(), chars.nth(1));
413} 410} //^ (Option<char>, Option<char>)
414 411
415//- /std.rs crate:std 412//- /std.rs crate:std
416#[prelude_import] 413#[prelude_import]
@@ -449,15 +446,12 @@ pub mod str {
449} 446}
450"#, 447"#,
451 ); 448 );
452
453 assert_eq!("(Option<char>, Option<char>)", super::type_at_pos(&db, pos));
454} 449}
455 450
456#[test] 451#[test]
457fn issue_3642_bad_macro_stackover() { 452fn issue_3642_bad_macro_stackover() {
458 let (db, pos) = TestDB::with_position( 453 check_types(
459 r#" 454 r#"
460//- /main.rs
461#[macro_export] 455#[macro_export]
462macro_rules! match_ast { 456macro_rules! match_ast {
463 (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) }; 457 (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) };
@@ -472,7 +466,8 @@ macro_rules! match_ast {
472} 466}
473 467
474fn main() { 468fn main() {
475 let anchor<|> = match_ast! { 469 let anchor = match_ast! {
470 //^ ()
476 match parent { 471 match parent {
477 as => {}, 472 as => {},
478 _ => return None 473 _ => return None
@@ -480,8 +475,6 @@ fn main() {
480 }; 475 };
481}"#, 476}"#,
482 ); 477 );
483
484 assert_eq!("()", super::type_at_pos(&db, pos));
485} 478}
486 479
487#[test] 480#[test]
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs
index cd919466f..de63f4cce 100644
--- a/crates/ra_hir_ty/src/tests/simple.rs
+++ b/crates/ra_hir_ty/src/tests/simple.rs
@@ -1,19 +1,17 @@
1use super::{infer, type_at, type_at_pos};
2use crate::test_db::TestDB;
3use insta::assert_snapshot; 1use insta::assert_snapshot;
4use ra_db::fixture::WithFixture; 2
3use super::{check_types, infer};
5 4
6#[test] 5#[test]
7fn infer_box() { 6fn infer_box() {
8 let (db, pos) = TestDB::with_position( 7 check_types(
9 r#" 8 r#"
10//- /main.rs crate:main deps:std 9//- /main.rs crate:main deps:std
11
12fn test() { 10fn test() {
13 let x = box 1; 11 let x = box 1;
14 let t = (x, box x, box &1, box [1]); 12 let t = (x, box x, box &1, box [1]);
15 t<|>; 13 t;
16} 14} //^ (Box<i32>, Box<Box<i32>>, Box<&i32>, Box<[i32; _]>)
17 15
18//- /std.rs crate:std 16//- /std.rs crate:std
19#[prelude_import] use prelude::*; 17#[prelude_import] use prelude::*;
@@ -25,29 +23,24 @@ mod boxed {
25 inner: *mut T, 23 inner: *mut T,
26 } 24 }
27} 25}
28
29"#, 26"#,
30 ); 27 );
31 assert_eq!("(Box<i32>, Box<Box<i32>>, Box<&i32>, Box<[i32; _]>)", type_at_pos(&db, pos));
32} 28}
33 29
34#[test] 30#[test]
35fn infer_adt_self() { 31fn infer_adt_self() {
36 let (db, pos) = TestDB::with_position( 32 check_types(
37 r#" 33 r#"
38//- /main.rs
39enum Nat { Succ(Self), Demo(Nat), Zero } 34enum Nat { Succ(Self), Demo(Nat), Zero }
40 35
41fn test() { 36fn test() {
42 let foo: Nat = Nat::Zero; 37 let foo: Nat = Nat::Zero;
43 if let Nat::Succ(x) = foo { 38 if let Nat::Succ(x) = foo {
44 x<|> 39 x
45 } 40 } //^ Nat
46} 41}
47
48"#, 42"#,
49 ); 43 );
50 assert_eq!("Nat", type_at_pos(&db, pos));
51} 44}
52 45
53#[test] 46#[test]
@@ -93,7 +86,7 @@ fn foo() {
93 86
94#[test] 87#[test]
95fn infer_ranges() { 88fn infer_ranges() {
96 let (db, pos) = TestDB::with_position( 89 check_types(
97 r#" 90 r#"
98//- /main.rs crate:main deps:core 91//- /main.rs crate:main deps:core
99fn test() { 92fn test() {
@@ -105,8 +98,8 @@ fn test() {
105 let f = 'a'..='z'; 98 let f = 'a'..='z';
106 99
107 let t = (a, b, c, d, e, f); 100 let t = (a, b, c, d, e, f);
108 t<|>; 101 t;
109} 102} //^ (RangeFull, RangeFrom<i32>, RangeTo<u32>, Range<usize>, RangeToInclusive<i32>, RangeInclusive<char>)
110 103
111//- /core.rs crate:core 104//- /core.rs crate:core
112#[prelude_import] use prelude::*; 105#[prelude_import] use prelude::*;
@@ -135,29 +128,22 @@ pub mod ops {
135} 128}
136"#, 129"#,
137 ); 130 );
138 assert_eq!(
139 "(RangeFull, RangeFrom<i32>, RangeTo<u32>, Range<usize>, RangeToInclusive<i32>, RangeInclusive<char>)",
140 type_at_pos(&db, pos),
141 );
142} 131}
143 132
144#[test] 133#[test]
145fn infer_while_let() { 134fn infer_while_let() {
146 let (db, pos) = TestDB::with_position( 135 check_types(
147 r#" 136 r#"
148//- /main.rs
149enum Option<T> { Some(T), None } 137enum Option<T> { Some(T), None }
150 138
151fn test() { 139fn test() {
152 let foo: Option<f32> = None; 140 let foo: Option<f32> = None;
153 while let Option::Some(x) = foo { 141 while let Option::Some(x) = foo {
154 <|>x 142 x
155 } 143 } //^ f32
156} 144}
157
158"#, 145"#,
159 ); 146 );
160 assert_eq!("f32", type_at_pos(&db, pos));
161} 147}
162 148
163#[test] 149#[test]
@@ -1687,9 +1673,8 @@ fn test() {
1687 1673
1688#[test] 1674#[test]
1689fn shadowing_primitive() { 1675fn shadowing_primitive() {
1690 let t = type_at( 1676 check_types(
1691 r#" 1677 r#"
1692//- /main.rs
1693struct i32; 1678struct i32;
1694struct Foo; 1679struct Foo;
1695 1680
@@ -1697,15 +1682,15 @@ impl i32 { fn foo(&self) -> Foo { Foo } }
1697 1682
1698fn main() { 1683fn main() {
1699 let x: i32 = i32; 1684 let x: i32 = i32;
1700 x.foo()<|>; 1685 x.foo();
1686 //^ Foo
1701}"#, 1687}"#,
1702 ); 1688 );
1703 assert_eq!(t, "Foo");
1704} 1689}
1705 1690
1706#[test] 1691#[test]
1707fn not_shadowing_primitive_by_module() { 1692fn not_shadowing_primitive_by_module() {
1708 let t = type_at( 1693 check_types(
1709 r#" 1694 r#"
1710//- /str.rs 1695//- /str.rs
1711fn foo() {} 1696fn foo() {}
@@ -1715,15 +1700,15 @@ mod str;
1715fn foo() -> &'static str { "" } 1700fn foo() -> &'static str { "" }
1716 1701
1717fn main() { 1702fn main() {
1718 foo()<|>; 1703 foo();
1704 //^ &str
1719}"#, 1705}"#,
1720 ); 1706 );
1721 assert_eq!(t, "&str");
1722} 1707}
1723 1708
1724#[test] 1709#[test]
1725fn not_shadowing_module_by_primitive() { 1710fn not_shadowing_module_by_primitive() {
1726 let t = type_at( 1711 check_types(
1727 r#" 1712 r#"
1728//- /str.rs 1713//- /str.rs
1729fn foo() -> u32 {0} 1714fn foo() -> u32 {0}
@@ -1733,10 +1718,10 @@ mod str;
1733fn foo() -> &'static str { "" } 1718fn foo() -> &'static str { "" }
1734 1719
1735fn main() { 1720fn main() {
1736 str::foo()<|>; 1721 str::foo();
1722 //^ u32
1737}"#, 1723}"#,
1738 ); 1724 );
1739 assert_eq!(t, "u32");
1740} 1725}
1741 1726
1742// This test is actually testing the shadowing behavior within ra_hir_def. It 1727// This test is actually testing the shadowing behavior within ra_hir_def. It
@@ -1744,27 +1729,7 @@ fn main() {
1744// capable of asserting the necessary conditions. 1729// capable of asserting the necessary conditions.
1745#[test] 1730#[test]
1746fn should_be_shadowing_imports() { 1731fn should_be_shadowing_imports() {
1747 let t = type_at( 1732 check_types(
1748 r#"
1749mod a {
1750 pub fn foo() -> i8 {0}
1751 pub struct foo { a: i8 }
1752}
1753mod b { pub fn foo () -> u8 {0} }
1754mod c { pub struct foo { a: u8 } }
1755mod d {
1756 pub use super::a::*;
1757 pub use super::c::foo;
1758 pub use super::b::foo;
1759}
1760
1761fn main() {
1762 d::foo()<|>;
1763}"#,
1764 );
1765 assert_eq!(t, "u8");
1766
1767 let t = type_at(
1768 r#" 1733 r#"
1769mod a { 1734mod a {
1770 pub fn foo() -> i8 {0} 1735 pub fn foo() -> i8 {0}
@@ -1779,10 +1744,12 @@ mod d {
1779} 1744}
1780 1745
1781fn main() { 1746fn main() {
1782 d::foo{a:0<|>}; 1747 d::foo();
1748 //^ u8
1749 d::foo{a:0};
1750 //^ u8
1783}"#, 1751}"#,
1784 ); 1752 );
1785 assert_eq!(t, "u8");
1786} 1753}
1787 1754
1788#[test] 1755#[test]
@@ -2152,3 +2119,48 @@ fn test() {
2152 "### 2119 "###
2153 ); 2120 );
2154} 2121}
2122
2123#[test]
2124fn generic_default_depending_on_other_type_arg() {
2125 assert_snapshot!(
2126 infer(r#"
2127struct Thing<T = u128, F = fn() -> T> { t: T }
2128
2129fn test(t1: Thing<u32>, t2: Thing) {
2130 t1;
2131 t2;
2132 Thing::<_> { t: 1u32 };
2133}
2134"#),
2135 // FIXME: the {unknown} is a bug
2136 @r###"
2137 56..58 't1': Thing<u32, fn() -> u32>
2138 72..74 't2': Thing<u128, fn() -> u128>
2139 83..130 '{ ...2 }; }': ()
2140 89..91 't1': Thing<u32, fn() -> u32>
2141 97..99 't2': Thing<u128, fn() -> u128>
2142 105..127 'Thing:...1u32 }': Thing<u32, fn() -> {unknown}>
2143 121..125 '1u32': u32
2144 "###
2145 );
2146}
2147
2148#[test]
2149fn generic_default_depending_on_other_type_arg_forward() {
2150 assert_snapshot!(
2151 infer(r#"
2152struct Thing<F = fn() -> T, T = u128> { t: T }
2153
2154fn test(t1: Thing) {
2155 t1;
2156}
2157"#),
2158 // the {unknown} here is intentional, as defaults are not allowed to
2159 // refer to type parameters coming later
2160 @r###"
2161 56..58 't1': Thing<fn() -> {unknown}, u128>
2162 67..78 '{ t1; }': ()
2163 73..75 't1': Thing<fn() -> {unknown}, u128>
2164 "###
2165 );
2166}
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index 71c0c2d27..01c919a7e 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -1,17 +1,13 @@
1use insta::assert_snapshot; 1use insta::assert_snapshot;
2use ra_db::fixture::WithFixture;
3use test_utils::mark; 2use test_utils::mark;
4 3
5use crate::test_db::TestDB; 4use super::{check_types, infer, infer_with_mismatches};
6
7use super::{infer, infer_with_mismatches, type_at, type_at_pos};
8 5
9#[test] 6#[test]
10fn infer_await() { 7fn infer_await() {
11 let (db, pos) = TestDB::with_position( 8 check_types(
12 r#" 9 r#"
13//- /main.rs crate:main deps:core 10//- /main.rs crate:main deps:core
14
15struct IntFuture; 11struct IntFuture;
16 12
17impl Future for IntFuture { 13impl Future for IntFuture {
@@ -21,8 +17,8 @@ impl Future for IntFuture {
21fn test() { 17fn test() {
22 let r = IntFuture; 18 let r = IntFuture;
23 let v = r.await; 19 let v = r.await;
24 v<|>; 20 v;
25} 21} //^ u64
26 22
27//- /core.rs crate:core 23//- /core.rs crate:core
28#[prelude_import] use future::*; 24#[prelude_import] use future::*;
@@ -32,18 +28,15 @@ mod future {
32 type Output; 28 type Output;
33 } 29 }
34} 30}
35
36"#, 31"#,
37 ); 32 );
38 assert_eq!("u64", type_at_pos(&db, pos));
39} 33}
40 34
41#[test] 35#[test]
42fn infer_async() { 36fn infer_async() {
43 let (db, pos) = TestDB::with_position( 37 check_types(
44 r#" 38 r#"
45//- /main.rs crate:main deps:core 39//- /main.rs crate:main deps:core
46
47async fn foo() -> u64 { 40async fn foo() -> u64 {
48 128 41 128
49} 42}
@@ -51,8 +44,8 @@ async fn foo() -> u64 {
51fn test() { 44fn test() {
52 let r = foo(); 45 let r = foo();
53 let v = r.await; 46 let v = r.await;
54 v<|>; 47 v;
55} 48} //^ u64
56 49
57//- /core.rs crate:core 50//- /core.rs crate:core
58#[prelude_import] use future::*; 51#[prelude_import] use future::*;
@@ -62,26 +55,23 @@ mod future {
62 type Output; 55 type Output;
63 } 56 }
64} 57}
65
66"#, 58"#,
67 ); 59 );
68 assert_eq!("u64", type_at_pos(&db, pos));
69} 60}
70 61
71#[test] 62#[test]
72fn infer_desugar_async() { 63fn infer_desugar_async() {
73 let (db, pos) = TestDB::with_position( 64 check_types(
74 r#" 65 r#"
75//- /main.rs crate:main deps:core 66//- /main.rs crate:main deps:core
76
77async fn foo() -> u64 { 67async fn foo() -> u64 {
78 128 68 128
79} 69}
80 70
81fn test() { 71fn test() {
82 let r = foo(); 72 let r = foo();
83 r<|>; 73 r;
84} 74} //^ impl Future<Output = u64>
85 75
86//- /core.rs crate:core 76//- /core.rs crate:core
87#[prelude_import] use future::*; 77#[prelude_import] use future::*;
@@ -93,23 +83,20 @@ mod future {
93 83
94"#, 84"#,
95 ); 85 );
96 assert_eq!("impl Future<Output = u64>", type_at_pos(&db, pos));
97} 86}
98 87
99#[test] 88#[test]
100fn infer_try() { 89fn infer_try() {
101 let (db, pos) = TestDB::with_position( 90 check_types(
102 r#" 91 r#"
103//- /main.rs crate:main deps:core 92//- /main.rs crate:main deps:core
104
105fn test() { 93fn test() {
106 let r: Result<i32, u64> = Result::Ok(1); 94 let r: Result<i32, u64> = Result::Ok(1);
107 let v = r?; 95 let v = r?;
108 v<|>; 96 v;
109} 97} //^ i32
110 98
111//- /core.rs crate:core 99//- /core.rs crate:core
112
113#[prelude_import] use ops::*; 100#[prelude_import] use ops::*;
114mod ops { 101mod ops {
115 trait Try { 102 trait Try {
@@ -130,30 +117,26 @@ mod result {
130 type Error = E; 117 type Error = E;
131 } 118 }
132} 119}
133
134"#, 120"#,
135 ); 121 );
136 assert_eq!("i32", type_at_pos(&db, pos));
137} 122}
138 123
139#[test] 124#[test]
140fn infer_for_loop() { 125fn infer_for_loop() {
141 let (db, pos) = TestDB::with_position( 126 check_types(
142 r#" 127 r#"
143//- /main.rs crate:main deps:core,alloc 128//- /main.rs crate:main deps:core,alloc
144
145use alloc::collections::Vec; 129use alloc::collections::Vec;
146 130
147fn test() { 131fn test() {
148 let v = Vec::new(); 132 let v = Vec::new();
149 v.push("foo"); 133 v.push("foo");
150 for x in v { 134 for x in v {
151 x<|>; 135 x;
152 } 136 } //^ &str
153} 137}
154 138
155//- /core.rs crate:core 139//- /core.rs crate:core
156
157#[prelude_import] use iter::*; 140#[prelude_import] use iter::*;
158mod iter { 141mod iter {
159 trait IntoIterator { 142 trait IntoIterator {
@@ -162,7 +145,6 @@ mod iter {
162} 145}
163 146
164//- /alloc.rs crate:alloc deps:core 147//- /alloc.rs crate:alloc deps:core
165
166mod collections { 148mod collections {
167 struct Vec<T> {} 149 struct Vec<T> {}
168 impl<T> Vec<T> { 150 impl<T> Vec<T> {
@@ -176,15 +158,13 @@ mod collections {
176} 158}
177"#, 159"#,
178 ); 160 );
179 assert_eq!("&str", type_at_pos(&db, pos));
180} 161}
181 162
182#[test] 163#[test]
183fn infer_ops_neg() { 164fn infer_ops_neg() {
184 let (db, pos) = TestDB::with_position( 165 check_types(
185 r#" 166 r#"
186//- /main.rs crate:main deps:std 167//- /main.rs crate:main deps:std
187
188struct Bar; 168struct Bar;
189struct Foo; 169struct Foo;
190 170
@@ -195,11 +175,10 @@ impl std::ops::Neg for Bar {
195fn test() { 175fn test() {
196 let a = Bar; 176 let a = Bar;
197 let b = -a; 177 let b = -a;
198 b<|>; 178 b;
199} 179} //^ Foo
200 180
201//- /std.rs crate:std 181//- /std.rs crate:std
202
203#[prelude_import] use ops::*; 182#[prelude_import] use ops::*;
204mod ops { 183mod ops {
205 #[lang = "neg"] 184 #[lang = "neg"]
@@ -209,15 +188,13 @@ mod ops {
209} 188}
210"#, 189"#,
211 ); 190 );
212 assert_eq!("Foo", type_at_pos(&db, pos));
213} 191}
214 192
215#[test] 193#[test]
216fn infer_ops_not() { 194fn infer_ops_not() {
217 let (db, pos) = TestDB::with_position( 195 check_types(
218 r#" 196 r#"
219//- /main.rs crate:main deps:std 197//- /main.rs crate:main deps:std
220
221struct Bar; 198struct Bar;
222struct Foo; 199struct Foo;
223 200
@@ -228,11 +205,10 @@ impl std::ops::Not for Bar {
228fn test() { 205fn test() {
229 let a = Bar; 206 let a = Bar;
230 let b = !a; 207 let b = !a;
231 b<|>; 208 b;
232} 209} //^ Foo
233 210
234//- /std.rs crate:std 211//- /std.rs crate:std
235
236#[prelude_import] use ops::*; 212#[prelude_import] use ops::*;
237mod ops { 213mod ops {
238 #[lang = "not"] 214 #[lang = "not"]
@@ -242,7 +218,6 @@ mod ops {
242} 218}
243"#, 219"#,
244 ); 220 );
245 assert_eq!("Foo", type_at_pos(&db, pos));
246} 221}
247 222
248#[test] 223#[test]
@@ -537,10 +512,9 @@ fn indexing_arrays() {
537 512
538#[test] 513#[test]
539fn infer_ops_index() { 514fn infer_ops_index() {
540 let (db, pos) = TestDB::with_position( 515 check_types(
541 r#" 516 r#"
542//- /main.rs crate:main deps:std 517//- /main.rs crate:main deps:std
543
544struct Bar; 518struct Bar;
545struct Foo; 519struct Foo;
546 520
@@ -551,11 +525,10 @@ impl std::ops::Index<u32> for Bar {
551fn test() { 525fn test() {
552 let a = Bar; 526 let a = Bar;
553 let b = a[1u32]; 527 let b = a[1u32];
554 b<|>; 528 b;
555} 529} //^ Foo
556 530
557//- /std.rs crate:std 531//- /std.rs crate:std
558
559#[prelude_import] use ops::*; 532#[prelude_import] use ops::*;
560mod ops { 533mod ops {
561 #[lang = "index"] 534 #[lang = "index"]
@@ -565,19 +538,18 @@ mod ops {
565} 538}
566"#, 539"#,
567 ); 540 );
568 assert_eq!("Foo", type_at_pos(&db, pos));
569} 541}
570 542
571#[test] 543#[test]
572fn infer_ops_index_autoderef() { 544fn infer_ops_index_autoderef() {
573 let (db, pos) = TestDB::with_position( 545 check_types(
574 r#" 546 r#"
575//- /main.rs crate:main deps:std 547//- /main.rs crate:main deps:std
576fn test() { 548fn test() {
577 let a = &[1u32, 2, 3]; 549 let a = &[1u32, 2, 3];
578 let b = a[1u32]; 550 let b = a[1u32];
579 b<|>; 551 b;
580} 552} //^ u32
581 553
582//- /std.rs crate:std 554//- /std.rs crate:std
583impl<T> ops::Index<u32> for [T] { 555impl<T> ops::Index<u32> for [T] {
@@ -593,14 +565,12 @@ mod ops {
593} 565}
594"#, 566"#,
595 ); 567 );
596 assert_eq!("u32", type_at_pos(&db, pos));
597} 568}
598 569
599#[test] 570#[test]
600fn deref_trait() { 571fn deref_trait() {
601 let t = type_at( 572 check_types(
602 r#" 573 r#"
603//- /main.rs
604#[lang = "deref"] 574#[lang = "deref"]
605trait Deref { 575trait Deref {
606 type Target; 576 type Target;
@@ -618,16 +588,15 @@ impl S {
618} 588}
619 589
620fn test(s: Arc<S>) { 590fn test(s: Arc<S>) {
621 (*s, s.foo())<|>; 591 (*s, s.foo());
622} 592} //^ (S, u128)
623"#, 593"#,
624 ); 594 );
625 assert_eq!(t, "(S, u128)");
626} 595}
627 596
628#[test] 597#[test]
629fn deref_trait_with_inference_var() { 598fn deref_trait_with_inference_var() {
630 let t = type_at( 599 check_types(
631 r#" 600 r#"
632//- /main.rs 601//- /main.rs
633#[lang = "deref"] 602#[lang = "deref"]
@@ -647,19 +616,18 @@ fn foo(a: Arc<S>) {}
647 616
648fn test() { 617fn test() {
649 let a = new_arc(); 618 let a = new_arc();
650 let b = (*a)<|>; 619 let b = (*a);
620 //^ S
651 foo(a); 621 foo(a);
652} 622}
653"#, 623"#,
654 ); 624 );
655 assert_eq!(t, "S");
656} 625}
657 626
658#[test] 627#[test]
659fn deref_trait_infinite_recursion() { 628fn deref_trait_infinite_recursion() {
660 let t = type_at( 629 check_types(
661 r#" 630 r#"
662//- /main.rs
663#[lang = "deref"] 631#[lang = "deref"]
664trait Deref { 632trait Deref {
665 type Target; 633 type Target;
@@ -673,18 +641,16 @@ impl Deref for S {
673} 641}
674 642
675fn test(s: S) { 643fn test(s: S) {
676 s.foo()<|>; 644 s.foo();
677} 645} //^ {unknown}
678"#, 646"#,
679 ); 647 );
680 assert_eq!(t, "{unknown}");
681} 648}
682 649
683#[test] 650#[test]
684fn deref_trait_with_question_mark_size() { 651fn deref_trait_with_question_mark_size() {
685 let t = type_at( 652 check_types(
686 r#" 653 r#"
687//- /main.rs
688#[lang = "deref"] 654#[lang = "deref"]
689trait Deref { 655trait Deref {
690 type Target; 656 type Target;
@@ -702,18 +668,16 @@ impl S {
702} 668}
703 669
704fn test(s: Arc<S>) { 670fn test(s: Arc<S>) {
705 (*s, s.foo())<|>; 671 (*s, s.foo());
706} 672} //^ (S, u128)
707"#, 673"#,
708 ); 674 );
709 assert_eq!(t, "(S, u128)");
710} 675}
711 676
712#[test] 677#[test]
713fn obligation_from_function_clause() { 678fn obligation_from_function_clause() {
714 let t = type_at( 679 check_types(
715 r#" 680 r#"
716//- /main.rs
717struct S; 681struct S;
718 682
719trait Trait<T> {} 683trait Trait<T> {}
@@ -722,16 +686,15 @@ impl Trait<u32> for S {}
722fn foo<T: Trait<U>, U>(t: T) -> U {} 686fn foo<T: Trait<U>, U>(t: T) -> U {}
723 687
724fn test(s: S) { 688fn test(s: S) {
725 foo(s)<|>; 689 (foo(s));
726} 690} //^ u32
727"#, 691"#,
728 ); 692 );
729 assert_eq!(t, "u32");
730} 693}
731 694
732#[test] 695#[test]
733fn obligation_from_method_clause() { 696fn obligation_from_method_clause() {
734 let t = type_at( 697 check_types(
735 r#" 698 r#"
736//- /main.rs 699//- /main.rs
737struct S; 700struct S;
@@ -745,18 +708,16 @@ impl O {
745} 708}
746 709
747fn test() { 710fn test() {
748 O.foo(S)<|>; 711 O.foo(S);
749} 712} //^ isize
750"#, 713"#,
751 ); 714 );
752 assert_eq!(t, "isize");
753} 715}
754 716
755#[test] 717#[test]
756fn obligation_from_self_method_clause() { 718fn obligation_from_self_method_clause() {
757 let t = type_at( 719 check_types(
758 r#" 720 r#"
759//- /main.rs
760struct S; 721struct S;
761 722
762trait Trait<T> {} 723trait Trait<T> {}
@@ -767,18 +728,16 @@ impl S {
767} 728}
768 729
769fn test() { 730fn test() {
770 S.foo()<|>; 731 S.foo();
771} 732} //^ i64
772"#, 733"#,
773 ); 734 );
774 assert_eq!(t, "i64");
775} 735}
776 736
777#[test] 737#[test]
778fn obligation_from_impl_clause() { 738fn obligation_from_impl_clause() {
779 let t = type_at( 739 check_types(
780 r#" 740 r#"
781//- /main.rs
782struct S; 741struct S;
783 742
784trait Trait<T> {} 743trait Trait<T> {}
@@ -790,32 +749,30 @@ impl<U, T: Trait<U>> O<T> {
790} 749}
791 750
792fn test(o: O<S>) { 751fn test(o: O<S>) {
793 o.foo()<|>; 752 o.foo();
794} 753} //^ &str
795"#, 754"#,
796 ); 755 );
797 assert_eq!(t, "&str");
798} 756}
799 757
800#[test] 758#[test]
801fn generic_param_env_1() { 759fn generic_param_env_1() {
802 let t = type_at( 760 check_types(
803 r#" 761 r#"
804//- /main.rs
805trait Clone {} 762trait Clone {}
806trait Trait { fn foo(self) -> u128; } 763trait Trait { fn foo(self) -> u128; }
807struct S; 764struct S;
808impl Clone for S {} 765impl Clone for S {}
809impl<T> Trait for T where T: Clone {} 766impl<T> Trait for T where T: Clone {}
810fn test<T: Clone>(t: T) { t.foo()<|>; } 767fn test<T: Clone>(t: T) { t.foo(); }
768 //^ u128
811"#, 769"#,
812 ); 770 );
813 assert_eq!(t, "u128");
814} 771}
815 772
816#[test] 773#[test]
817fn generic_param_env_1_not_met() { 774fn generic_param_env_1_not_met() {
818 let t = type_at( 775 check_types(
819 r#" 776 r#"
820//- /main.rs 777//- /main.rs
821trait Clone {} 778trait Clone {}
@@ -823,45 +780,42 @@ trait Trait { fn foo(self) -> u128; }
823struct S; 780struct S;
824impl Clone for S {} 781impl Clone for S {}
825impl<T> Trait for T where T: Clone {} 782impl<T> Trait for T where T: Clone {}
826fn test<T>(t: T) { t.foo()<|>; } 783fn test<T>(t: T) { t.foo(); }
784 //^ {unknown}
827"#, 785"#,
828 ); 786 );
829 assert_eq!(t, "{unknown}");
830} 787}
831 788
832#[test] 789#[test]
833fn generic_param_env_2() { 790fn generic_param_env_2() {
834 let t = type_at( 791 check_types(
835 r#" 792 r#"
836//- /main.rs
837trait Trait { fn foo(self) -> u128; } 793trait Trait { fn foo(self) -> u128; }
838struct S; 794struct S;
839impl Trait for S {} 795impl Trait for S {}
840fn test<T: Trait>(t: T) { t.foo()<|>; } 796fn test<T: Trait>(t: T) { t.foo(); }
797 //^ u128
841"#, 798"#,
842 ); 799 );
843 assert_eq!(t, "u128");
844} 800}
845 801
846#[test] 802#[test]
847fn generic_param_env_2_not_met() { 803fn generic_param_env_2_not_met() {
848 let t = type_at( 804 check_types(
849 r#" 805 r#"
850//- /main.rs
851trait Trait { fn foo(self) -> u128; } 806trait Trait { fn foo(self) -> u128; }
852struct S; 807struct S;
853impl Trait for S {} 808impl Trait for S {}
854fn test<T>(t: T) { t.foo()<|>; } 809fn test<T>(t: T) { t.foo(); }
810 //^ {unknown}
855"#, 811"#,
856 ); 812 );
857 assert_eq!(t, "{unknown}");
858} 813}
859 814
860#[test] 815#[test]
861fn generic_param_env_deref() { 816fn generic_param_env_deref() {
862 let t = type_at( 817 check_types(
863 r#" 818 r#"
864//- /main.rs
865#[lang = "deref"] 819#[lang = "deref"]
866trait Deref { 820trait Deref {
867 type Target; 821 type Target;
@@ -870,17 +824,17 @@ trait Trait {}
870impl<T> Deref for T where T: Trait { 824impl<T> Deref for T where T: Trait {
871 type Target = i128; 825 type Target = i128;
872} 826}
873fn test<T: Trait>(t: T) { (*t)<|>; } 827fn test<T: Trait>(t: T) { (*t); }
828 //^ i128
874"#, 829"#,
875 ); 830 );
876 assert_eq!(t, "i128");
877} 831}
878 832
879#[test] 833#[test]
880fn associated_type_placeholder() { 834fn associated_type_placeholder() {
881 let t = type_at( 835 // inside the generic function, the associated type gets normalized to a placeholder `ApplL::Out<T>` [https://rust-lang.github.io/rustc-guide/traits/associated-types.html#placeholder-associated-types].
836 check_types(
882 r#" 837 r#"
883//- /main.rs
884pub trait ApplyL { 838pub trait ApplyL {
885 type Out; 839 type Out;
886} 840}
@@ -893,19 +847,16 @@ impl<T> ApplyL for RefMutL<T> {
893 847
894fn test<T: ApplyL>() { 848fn test<T: ApplyL>() {
895 let y: <RefMutL<T> as ApplyL>::Out = no_matter; 849 let y: <RefMutL<T> as ApplyL>::Out = no_matter;
896 y<|>; 850 y;
897} 851} //^ ApplyL::Out<T>
898"#, 852"#,
899 ); 853 );
900 // inside the generic function, the associated type gets normalized to a placeholder `ApplL::Out<T>` [https://rust-lang.github.io/rustc-guide/traits/associated-types.html#placeholder-associated-types].
901 assert_eq!(t, "ApplyL::Out<T>");
902} 854}
903 855
904#[test] 856#[test]
905fn associated_type_placeholder_2() { 857fn associated_type_placeholder_2() {
906 let t = type_at( 858 check_types(
907 r#" 859 r#"
908//- /main.rs
909pub trait ApplyL { 860pub trait ApplyL {
910 type Out; 861 type Out;
911} 862}
@@ -913,11 +864,10 @@ fn foo<T: ApplyL>(t: T) -> <T as ApplyL>::Out;
913 864
914fn test<T: ApplyL>(t: T) { 865fn test<T: ApplyL>(t: T) {
915 let y = foo(t); 866 let y = foo(t);
916 y<|>; 867 y;
917} 868} //^ ApplyL::Out<T>
918"#, 869"#,
919 ); 870 );
920 assert_eq!(t, "ApplyL::Out<T>");
921} 871}
922 872
923#[test] 873#[test]
@@ -1398,19 +1348,17 @@ fn test(a: impl Trait + 'lifetime, b: impl 'lifetime, c: impl (Trait), d: impl (
1398#[test] 1348#[test]
1399#[ignore] 1349#[ignore]
1400fn error_bound_chalk() { 1350fn error_bound_chalk() {
1401 let t = type_at( 1351 check_types(
1402 r#" 1352 r#"
1403//- /main.rs
1404trait Trait { 1353trait Trait {
1405 fn foo(&self) -> u32 {} 1354 fn foo(&self) -> u32 {}
1406} 1355}
1407 1356
1408fn test(x: (impl Trait + UnknownTrait)) { 1357fn test(x: (impl Trait + UnknownTrait)) {
1409 x.foo()<|>; 1358 x.foo();
1410} 1359} //^ u32
1411"#, 1360"#,
1412 ); 1361 );
1413 assert_eq!(t, "u32");
1414} 1362}
1415 1363
1416#[test] 1364#[test]
@@ -1480,7 +1428,7 @@ fn test<T: Trait<Type = u32>>(x: T, y: impl Trait<Type = i64>) {
1480 1428
1481#[test] 1429#[test]
1482fn impl_trait_assoc_binding_projection_bug() { 1430fn impl_trait_assoc_binding_projection_bug() {
1483 let (db, pos) = TestDB::with_position( 1431 check_types(
1484 r#" 1432 r#"
1485//- /main.rs crate:main deps:std 1433//- /main.rs crate:main deps:std
1486pub trait Language { 1434pub trait Language {
@@ -1499,8 +1447,8 @@ trait Clone {
1499 1447
1500fn api_walkthrough() { 1448fn api_walkthrough() {
1501 for node in foo() { 1449 for node in foo() {
1502 node.clone()<|>; 1450 node.clone();
1503 } 1451 } //^ {unknown}
1504} 1452}
1505 1453
1506//- /std.rs crate:std 1454//- /std.rs crate:std
@@ -1518,7 +1466,6 @@ mod iter {
1518} 1466}
1519"#, 1467"#,
1520 ); 1468 );
1521 assert_eq!("{unknown}", type_at_pos(&db, pos));
1522} 1469}
1523 1470
1524#[test] 1471#[test]
@@ -1549,9 +1496,8 @@ fn test<T: Trait1<Type = u32>>(x: T) {
1549 1496
1550#[test] 1497#[test]
1551fn where_clause_trait_in_scope_for_method_resolution() { 1498fn where_clause_trait_in_scope_for_method_resolution() {
1552 let t = type_at( 1499 check_types(
1553 r#" 1500 r#"
1554//- /main.rs
1555mod foo { 1501mod foo {
1556 trait Trait { 1502 trait Trait {
1557 fn foo(&self) -> u32 {} 1503 fn foo(&self) -> u32 {}
@@ -1559,11 +1505,10 @@ mod foo {
1559} 1505}
1560 1506
1561fn test<T: foo::Trait>(x: T) { 1507fn test<T: foo::Trait>(x: T) {
1562 x.foo()<|>; 1508 x.foo();
1563} 1509} //^ u32
1564"#, 1510"#,
1565 ); 1511 );
1566 assert_eq!(t, "u32");
1567} 1512}
1568 1513
1569#[test] 1514#[test]
@@ -2012,7 +1957,7 @@ fn test() {
2012 1957
2013#[test] 1958#[test]
2014fn unselected_projection_in_trait_env_1() { 1959fn unselected_projection_in_trait_env_1() {
2015 let t = type_at( 1960 check_types(
2016 r#" 1961 r#"
2017//- /main.rs 1962//- /main.rs
2018trait Trait { 1963trait Trait {
@@ -2025,18 +1970,16 @@ trait Trait2 {
2025 1970
2026fn test<T: Trait>() where T::Item: Trait2 { 1971fn test<T: Trait>() where T::Item: Trait2 {
2027 let x: T::Item = no_matter; 1972 let x: T::Item = no_matter;
2028 x.foo()<|>; 1973 x.foo();
2029} 1974} //^ u32
2030"#, 1975"#,
2031 ); 1976 );
2032 assert_eq!(t, "u32");
2033} 1977}
2034 1978
2035#[test] 1979#[test]
2036fn unselected_projection_in_trait_env_2() { 1980fn unselected_projection_in_trait_env_2() {
2037 let t = type_at( 1981 check_types(
2038 r#" 1982 r#"
2039//- /main.rs
2040trait Trait<T> { 1983trait Trait<T> {
2041 type Item; 1984 type Item;
2042} 1985}
@@ -2047,11 +1990,10 @@ trait Trait2 {
2047 1990
2048fn test<T, U>() where T::Item: Trait2, T: Trait<U::Item>, U: Trait<()> { 1991fn test<T, U>() where T::Item: Trait2, T: Trait<U::Item>, U: Trait<()> {
2049 let x: T::Item = no_matter; 1992 let x: T::Item = no_matter;
2050 x.foo()<|>; 1993 x.foo();
2051} 1994} //^ u32
2052"#, 1995"#,
2053 ); 1996 );
2054 assert_eq!(t, "u32");
2055} 1997}
2056 1998
2057#[test] 1999#[test]
@@ -2097,9 +2039,8 @@ impl Trait for S2 {
2097 2039
2098#[test] 2040#[test]
2099fn unselected_projection_on_trait_self() { 2041fn unselected_projection_on_trait_self() {
2100 let t = type_at( 2042 check_types(
2101 r#" 2043 r#"
2102//- /main.rs
2103trait Trait { 2044trait Trait {
2104 type Item; 2045 type Item;
2105 2046
@@ -2112,18 +2053,16 @@ impl Trait for S {
2112} 2053}
2113 2054
2114fn test() { 2055fn test() {
2115 S.f()<|>; 2056 S.f();
2116} 2057} //^ u32
2117"#, 2058"#,
2118 ); 2059 );
2119 assert_eq!(t, "u32");
2120} 2060}
2121 2061
2122#[test] 2062#[test]
2123fn unselected_projection_chalk_fold() { 2063fn unselected_projection_chalk_fold() {
2124 let t = type_at( 2064 check_types(
2125 r#" 2065 r#"
2126//- /main.rs
2127trait Interner {} 2066trait Interner {}
2128trait Fold<I: Interner, TI = I> { 2067trait Fold<I: Interner, TI = I> {
2129 type Result; 2068 type Result;
@@ -2142,18 +2081,16 @@ where
2142} 2081}
2143 2082
2144fn foo<I: Interner>(interner: &I, t: Ty<I>) { 2083fn foo<I: Interner>(interner: &I, t: Ty<I>) {
2145 fold(interner, t)<|>; 2084 fold(interner, t);
2146} 2085} //^ Ty<I>
2147"#, 2086"#,
2148 ); 2087 );
2149 assert_eq!(t, "Ty<I>");
2150} 2088}
2151 2089
2152#[test] 2090#[test]
2153fn trait_impl_self_ty() { 2091fn trait_impl_self_ty() {
2154 let t = type_at( 2092 check_types(
2155 r#" 2093 r#"
2156//- /main.rs
2157trait Trait<T> { 2094trait Trait<T> {
2158 fn foo(&self); 2095 fn foo(&self);
2159} 2096}
@@ -2163,18 +2100,16 @@ struct S;
2163impl Trait<Self> for S {} 2100impl Trait<Self> for S {}
2164 2101
2165fn test() { 2102fn test() {
2166 S.foo()<|>; 2103 S.foo();
2167} 2104} //^ ()
2168"#, 2105"#,
2169 ); 2106 );
2170 assert_eq!(t, "()");
2171} 2107}
2172 2108
2173#[test] 2109#[test]
2174fn trait_impl_self_ty_cycle() { 2110fn trait_impl_self_ty_cycle() {
2175 let t = type_at( 2111 check_types(
2176 r#" 2112 r#"
2177//- /main.rs
2178trait Trait { 2113trait Trait {
2179 fn foo(&self); 2114 fn foo(&self);
2180} 2115}
@@ -2184,18 +2119,17 @@ struct S<T>;
2184impl Trait for S<Self> {} 2119impl Trait for S<Self> {}
2185 2120
2186fn test() { 2121fn test() {
2187 S.foo()<|>; 2122 S.foo();
2188} 2123} //^ {unknown}
2189"#, 2124"#,
2190 ); 2125 );
2191 assert_eq!(t, "{unknown}");
2192} 2126}
2193 2127
2194#[test] 2128#[test]
2195fn unselected_projection_in_trait_env_cycle_1() { 2129fn unselected_projection_in_trait_env_cycle_1() {
2196 let t = type_at( 2130 // this is a legitimate cycle
2131 check_types(
2197 r#" 2132 r#"
2198//- /main.rs
2199trait Trait { 2133trait Trait {
2200 type Item; 2134 type Item;
2201} 2135}
@@ -2203,17 +2137,16 @@ trait Trait {
2203trait Trait2<T> {} 2137trait Trait2<T> {}
2204 2138
2205fn test<T: Trait>() where T: Trait2<T::Item> { 2139fn test<T: Trait>() where T: Trait2<T::Item> {
2206 let x: T::Item = no_matter<|>; 2140 let x: T::Item = no_matter;
2207} 2141} //^ {unknown}
2208"#, 2142"#,
2209 ); 2143 );
2210 // this is a legitimate cycle
2211 assert_eq!(t, "{unknown}");
2212} 2144}
2213 2145
2214#[test] 2146#[test]
2215fn unselected_projection_in_trait_env_cycle_2() { 2147fn unselected_projection_in_trait_env_cycle_2() {
2216 let t = type_at( 2148 // this is a legitimate cycle
2149 check_types(
2217 r#" 2150 r#"
2218//- /main.rs 2151//- /main.rs
2219trait Trait<T> { 2152trait Trait<T> {
@@ -2221,19 +2154,16 @@ trait Trait<T> {
2221} 2154}
2222 2155
2223fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> { 2156fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> {
2224 let x: T::Item = no_matter<|>; 2157 let x: T::Item = no_matter;
2225} 2158} //^ {unknown}
2226"#, 2159"#,
2227 ); 2160 );
2228 // this is a legitimate cycle
2229 assert_eq!(t, "{unknown}");
2230} 2161}
2231 2162
2232#[test] 2163#[test]
2233fn inline_assoc_type_bounds_1() { 2164fn inline_assoc_type_bounds_1() {
2234 let t = type_at( 2165 check_types(
2235 r#" 2166 r#"
2236//- /main.rs
2237trait Iterator { 2167trait Iterator {
2238 type Item; 2168 type Item;
2239} 2169}
@@ -2249,29 +2179,26 @@ impl<T: Iterator> Iterator for S<T> {
2249 2179
2250fn test<I: Iterator<Item: OtherTrait<u32>>>() { 2180fn test<I: Iterator<Item: OtherTrait<u32>>>() {
2251 let x: <S<I> as Iterator>::Item; 2181 let x: <S<I> as Iterator>::Item;
2252 x.foo()<|>; 2182 x.foo();
2253} 2183} //^ u32
2254"#, 2184"#,
2255 ); 2185 );
2256 assert_eq!(t, "u32");
2257} 2186}
2258 2187
2259#[test] 2188#[test]
2260fn inline_assoc_type_bounds_2() { 2189fn inline_assoc_type_bounds_2() {
2261 let t = type_at( 2190 check_types(
2262 r#" 2191 r#"
2263//- /main.rs
2264trait Iterator { 2192trait Iterator {
2265 type Item; 2193 type Item;
2266} 2194}
2267 2195
2268fn test<I: Iterator<Item: Iterator<Item = u32>>>() { 2196fn test<I: Iterator<Item: Iterator<Item = u32>>>() {
2269 let x: <<I as Iterator>::Item as Iterator>::Item; 2197 let x: <<I as Iterator>::Item as Iterator>::Item;
2270 x<|>; 2198 x;
2271} 2199} //^ u32
2272"#, 2200"#,
2273 ); 2201 );
2274 assert_eq!(t, "u32");
2275} 2202}
2276 2203
2277#[test] 2204#[test]
@@ -2445,9 +2372,8 @@ fn main() {
2445 2372
2446#[test] 2373#[test]
2447fn associated_type_bound() { 2374fn associated_type_bound() {
2448 let t = type_at( 2375 check_types(
2449 r#" 2376 r#"
2450//- /main.rs
2451pub trait Trait { 2377pub trait Trait {
2452 type Item: OtherTrait<u32>; 2378 type Item: OtherTrait<u32>;
2453} 2379}
@@ -2463,18 +2389,16 @@ impl<T: Trait> Trait for S<T> {
2463 2389
2464fn test<T: Trait>() { 2390fn test<T: Trait>() {
2465 let y: <S<T> as Trait>::Item = no_matter; 2391 let y: <S<T> as Trait>::Item = no_matter;
2466 y.foo()<|>; 2392 y.foo();
2467} 2393} //^ u32
2468"#, 2394"#,
2469 ); 2395 );
2470 assert_eq!(t, "u32");
2471} 2396}
2472 2397
2473#[test] 2398#[test]
2474fn dyn_trait_through_chalk() { 2399fn dyn_trait_through_chalk() {
2475 let t = type_at( 2400 check_types(
2476 r#" 2401 r#"
2477//- /main.rs
2478struct Box<T> {} 2402struct Box<T> {}
2479#[lang = "deref"] 2403#[lang = "deref"]
2480trait Deref { 2404trait Deref {
@@ -2488,18 +2412,16 @@ trait Trait {
2488} 2412}
2489 2413
2490fn test(x: Box<dyn Trait>) { 2414fn test(x: Box<dyn Trait>) {
2491 x.foo()<|>; 2415 x.foo();
2492} 2416} //^ ()
2493"#, 2417"#,
2494 ); 2418 );
2495 assert_eq!(t, "()");
2496} 2419}
2497 2420
2498#[test] 2421#[test]
2499fn string_to_owned() { 2422fn string_to_owned() {
2500 let t = type_at( 2423 check_types(
2501 r#" 2424 r#"
2502//- /main.rs
2503struct String {} 2425struct String {}
2504pub trait ToOwned { 2426pub trait ToOwned {
2505 type Owned; 2427 type Owned;
@@ -2509,11 +2431,10 @@ impl ToOwned for str {
2509 type Owned = String; 2431 type Owned = String;
2510} 2432}
2511fn test() { 2433fn test() {
2512 "foo".to_owned()<|>; 2434 "foo".to_owned();
2513} 2435} //^ String
2514"#, 2436"#,
2515 ); 2437 );
2516 assert_eq!(t, "String");
2517} 2438}
2518 2439
2519#[test] 2440#[test]
@@ -2637,9 +2558,8 @@ fn main() {
2637 2558
2638#[test] 2559#[test]
2639fn nested_assoc() { 2560fn nested_assoc() {
2640 let t = type_at( 2561 check_types(
2641 r#" 2562 r#"
2642//- /main.rs
2643struct Bar; 2563struct Bar;
2644struct Foo; 2564struct Foo;
2645 2565
@@ -2662,11 +2582,10 @@ impl<T:A> B for T {
2662} 2582}
2663 2583
2664fn main() { 2584fn main() {
2665 Bar::foo()<|>; 2585 Bar::foo();
2666} 2586} //^ Foo
2667"#, 2587"#,
2668 ); 2588 );
2669 assert_eq!(t, "Foo");
2670} 2589}
2671 2590
2672#[test] 2591#[test]
@@ -2846,12 +2765,12 @@ fn test() {
2846 2765
2847#[test] 2766#[test]
2848fn integer_range_iterate() { 2767fn integer_range_iterate() {
2849 let t = type_at( 2768 check_types(
2850 r#" 2769 r#"
2851//- /main.rs crate:main deps:core 2770//- /main.rs crate:main deps:core
2852fn test() { 2771fn test() {
2853 for x in 0..100 { x<|>; } 2772 for x in 0..100 { x; }
2854} 2773} //^ i32
2855 2774
2856//- /core.rs crate:core 2775//- /core.rs crate:core
2857pub mod ops { 2776pub mod ops {
@@ -2886,7 +2805,6 @@ impl<A: Step> iter::Iterator for ops::Range<A> {
2886} 2805}
2887"#, 2806"#,
2888 ); 2807 );
2889 assert_eq!(t, "i32");
2890} 2808}
2891 2809
2892#[test] 2810#[test]
diff --git a/crates/ra_ssr/src/lib.rs b/crates/ra_ssr/src/lib.rs
index 8f149e3db..e148f4564 100644
--- a/crates/ra_ssr/src/lib.rs
+++ b/crates/ra_ssr/src/lib.rs
@@ -69,7 +69,8 @@ impl<'db> MatchFinder<'db> {
69 if matches.matches.is_empty() { 69 if matches.matches.is_empty() {
70 None 70 None
71 } else { 71 } else {
72 Some(replacing::matches_to_edit(&matches)) 72 use ra_db::SourceDatabaseExt;
73 Some(replacing::matches_to_edit(&matches, &self.sema.db.file_text(file_id)))
73 } 74 }
74 } 75 }
75 76
diff --git a/crates/ra_ssr/src/matching.rs b/crates/ra_ssr/src/matching.rs
index 85420ed3c..bb87bda43 100644
--- a/crates/ra_ssr/src/matching.rs
+++ b/crates/ra_ssr/src/matching.rs
@@ -585,7 +585,7 @@ mod tests {
585 "1+2" 585 "1+2"
586 ); 586 );
587 587
588 let edit = crate::replacing::matches_to_edit(&matches); 588 let edit = crate::replacing::matches_to_edit(&matches, input);
589 let mut after = input.to_string(); 589 let mut after = input.to_string();
590 edit.apply(&mut after); 590 edit.apply(&mut after);
591 assert_eq!(after, "fn main() { bar(1+2); }"); 591 assert_eq!(after, "fn main() { bar(1+2); }");
diff --git a/crates/ra_ssr/src/parsing.rs b/crates/ra_ssr/src/parsing.rs
index 90c13dbc2..1ae166d19 100644
--- a/crates/ra_ssr/src/parsing.rs
+++ b/crates/ra_ssr/src/parsing.rs
@@ -165,7 +165,7 @@ fn parse_pattern(pattern_str: &str) -> Result<Vec<PatternElement>, SsrError> {
165/// Checks for errors in a rule. e.g. the replace pattern referencing placeholders that the search 165/// Checks for errors in a rule. e.g. the replace pattern referencing placeholders that the search
166/// pattern didn't define. 166/// pattern didn't define.
167fn validate_rule(rule: &SsrRule) -> Result<(), SsrError> { 167fn validate_rule(rule: &SsrRule) -> Result<(), SsrError> {
168 let mut defined_placeholders = std::collections::HashSet::new(); 168 let mut defined_placeholders = FxHashSet::default();
169 for p in &rule.pattern.raw.tokens { 169 for p in &rule.pattern.raw.tokens {
170 if let PatternElement::Placeholder(placeholder) = p { 170 if let PatternElement::Placeholder(placeholder) = p {
171 defined_placeholders.insert(&placeholder.ident); 171 defined_placeholders.insert(&placeholder.ident);
diff --git a/crates/ra_ssr/src/replacing.rs b/crates/ra_ssr/src/replacing.rs
index 5dcde82a2..70ce1c185 100644
--- a/crates/ra_ssr/src/replacing.rs
+++ b/crates/ra_ssr/src/replacing.rs
@@ -10,21 +10,25 @@ use ra_text_edit::TextEdit;
10/// Returns a text edit that will replace each match in `matches` with its corresponding replacement 10/// Returns a text edit that will replace each match in `matches` with its corresponding replacement
11/// template. Placeholders in the template will have been substituted with whatever they matched to 11/// template. Placeholders in the template will have been substituted with whatever they matched to
12/// in the original code. 12/// in the original code.
13pub(crate) fn matches_to_edit(matches: &SsrMatches) -> TextEdit { 13pub(crate) fn matches_to_edit(matches: &SsrMatches, file_src: &str) -> TextEdit {
14 matches_to_edit_at_offset(matches, 0.into()) 14 matches_to_edit_at_offset(matches, file_src, 0.into())
15} 15}
16 16
17fn matches_to_edit_at_offset(matches: &SsrMatches, relative_start: TextSize) -> TextEdit { 17fn matches_to_edit_at_offset(
18 matches: &SsrMatches,
19 file_src: &str,
20 relative_start: TextSize,
21) -> TextEdit {
18 let mut edit_builder = ra_text_edit::TextEditBuilder::default(); 22 let mut edit_builder = ra_text_edit::TextEditBuilder::default();
19 for m in &matches.matches { 23 for m in &matches.matches {
20 edit_builder.replace(m.range.checked_sub(relative_start).unwrap(), render_replace(m)); 24 edit_builder
25 .replace(m.range.checked_sub(relative_start).unwrap(), render_replace(m, file_src));
21 } 26 }
22 edit_builder.finish() 27 edit_builder.finish()
23} 28}
24 29
25fn render_replace(match_info: &Match) -> String { 30fn render_replace(match_info: &Match, file_src: &str) -> String {
26 let mut out = String::new(); 31 let mut out = String::new();
27 let match_start = match_info.matched_node.text_range().start();
28 for r in &match_info.template.tokens { 32 for r in &match_info.template.tokens {
29 match r { 33 match r {
30 PatternElement::Token(t) => out.push_str(t.text.as_str()), 34 PatternElement::Token(t) => out.push_str(t.text.as_str()),
@@ -33,16 +37,13 @@ fn render_replace(match_info: &Match) -> String {
33 match_info.placeholder_values.get(&Var(p.ident.to_string())) 37 match_info.placeholder_values.get(&Var(p.ident.to_string()))
34 { 38 {
35 let range = &placeholder_value.range.range; 39 let range = &placeholder_value.range.range;
36 let mut matched_text = if let Some(node) = &placeholder_value.node { 40 let mut matched_text =
37 node.text().to_string() 41 file_src[usize::from(range.start())..usize::from(range.end())].to_owned();
38 } else { 42 let edit = matches_to_edit_at_offset(
39 let relative_range = range.checked_sub(match_start).unwrap(); 43 &placeholder_value.inner_matches,
40 match_info.matched_node.text().to_string() 44 file_src,
41 [usize::from(relative_range.start())..usize::from(relative_range.end())] 45 range.start(),
42 .to_string() 46 );
43 };
44 let edit =
45 matches_to_edit_at_offset(&placeholder_value.inner_matches, range.start());
46 edit.apply(&mut matched_text); 47 edit.apply(&mut matched_text);
47 out.push_str(&matched_text); 48 out.push_str(&matched_text);
48 } else { 49 } else {
diff --git a/crates/ra_ssr/src/tests.rs b/crates/ra_ssr/src/tests.rs
index 7a3141be8..8be60c293 100644
--- a/crates/ra_ssr/src/tests.rs
+++ b/crates/ra_ssr/src/tests.rs
@@ -606,3 +606,20 @@ fn replace_within_macro_expansion() {
606 fn f() {macro1!(bar(5.x()).o2())}"#, 606 fn f() {macro1!(bar(5.x()).o2())}"#,
607 ) 607 )
608} 608}
609
610#[test]
611fn preserves_whitespace_within_macro_expansion() {
612 assert_ssr_transform(
613 "$a + $b ==>> $b - $a",
614 r#"
615 macro_rules! macro1 {
616 ($a:expr) => {$a}
617 }
618 fn f() {macro1!(1 * 2 + 3 + 4}"#,
619 r#"
620 macro_rules! macro1 {
621 ($a:expr) => {$a}
622 }
623 fn f() {macro1!(4 - 3 - 1 * 2}"#,
624 )
625}
diff --git a/crates/ra_syntax/src/algo.rs b/crates/ra_syntax/src/algo.rs
index f7a885eb3..26b3c813a 100644
--- a/crates/ra_syntax/src/algo.rs
+++ b/crates/ra_syntax/src/algo.rs
@@ -41,6 +41,10 @@ pub fn find_node_at_offset<N: AstNode>(syntax: &SyntaxNode, offset: TextSize) ->
41 ancestors_at_offset(syntax, offset).find_map(N::cast) 41 ancestors_at_offset(syntax, offset).find_map(N::cast)
42} 42}
43 43
44pub fn find_node_at_range<N: AstNode>(syntax: &SyntaxNode, range: TextRange) -> Option<N> {
45 find_covering_element(syntax, range).ancestors().find_map(N::cast)
46}
47
44/// Skip to next non `trivia` token 48/// Skip to next non `trivia` token
45pub fn skip_trivia_token(mut token: SyntaxToken, direction: Direction) -> Option<SyntaxToken> { 49pub fn skip_trivia_token(mut token: SyntaxToken, direction: Direction) -> Option<SyntaxToken> {
46 while token.kind().is_trivia() { 50 while token.kind().is_trivia() {
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index 2f4c29e06..9d09501cd 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -1,7 +1,11 @@
1//! Fully type-check project and print various stats, like the number of type 1//! Fully type-check project and print various stats, like the number of type
2//! errors. 2//! errors.
3 3
4use std::{collections::HashSet, path::Path, time::Instant}; 4use std::{path::Path, time::Instant};
5
6use itertools::Itertools;
7use rand::{seq::SliceRandom, thread_rng};
8use rustc_hash::FxHashSet;
5 9
6use hir::{ 10use hir::{
7 db::{AstDatabase, DefDatabase, HirDatabase}, 11 db::{AstDatabase, DefDatabase, HirDatabase},
@@ -9,10 +13,8 @@ use hir::{
9}; 13};
10use hir_def::FunctionId; 14use hir_def::FunctionId;
11use hir_ty::{Ty, TypeWalk}; 15use hir_ty::{Ty, TypeWalk};
12use itertools::Itertools;
13use ra_db::SourceDatabaseExt; 16use ra_db::SourceDatabaseExt;
14use ra_syntax::AstNode; 17use ra_syntax::AstNode;
15use rand::{seq::SliceRandom, thread_rng};
16use stdx::format_to; 18use stdx::format_to;
17 19
18use crate::cli::{load_cargo::load_cargo, progress_report::ProgressReport, Result, Verbosity}; 20use crate::cli::{load_cargo::load_cargo, progress_report::ProgressReport, Result, Verbosity};
@@ -33,7 +35,7 @@ pub fn analysis_stats(
33 println!("Database loaded {:?}", db_load_time.elapsed()); 35 println!("Database loaded {:?}", db_load_time.elapsed());
34 let analysis_time = Instant::now(); 36 let analysis_time = Instant::now();
35 let mut num_crates = 0; 37 let mut num_crates = 0;
36 let mut visited_modules = HashSet::new(); 38 let mut visited_modules = FxHashSet::default();
37 let mut visit_queue = Vec::new(); 39 let mut visit_queue = Vec::new();
38 40
39 let mut krates = Crate::all(db); 41 let mut krates = Crate::all(db);
diff --git a/crates/rust-analyzer/src/cli/diagnostics.rs b/crates/rust-analyzer/src/cli/diagnostics.rs
index 82b3a8a53..6f3c1c1f9 100644
--- a/crates/rust-analyzer/src/cli/diagnostics.rs
+++ b/crates/rust-analyzer/src/cli/diagnostics.rs
@@ -1,11 +1,14 @@
1//! Analyze all modules in a project for diagnostics. Exits with a non-zero status 1//! Analyze all modules in a project for diagnostics. Exits with a non-zero status
2//! code if any errors are found. 2//! code if any errors are found.
3 3
4use std::path::Path;
5
4use anyhow::anyhow; 6use anyhow::anyhow;
7use rustc_hash::FxHashSet;
8
5use hir::Crate; 9use hir::Crate;
6use ra_db::SourceDatabaseExt; 10use ra_db::SourceDatabaseExt;
7use ra_ide::Severity; 11use ra_ide::Severity;
8use std::{collections::HashSet, path::Path};
9 12
10use crate::cli::{load_cargo::load_cargo, Result}; 13use crate::cli::{load_cargo::load_cargo, Result};
11 14
@@ -20,7 +23,7 @@ pub fn diagnostics(
20 let analysis = host.analysis(); 23 let analysis = host.analysis();
21 24
22 let mut found_error = false; 25 let mut found_error = false;
23 let mut visited_files = HashSet::new(); 26 let mut visited_files = FxHashSet::default();
24 27
25 let mut work = Vec::new(); 28 let mut work = Vec::new();
26 let krates = Crate::all(db); 29 let krates = Crate::all(db);
diff --git a/crates/rust-analyzer/src/diagnostics.rs b/crates/rust-analyzer/src/diagnostics.rs
index 1cf50b677..b46281c98 100644
--- a/crates/rust-analyzer/src/diagnostics.rs
+++ b/crates/rust-analyzer/src/diagnostics.rs
@@ -1,14 +1,14 @@
1//! Book keeping for keeping diagnostics easily in sync with the client. 1//! Book keeping for keeping diagnostics easily in sync with the client.
2pub(crate) mod to_proto; 2pub(crate) mod to_proto;
3 3
4use std::{collections::HashMap, mem, sync::Arc}; 4use std::{mem, sync::Arc};
5 5
6use ra_ide::FileId; 6use ra_ide::FileId;
7use rustc_hash::FxHashSet; 7use rustc_hash::{FxHashMap, FxHashSet};
8 8
9use crate::lsp_ext; 9use crate::lsp_ext;
10 10
11pub(crate) type CheckFixes = Arc<HashMap<FileId, Vec<Fix>>>; 11pub(crate) type CheckFixes = Arc<FxHashMap<FileId, Vec<Fix>>>;
12 12
13#[derive(Debug, Default, Clone)] 13#[derive(Debug, Default, Clone)]
14pub struct DiagnosticsConfig { 14pub struct DiagnosticsConfig {
@@ -18,8 +18,8 @@ pub struct DiagnosticsConfig {
18 18
19#[derive(Debug, Default, Clone)] 19#[derive(Debug, Default, Clone)]
20pub(crate) struct DiagnosticCollection { 20pub(crate) struct DiagnosticCollection {
21 pub(crate) native: HashMap<FileId, Vec<lsp_types::Diagnostic>>, 21 pub(crate) native: FxHashMap<FileId, Vec<lsp_types::Diagnostic>>,
22 pub(crate) check: HashMap<FileId, Vec<lsp_types::Diagnostic>>, 22 pub(crate) check: FxHashMap<FileId, Vec<lsp_types::Diagnostic>>,
23 pub(crate) check_fixes: CheckFixes, 23 pub(crate) check_fixes: CheckFixes,
24 changes: FxHashSet<FileId>, 24 changes: FxHashSet<FileId>,
25} 25}
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 38e3c3324..e35a5e846 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -1283,7 +1283,7 @@ fn should_skip_target(runnable: &Runnable, cargo_spec: Option<&CargoTargetSpec>)
1283 RunnableKind::Bin => { 1283 RunnableKind::Bin => {
1284 // Do not suggest binary run on other target than binary 1284 // Do not suggest binary run on other target than binary
1285 match &cargo_spec { 1285 match &cargo_spec {
1286 Some(spec) => spec.target_kind != TargetKind::Bin, 1286 Some(spec) => !matches!(spec.target_kind, TargetKind::Bin | TargetKind::Example),
1287 None => true, 1287 None => true,
1288 } 1288 }
1289 } 1289 }
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs
index eaeeeb97b..caf847273 100644
--- a/crates/test_utils/src/lib.rs
+++ b/crates/test_utils/src/lib.rs
@@ -16,6 +16,7 @@ use std::{
16}; 16};
17 17
18use serde_json::Value; 18use serde_json::Value;
19use stdx::lines_with_ends;
19use text_size::{TextRange, TextSize}; 20use text_size::{TextRange, TextSize};
20 21
21pub use difference::Changeset as __Changeset; 22pub use difference::Changeset as __Changeset;
@@ -159,6 +160,41 @@ pub fn add_cursor(text: &str, offset: TextSize) -> String {
159 res 160 res
160} 161}
161 162
163/// Extracts `//^ some text` annotations
164pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> {
165 let mut res = Vec::new();
166 let mut prev_line_start: Option<TextSize> = None;
167 let mut line_start: TextSize = 0.into();
168 for line in lines_with_ends(text) {
169 if let Some(idx) = line.find("//^") {
170 let offset = prev_line_start.unwrap() + TextSize::of(&line[..idx + "//".len()]);
171 let data = line[idx + "//^".len()..].trim().to_string();
172 res.push((TextRange::at(offset, 1.into()), data))
173 }
174 prev_line_start = Some(line_start);
175 line_start += TextSize::of(line);
176 }
177 res
178}
179
180#[test]
181fn test_extract_annotations() {
182 let text = stdx::trim_indent(
183 r#"
184fn main() {
185 let x = 92;
186 //^ def
187 z + 1
188} //^ i32
189 "#,
190 );
191 let res = extract_annotations(&text)
192 .into_iter()
193 .map(|(range, ann)| (&text[range], ann))
194 .collect::<Vec<_>>();
195 assert_eq!(res, vec![("x", "def".into()), ("z", "i32".into()),]);
196}
197
162// Comparison functionality borrowed from cargo: 198// Comparison functionality borrowed from cargo:
163 199
164/// Compare a line with an expected pattern. 200/// Compare a line with an expected pattern.
diff --git a/docs/dev/README.md b/docs/dev/README.md
index 11dc5261b..6b6824ded 100644
--- a/docs/dev/README.md
+++ b/docs/dev/README.md
@@ -254,6 +254,11 @@ The default name is a lowercased name of the type: `global_state: GlobalState`.
254Avoid ad-hoc acronyms and contractions, but use the ones that exist consistently (`db`, `ctx`, `acc`). 254Avoid ad-hoc acronyms and contractions, but use the ones that exist consistently (`db`, `ctx`, `acc`).
255The default name for "result of the function" local variable is `res`. 255The default name for "result of the function" local variable is `res`.
256 256
257## Collection types
258
259We prefer `rustc_hash::FxHashMap` and `rustc_hash::FxHashSet` instead of the ones in `std::collections`.
260They use a hasher that's slightly faster and using them consistently will reduce code size by some small amount.
261
257## Preconditions 262## Preconditions
258 263
259Function preconditions should generally be expressed in types and provided by the caller (rather than checked by callee): 264Function preconditions should generally be expressed in types and provided by the caller (rather than checked by callee):
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts
index 8c9d7802f..0e78f5101 100644
--- a/editors/code/src/commands.ts
+++ b/editors/code/src/commands.ts
@@ -158,7 +158,7 @@ export function ssr(ctx: Ctx): Cmd {
158 158
159 const options: vscode.InputBoxOptions = { 159 const options: vscode.InputBoxOptions = {
160 value: "() ==>> ()", 160 value: "() ==>> ()",
161 prompt: "Enter request, for example 'Foo($a:expr) ==> Foo::new($a)' ", 161 prompt: "Enter request, for example 'Foo($a) ==> Foo::new($a)' ",
162 validateInput: async (x: string) => { 162 validateInput: async (x: string) => {
163 try { 163 try {
164 await client.sendRequest(ra.ssr, { query: x, parseOnly: true }); 164 await client.sendRequest(ra.ssr, { query: x, parseOnly: true });
@@ -171,9 +171,15 @@ export function ssr(ctx: Ctx): Cmd {
171 const request = await vscode.window.showInputBox(options); 171 const request = await vscode.window.showInputBox(options);
172 if (!request) return; 172 if (!request) return;
173 173
174 const edit = await client.sendRequest(ra.ssr, { query: request, parseOnly: false }); 174 vscode.window.withProgress({
175 location: vscode.ProgressLocation.Notification,
176 title: "Structured search replace in progress...",
177 cancellable: false,
178 }, async (_progress, _token) => {
179 const edit = await client.sendRequest(ra.ssr, { query: request, parseOnly: false });
175 180
176 await vscode.workspace.applyEdit(client.protocol2CodeConverter.asWorkspaceEdit(edit)); 181 await vscode.workspace.applyEdit(client.protocol2CodeConverter.asWorkspaceEdit(edit));
182 });
177 }; 183 };
178} 184}
179 185