diff options
author | Florian Diebold <[email protected]> | 2019-02-23 11:32:25 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2019-02-23 11:37:29 +0000 |
commit | 6a04d1f292f14744c6b747fa39f1d1c1c20db0ee (patch) | |
tree | 5efa93cfd5c474d70b850ab24cd9b1e90ff79bd0 /crates/ra_hir | |
parent | 3d8a0982a12f3aa4b8c193a841f864b15c3cb66e (diff) |
Fix resolution of associated method calls across crates
I think it'll be better to make the path resolution the number of unresolved
segments, not the first unresolved index; then this error could simply not have
happened. But I'll do that separately.
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/src/nameres.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 9 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 41 |
3 files changed, 53 insertions, 3 deletions
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 8067b8415..ac390c5db 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -642,7 +642,11 @@ impl ItemMap { | |||
642 | log::debug!("resolving {:?} in other crate", path); | 642 | log::debug!("resolving {:?} in other crate", path); |
643 | let item_map = db.item_map(module.krate); | 643 | let item_map = db.item_map(module.krate); |
644 | let (def, s) = item_map.resolve_path(db, *module, &path); | 644 | let (def, s) = item_map.resolve_path(db, *module, &path); |
645 | return ResolvePathResult::with(def, ReachedFixedPoint::Yes, s); | 645 | return ResolvePathResult::with( |
646 | def, | ||
647 | ReachedFixedPoint::Yes, | ||
648 | s.map(|s| s + i), | ||
649 | ); | ||
646 | } | 650 | } |
647 | 651 | ||
648 | match self[module.module_id].items.get(&segment.name) { | 652 | match self[module.module_id].items.get(&segment.name) { |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index ae595c16d..34f9ccd07 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -1170,6 +1170,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1170 | 1170 | ||
1171 | let (def, remaining_index) = resolved.into_inner(); | 1171 | let (def, remaining_index) = resolved.into_inner(); |
1172 | 1172 | ||
1173 | log::debug!( | ||
1174 | "path {:?} resolved to {:?} with remaining index {:?}", | ||
1175 | path, | ||
1176 | def, | ||
1177 | remaining_index | ||
1178 | ); | ||
1179 | |||
1173 | // if the remaining_index is None, we expect the path | 1180 | // if the remaining_index is None, we expect the path |
1174 | // to be fully resolved, in this case we continue with | 1181 | // to be fully resolved, in this case we continue with |
1175 | // the default by attempting to `take_values´ from the resolution. | 1182 | // the default by attempting to `take_values´ from the resolution. |
@@ -1191,6 +1198,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1191 | // if we have more segments to process | 1198 | // if we have more segments to process |
1192 | let segment = &path.segments[remaining_index]; | 1199 | let segment = &path.segments[remaining_index]; |
1193 | 1200 | ||
1201 | log::debug!("looking for path segment: {:?}", segment); | ||
1202 | |||
1194 | // Attempt to find an impl_item for the type which has a name matching | 1203 | // Attempt to find an impl_item for the type which has a name matching |
1195 | // the current segment | 1204 | // the current segment |
1196 | let ty = ty.iterate_impl_items(self.db, |item| match item { | 1205 | let ty = ty.iterate_impl_items(self.db, |item| match item { |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index f04e9109c..77aeca669 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -1,8 +1,8 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | use std::fmt::Write; | 2 | use std::fmt::Write; |
3 | 3 | ||
4 | use ra_db::{SourceDatabase, salsa::Database}; | 4 | use ra_db::{SourceDatabase, salsa::Database, FilePosition}; |
5 | use ra_syntax::ast::{self, AstNode}; | 5 | use ra_syntax::{algo, ast::{self, AstNode}}; |
6 | use test_utils::covers; | 6 | use test_utils::covers; |
7 | 7 | ||
8 | use crate::{ | 8 | use crate::{ |
@@ -946,6 +946,43 @@ fn test<R>(query_response: Canonical<QueryResponse<R>>) { | |||
946 | ); | 946 | ); |
947 | } | 947 | } |
948 | 948 | ||
949 | #[test] | ||
950 | fn cross_crate_associated_method_call() { | ||
951 | let (mut db, pos) = MockDatabase::with_position( | ||
952 | r#" | ||
953 | //- /main.rs | ||
954 | fn test() { | ||
955 | let x = other_crate::foo::S::thing(); | ||
956 | x<|>; | ||
957 | } | ||
958 | |||
959 | //- /lib.rs | ||
960 | mod foo { | ||
961 | struct S; | ||
962 | impl S { | ||
963 | fn thing() -> i128 {} | ||
964 | } | ||
965 | } | ||
966 | "#, | ||
967 | ); | ||
968 | db.set_crate_graph_from_fixture(crate_graph! { | ||
969 | "main": ("/main.rs", ["other_crate"]), | ||
970 | "other_crate": ("/lib.rs", []), | ||
971 | }); | ||
972 | assert_eq!("i128", type_at_pos(&db, pos)); | ||
973 | } | ||
974 | |||
975 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { | ||
976 | let func = source_binder::function_from_position(db, pos).unwrap(); | ||
977 | let body_syntax_mapping = func.body_syntax_mapping(db); | ||
978 | let inference_result = func.infer(db); | ||
979 | let (_, syntax) = func.source(db); | ||
980 | let node = algo::find_node_at_offset::<ast::Expr>(syntax.syntax(), pos.offset).unwrap(); | ||
981 | let expr = body_syntax_mapping.node_expr(node).unwrap(); | ||
982 | let ty = &inference_result[expr]; | ||
983 | ty.to_string() | ||
984 | } | ||
985 | |||
949 | fn infer(content: &str) -> String { | 986 | fn infer(content: &str) -> String { |
950 | let (db, _, file_id) = MockDatabase::with_single_file(content); | 987 | let (db, _, file_id) = MockDatabase::with_single_file(content); |
951 | let source_file = db.parse(file_id); | 988 | let source_file = db.parse(file_id); |