aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def')
-rw-r--r--crates/hir_def/src/body/lower.rs21
-rw-r--r--crates/hir_def/src/nameres/collector.rs25
-rw-r--r--crates/hir_def/src/nameres/mod_resolution.rs23
-rw-r--r--crates/hir_def/src/nameres/tests.rs5
-rw-r--r--crates/hir_def/src/nameres/tests/mod_resolution.rs44
5 files changed, 88 insertions, 30 deletions
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 1deaa90f2..cd7958746 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -953,18 +953,19 @@ impl From<ast::BinOp> for BinaryOp {
953impl From<ast::LiteralKind> for Literal { 953impl From<ast::LiteralKind> for Literal {
954 fn from(ast_lit_kind: ast::LiteralKind) -> Self { 954 fn from(ast_lit_kind: ast::LiteralKind) -> Self {
955 match ast_lit_kind { 955 match ast_lit_kind {
956 LiteralKind::IntNumber { suffix } => { 956 LiteralKind::IntNumber(lit) => {
957 let known_name = suffix.and_then(|it| BuiltinInt::from_suffix(&it)); 957 if let Some(float_suffix) = lit.suffix().and_then(BuiltinFloat::from_suffix) {
958 958 return Literal::Float(Default::default(), Some(float_suffix));
959 Literal::Int(Default::default(), known_name) 959 }
960 let ty = lit.suffix().and_then(|it| BuiltinInt::from_suffix(&it));
961 Literal::Int(Default::default(), ty)
960 } 962 }
961 LiteralKind::FloatNumber { suffix } => { 963 LiteralKind::FloatNumber(lit) => {
962 let known_name = suffix.and_then(|it| BuiltinFloat::from_suffix(&it)); 964 let ty = lit.suffix().and_then(|it| BuiltinFloat::from_suffix(&it));
963 965 Literal::Float(Default::default(), ty)
964 Literal::Float(Default::default(), known_name)
965 } 966 }
966 LiteralKind::ByteString => Literal::ByteString(Default::default()), 967 LiteralKind::ByteString(_) => Literal::ByteString(Default::default()),
967 LiteralKind::String => Literal::String(Default::default()), 968 LiteralKind::String(_) => Literal::String(Default::default()),
968 LiteralKind::Byte => Literal::Int(Default::default(), Some(BuiltinInt::U8)), 969 LiteralKind::Byte => Literal::Int(Default::default(), Some(BuiltinInt::U8)),
969 LiteralKind::Bool(val) => Literal::Bool(val), 970 LiteralKind::Bool(val) => Literal::Bool(val),
970 LiteralKind::Char => Literal::Char(Default::default()), 971 LiteralKind::Char => Literal::Char(Default::default()),
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 59b6644c3..386287518 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -1116,17 +1116,20 @@ impl ModCollector<'_, '_> {
1116 &self.item_tree[module.visibility], 1116 &self.item_tree[module.visibility],
1117 ); 1117 );
1118 1118
1119 ModCollector { 1119 if let Some(mod_dir) = self.mod_dir.descend_into_definition(&module.name, path_attr)
1120 def_collector: &mut *self.def_collector, 1120 {
1121 macro_depth: self.macro_depth, 1121 ModCollector {
1122 module_id, 1122 def_collector: &mut *self.def_collector,
1123 file_id: self.file_id, 1123 macro_depth: self.macro_depth,
1124 item_tree: self.item_tree, 1124 module_id,
1125 mod_dir: self.mod_dir.descend_into_definition(&module.name, path_attr), 1125 file_id: self.file_id,
1126 } 1126 item_tree: self.item_tree,
1127 .collect(&*items); 1127 mod_dir,
1128 if is_macro_use { 1128 }
1129 self.import_all_legacy_macros(module_id); 1129 .collect(&*items);
1130 if is_macro_use {
1131 self.import_all_legacy_macros(module_id);
1132 }
1130 } 1133 }
1131 } 1134 }
1132 // out of line module, resolve, parse and recurse 1135 // out of line module, resolve, parse and recurse
diff --git a/crates/hir_def/src/nameres/mod_resolution.rs b/crates/hir_def/src/nameres/mod_resolution.rs
index e8389b484..c0c789cae 100644
--- a/crates/hir_def/src/nameres/mod_resolution.rs
+++ b/crates/hir_def/src/nameres/mod_resolution.rs
@@ -2,9 +2,12 @@
2use base_db::FileId; 2use base_db::FileId;
3use hir_expand::name::Name; 3use hir_expand::name::Name;
4use syntax::SmolStr; 4use syntax::SmolStr;
5use test_utils::mark;
5 6
6use crate::{db::DefDatabase, HirFileId}; 7use crate::{db::DefDatabase, HirFileId};
7 8
9const MOD_DEPTH_LIMIT: u32 = 32;
10
8#[derive(Clone, Debug)] 11#[derive(Clone, Debug)]
9pub(super) struct ModDir { 12pub(super) struct ModDir {
10 /// `` for `mod.rs`, `lib.rs` 13 /// `` for `mod.rs`, `lib.rs`
@@ -14,18 +17,28 @@ pub(super) struct ModDir {
14 dir_path: DirPath, 17 dir_path: DirPath,
15 /// inside `./foo.rs`, mods with `#[path]` should *not* be relative to `./foo/` 18 /// inside `./foo.rs`, mods with `#[path]` should *not* be relative to `./foo/`
16 root_non_dir_owner: bool, 19 root_non_dir_owner: bool,
20 depth: u32,
17} 21}
18 22
19impl ModDir { 23impl ModDir {
20 pub(super) fn root() -> ModDir { 24 pub(super) fn root() -> ModDir {
21 ModDir { dir_path: DirPath::empty(), root_non_dir_owner: false } 25 ModDir { dir_path: DirPath::empty(), root_non_dir_owner: false, depth: 0 }
26 }
27 fn child(&self, dir_path: DirPath, root_non_dir_owner: bool) -> Option<ModDir> {
28 let depth = self.depth + 1;
29 if depth > MOD_DEPTH_LIMIT {
30 log::error!("MOD_DEPTH_LIMIT exceeded");
31 mark::hit!(circular_mods);
32 return None;
33 }
34 Some(ModDir { dir_path, root_non_dir_owner, depth })
22 } 35 }
23 36
24 pub(super) fn descend_into_definition( 37 pub(super) fn descend_into_definition(
25 &self, 38 &self,
26 name: &Name, 39 name: &Name,
27 attr_path: Option<&SmolStr>, 40 attr_path: Option<&SmolStr>,
28 ) -> ModDir { 41 ) -> Option<ModDir> {
29 let path = match attr_path.map(|it| it.as_str()) { 42 let path = match attr_path.map(|it| it.as_str()) {
30 None => { 43 None => {
31 let mut path = self.dir_path.clone(); 44 let mut path = self.dir_path.clone();
@@ -40,7 +53,7 @@ impl ModDir {
40 DirPath::new(path) 53 DirPath::new(path)
41 } 54 }
42 }; 55 };
43 ModDir { dir_path: path, root_non_dir_owner: false } 56 self.child(path, false)
44 } 57 }
45 58
46 pub(super) fn resolve_declaration( 59 pub(super) fn resolve_declaration(
@@ -72,7 +85,9 @@ impl ModDir {
72 } else { 85 } else {
73 (DirPath::new(format!("{}/", name)), true) 86 (DirPath::new(format!("{}/", name)), true)
74 }; 87 };
75 return Ok((file_id, is_mod_rs, ModDir { dir_path, root_non_dir_owner })); 88 if let Some(mod_dir) = self.child(dir_path, root_non_dir_owner) {
89 return Ok((file_id, is_mod_rs, mod_dir));
90 }
76 } 91 }
77 } 92 }
78 Err(candidate_files.remove(0)) 93 Err(candidate_files.remove(0))
diff --git a/crates/hir_def/src/nameres/tests.rs b/crates/hir_def/src/nameres/tests.rs
index 9c19bf572..a4d1fb8f3 100644
--- a/crates/hir_def/src/nameres/tests.rs
+++ b/crates/hir_def/src/nameres/tests.rs
@@ -20,9 +20,8 @@ fn compute_crate_def_map(fixture: &str) -> Arc<CrateDefMap> {
20} 20}
21 21
22fn check(ra_fixture: &str, expect: Expect) { 22fn check(ra_fixture: &str, expect: Expect) {
23 let db = TestDB::with_files(ra_fixture); 23 let def_map = compute_crate_def_map(ra_fixture);
24 let krate = db.crate_graph().iter().next().unwrap(); 24 let actual = def_map.dump();
25 let actual = db.crate_def_map(krate).dump();
26 expect.assert_eq(&actual); 25 expect.assert_eq(&actual);
27} 26}
28 27
diff --git a/crates/hir_def/src/nameres/tests/mod_resolution.rs b/crates/hir_def/src/nameres/tests/mod_resolution.rs
index f93337a6e..ba295fd9e 100644
--- a/crates/hir_def/src/nameres/tests/mod_resolution.rs
+++ b/crates/hir_def/src/nameres/tests/mod_resolution.rs
@@ -323,13 +323,26 @@ pub struct Baz;
323fn module_resolution_relative_path_outside_root() { 323fn module_resolution_relative_path_outside_root() {
324 check( 324 check(
325 r#" 325 r#"
326//- /main.rs 326//- /a/b/c/d/e/main.rs crate:main
327#[path="../../../../../outside.rs"] 327#[path="../../../../../outside.rs"]
328mod foo; 328mod foo;
329
330//- /outside.rs
331mod bar;
332
333//- /bar.rs
334pub struct Baz;
329"#, 335"#,
330 expect![[r#" 336 expect![[r#"
331 crate 337 crate
332 "#]], 338 foo: t
339
340 crate::foo
341 bar: t
342
343 crate::foo::bar
344 Baz: t v
345"#]],
333 ); 346 );
334} 347}
335 348
@@ -758,3 +771,30 @@ struct X;
758 "#]], 771 "#]],
759 ); 772 );
760} 773}
774
775#[test]
776fn circular_mods() {
777 mark::check!(circular_mods);
778 compute_crate_def_map(
779 r#"
780//- /lib.rs
781mod foo;
782//- /foo.rs
783#[path = "./foo.rs"]
784mod foo;
785"#,
786 );
787
788 compute_crate_def_map(
789 r#"
790//- /lib.rs
791mod foo;
792//- /foo.rs
793#[path = "./bar.rs"]
794mod bar;
795//- /bar.rs
796#[path = "./foo.rs"]
797mod foo;
798"#,
799 );
800}