aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-02-23 11:32:25 +0000
committerFlorian Diebold <[email protected]>2019-02-23 11:37:29 +0000
commit6a04d1f292f14744c6b747fa39f1d1c1c20db0ee (patch)
tree5efa93cfd5c474d70b850ab24cd9b1e90ff79bd0 /crates/ra_hir
parent3d8a0982a12f3aa4b8c193a841f864b15c3cb66e (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.rs6
-rw-r--r--crates/ra_hir/src/ty.rs9
-rw-r--r--crates/ra_hir/src/ty/tests.rs41
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 @@
1use std::sync::Arc; 1use std::sync::Arc;
2use std::fmt::Write; 2use std::fmt::Write;
3 3
4use ra_db::{SourceDatabase, salsa::Database}; 4use ra_db::{SourceDatabase, salsa::Database, FilePosition};
5use ra_syntax::ast::{self, AstNode}; 5use ra_syntax::{algo, ast::{self, AstNode}};
6use test_utils::covers; 6use test_utils::covers;
7 7
8use crate::{ 8use crate::{
@@ -946,6 +946,43 @@ fn test<R>(query_response: Canonical<QueryResponse<R>>) {
946 ); 946 );
947} 947}
948 948
949#[test]
950fn cross_crate_associated_method_call() {
951 let (mut db, pos) = MockDatabase::with_position(
952 r#"
953//- /main.rs
954fn test() {
955 let x = other_crate::foo::S::thing();
956 x<|>;
957}
958
959//- /lib.rs
960mod 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
975fn 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
949fn infer(content: &str) -> String { 986fn 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);