diff options
Diffstat (limited to 'crates/hir_def')
28 files changed, 414 insertions, 707 deletions
diff --git a/crates/hir_def/Cargo.toml b/crates/hir_def/Cargo.toml index 43324d8d9..bb86f6a73 100644 --- a/crates/hir_def/Cargo.toml +++ b/crates/hir_def/Cargo.toml | |||
@@ -10,7 +10,7 @@ edition = "2018" | |||
10 | doctest = false | 10 | doctest = false |
11 | 11 | ||
12 | [dependencies] | 12 | [dependencies] |
13 | cov-mark = { version = "1.1", features = ["thread-local"] } | 13 | cov-mark = "2.0.0-pre.1" |
14 | dashmap = { version = "4.0.2", features = ["raw-api"] } | 14 | dashmap = { version = "4.0.2", features = ["raw-api"] } |
15 | log = "0.4.8" | 15 | log = "0.4.8" |
16 | once_cell = "1.3.1" | 16 | once_cell = "1.3.1" |
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index 385ba8c80..d07adb084 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -36,6 +36,10 @@ use crate::{ | |||
36 | pub struct Documentation(String); | 36 | pub struct Documentation(String); |
37 | 37 | ||
38 | impl Documentation { | 38 | impl Documentation { |
39 | pub fn new(s: String) -> Self { | ||
40 | Documentation(s) | ||
41 | } | ||
42 | |||
39 | pub fn as_str(&self) -> &str { | 43 | pub fn as_str(&self) -> &str { |
40 | &self.0 | 44 | &self.0 |
41 | } | 45 | } |
@@ -102,7 +106,9 @@ impl RawAttrs { | |||
102 | ) -> Self { | 106 | ) -> Self { |
103 | let entries = collect_attrs(owner) | 107 | let entries = collect_attrs(owner) |
104 | .flat_map(|(id, attr)| match attr { | 108 | .flat_map(|(id, attr)| match attr { |
105 | Either::Left(attr) => Attr::from_src(db, attr, hygiene, id), | 109 | Either::Left(attr) => { |
110 | attr.meta().and_then(|meta| Attr::from_src(db, meta, hygiene, id)) | ||
111 | } | ||
106 | Either::Right(comment) => comment.doc_comment().map(|doc| Attr { | 112 | Either::Right(comment) => comment.doc_comment().map(|doc| Attr { |
107 | id, | 113 | id, |
108 | input: Some(Interned::new(AttrInput::Literal(SmolStr::new(doc)))), | 114 | input: Some(Interned::new(AttrInput::Literal(SmolStr::new(doc)))), |
@@ -168,10 +174,9 @@ impl RawAttrs { | |||
168 | let index = attr.id; | 174 | let index = attr.id; |
169 | let attrs = parts.filter(|a| !a.is_empty()).filter_map(|attr| { | 175 | let attrs = parts.filter(|a| !a.is_empty()).filter_map(|attr| { |
170 | let tree = Subtree { delimiter: None, token_trees: attr.to_vec() }; | 176 | let tree = Subtree { delimiter: None, token_trees: attr.to_vec() }; |
171 | let attr = ast::Attr::parse(&format!("#[{}]", tree)).ok()?; | ||
172 | // FIXME hygiene | 177 | // FIXME hygiene |
173 | let hygiene = Hygiene::new_unhygienic(); | 178 | let hygiene = Hygiene::new_unhygienic(); |
174 | Attr::from_src(db, attr, &hygiene, index) | 179 | Attr::from_tt(db, &tree, &hygiene, index) |
175 | }); | 180 | }); |
176 | 181 | ||
177 | let cfg_options = &crate_graph[krate].cfg_options; | 182 | let cfg_options = &crate_graph[krate].cfg_options; |
@@ -578,13 +583,13 @@ impl AttrSourceMap { | |||
578 | .get(id.ast_index as usize) | 583 | .get(id.ast_index as usize) |
579 | .unwrap_or_else(|| panic!("cannot find doc comment at index {:?}", id)) | 584 | .unwrap_or_else(|| panic!("cannot find doc comment at index {:?}", id)) |
580 | .clone() | 585 | .clone() |
581 | .map(|attr| Either::Right(attr)) | 586 | .map(Either::Right) |
582 | } else { | 587 | } else { |
583 | self.attrs | 588 | self.attrs |
584 | .get(id.ast_index as usize) | 589 | .get(id.ast_index as usize) |
585 | .unwrap_or_else(|| panic!("cannot find `Attr` at index {:?}", id)) | 590 | .unwrap_or_else(|| panic!("cannot find `Attr` at index {:?}", id)) |
586 | .clone() | 591 | .clone() |
587 | .map(|attr| Either::Left(attr)) | 592 | .map(Either::Left) |
588 | } | 593 | } |
589 | } | 594 | } |
590 | } | 595 | } |
@@ -601,7 +606,7 @@ pub struct DocsRangeMap { | |||
601 | impl DocsRangeMap { | 606 | impl DocsRangeMap { |
602 | pub fn map(&self, range: TextRange) -> Option<InFile<TextRange>> { | 607 | pub fn map(&self, range: TextRange) -> Option<InFile<TextRange>> { |
603 | let found = self.mapping.binary_search_by(|(probe, ..)| probe.ordering(range)).ok()?; | 608 | let found = self.mapping.binary_search_by(|(probe, ..)| probe.ordering(range)).ok()?; |
604 | let (line_docs_range, idx, original_line_src_range) = self.mapping[found].clone(); | 609 | let (line_docs_range, idx, original_line_src_range) = self.mapping[found]; |
605 | if !line_docs_range.contains_range(range) { | 610 | if !line_docs_range.contains_range(range) { |
606 | return None; | 611 | return None; |
607 | } | 612 | } |
@@ -660,7 +665,7 @@ impl fmt::Display for AttrInput { | |||
660 | impl Attr { | 665 | impl Attr { |
661 | fn from_src( | 666 | fn from_src( |
662 | db: &dyn DefDatabase, | 667 | db: &dyn DefDatabase, |
663 | ast: ast::Attr, | 668 | ast: ast::Meta, |
664 | hygiene: &Hygiene, | 669 | hygiene: &Hygiene, |
665 | id: AttrId, | 670 | id: AttrId, |
666 | ) -> Option<Attr> { | 671 | ) -> Option<Attr> { |
@@ -679,6 +684,19 @@ impl Attr { | |||
679 | Some(Attr { id, path, input }) | 684 | Some(Attr { id, path, input }) |
680 | } | 685 | } |
681 | 686 | ||
687 | fn from_tt( | ||
688 | db: &dyn DefDatabase, | ||
689 | tt: &tt::Subtree, | ||
690 | hygiene: &Hygiene, | ||
691 | id: AttrId, | ||
692 | ) -> Option<Attr> { | ||
693 | let (parse, _) = | ||
694 | mbe::token_tree_to_syntax_node(tt, hir_expand::FragmentKind::MetaItem).ok()?; | ||
695 | let ast = ast::Meta::cast(parse.syntax_node())?; | ||
696 | |||
697 | Self::from_src(db, ast, hygiene, id) | ||
698 | } | ||
699 | |||
682 | /// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths | 700 | /// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths |
683 | /// to derive macros. | 701 | /// to derive macros. |
684 | /// | 702 | /// |
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index da1fdac33..bed4c4994 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -1000,18 +1000,18 @@ impl From<ast::LiteralKind> for Literal { | |||
1000 | // FIXME: these should have actual values filled in, but unsure on perf impact | 1000 | // FIXME: these should have actual values filled in, but unsure on perf impact |
1001 | LiteralKind::IntNumber(lit) => { | 1001 | LiteralKind::IntNumber(lit) => { |
1002 | if let builtin @ Some(_) = lit.suffix().and_then(BuiltinFloat::from_suffix) { | 1002 | if let builtin @ Some(_) = lit.suffix().and_then(BuiltinFloat::from_suffix) { |
1003 | return Literal::Float(Default::default(), builtin); | 1003 | Literal::Float(Default::default(), builtin) |
1004 | } else if let builtin @ Some(_) = | 1004 | } else if let builtin @ Some(_) = |
1005 | lit.suffix().and_then(|it| BuiltinInt::from_suffix(&it)) | 1005 | lit.suffix().and_then(|it| BuiltinInt::from_suffix(it)) |
1006 | { | 1006 | { |
1007 | Literal::Int(lit.value().unwrap_or(0) as i128, builtin) | 1007 | Literal::Int(lit.value().unwrap_or(0) as i128, builtin) |
1008 | } else { | 1008 | } else { |
1009 | let builtin = lit.suffix().and_then(|it| BuiltinUint::from_suffix(&it)); | 1009 | let builtin = lit.suffix().and_then(|it| BuiltinUint::from_suffix(it)); |
1010 | Literal::Uint(lit.value().unwrap_or(0), builtin) | 1010 | Literal::Uint(lit.value().unwrap_or(0), builtin) |
1011 | } | 1011 | } |
1012 | } | 1012 | } |
1013 | LiteralKind::FloatNumber(lit) => { | 1013 | LiteralKind::FloatNumber(lit) => { |
1014 | let ty = lit.suffix().and_then(|it| BuiltinFloat::from_suffix(&it)); | 1014 | let ty = lit.suffix().and_then(|it| BuiltinFloat::from_suffix(it)); |
1015 | Literal::Float(Default::default(), ty) | 1015 | Literal::Float(Default::default(), ty) |
1016 | } | 1016 | } |
1017 | LiteralKind::ByteString(bs) => { | 1017 | LiteralKind::ByteString(bs) => { |
diff --git a/crates/hir_def/src/body/scope.rs b/crates/hir_def/src/body/scope.rs index 6764de3a7..58a1fc81c 100644 --- a/crates/hir_def/src/body/scope.rs +++ b/crates/hir_def/src/body/scope.rs | |||
@@ -198,7 +198,7 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope | |||
198 | } | 198 | } |
199 | Expr::Lambda { args, body: body_expr, .. } => { | 199 | Expr::Lambda { args, body: body_expr, .. } => { |
200 | let scope = scopes.new_scope(scope); | 200 | let scope = scopes.new_scope(scope); |
201 | scopes.add_params_bindings(body, scope, &args); | 201 | scopes.add_params_bindings(body, scope, args); |
202 | compute_expr_scopes(*body_expr, body, scopes, scope); | 202 | compute_expr_scopes(*body_expr, body, scopes, scope); |
203 | } | 203 | } |
204 | Expr::Match { expr, arms } => { | 204 | Expr::Match { expr, arms } => { |
diff --git a/crates/hir_def/src/body/tests.rs b/crates/hir_def/src/body/tests.rs index d4fae05a6..27d837d47 100644 --- a/crates/hir_def/src/body/tests.rs +++ b/crates/hir_def/src/body/tests.rs | |||
@@ -3,7 +3,7 @@ mod block; | |||
3 | use base_db::{fixture::WithFixture, SourceDatabase}; | 3 | use base_db::{fixture::WithFixture, SourceDatabase}; |
4 | use expect_test::Expect; | 4 | use expect_test::Expect; |
5 | 5 | ||
6 | use crate::{test_db::TestDB, ModuleDefId}; | 6 | use crate::ModuleDefId; |
7 | 7 | ||
8 | use super::*; | 8 | use super::*; |
9 | 9 | ||
@@ -28,11 +28,6 @@ fn lower(ra_fixture: &str) -> Arc<Body> { | |||
28 | db.body(fn_def.unwrap().into()) | 28 | db.body(fn_def.unwrap().into()) |
29 | } | 29 | } |
30 | 30 | ||
31 | fn check_diagnostics(ra_fixture: &str) { | ||
32 | let db: TestDB = TestDB::with_files(ra_fixture); | ||
33 | db.check_diagnostics(); | ||
34 | } | ||
35 | |||
36 | fn block_def_map_at(ra_fixture: &str) -> String { | 31 | fn block_def_map_at(ra_fixture: &str) -> String { |
37 | let (db, position) = crate::test_db::TestDB::with_position(ra_fixture); | 32 | let (db, position) = crate::test_db::TestDB::with_position(ra_fixture); |
38 | 33 | ||
@@ -57,7 +52,7 @@ fn check_at(ra_fixture: &str, expect: Expect) { | |||
57 | fn your_stack_belongs_to_me() { | 52 | fn your_stack_belongs_to_me() { |
58 | cov_mark::check!(your_stack_belongs_to_me); | 53 | cov_mark::check!(your_stack_belongs_to_me); |
59 | lower( | 54 | lower( |
60 | " | 55 | r#" |
61 | macro_rules! n_nuple { | 56 | macro_rules! n_nuple { |
62 | ($e:tt) => (); | 57 | ($e:tt) => (); |
63 | ($($rest:tt)*) => {{ | 58 | ($($rest:tt)*) => {{ |
@@ -65,7 +60,7 @@ macro_rules! n_nuple { | |||
65 | }}; | 60 | }}; |
66 | } | 61 | } |
67 | fn main() { n_nuple!(1,2,3); } | 62 | fn main() { n_nuple!(1,2,3); } |
68 | ", | 63 | "#, |
69 | ); | 64 | ); |
70 | } | 65 | } |
71 | 66 | ||
@@ -73,7 +68,7 @@ fn main() { n_nuple!(1,2,3); } | |||
73 | fn macro_resolve() { | 68 | fn macro_resolve() { |
74 | // Regression test for a path resolution bug introduced with inner item handling. | 69 | // Regression test for a path resolution bug introduced with inner item handling. |
75 | lower( | 70 | lower( |
76 | r" | 71 | r#" |
77 | macro_rules! vec { | 72 | macro_rules! vec { |
78 | () => { () }; | 73 | () => { () }; |
79 | ($elem:expr; $n:expr) => { () }; | 74 | ($elem:expr; $n:expr) => { () }; |
@@ -84,140 +79,6 @@ mod m { | |||
84 | let _ = vec![FileSet::default(); self.len()]; | 79 | let _ = vec![FileSet::default(); self.len()]; |
85 | } | 80 | } |
86 | } | 81 | } |
87 | ", | 82 | "#, |
88 | ); | ||
89 | } | ||
90 | |||
91 | #[test] | ||
92 | fn cfg_diagnostics() { | ||
93 | check_diagnostics( | ||
94 | r" | ||
95 | fn f() { | ||
96 | // The three g̶e̶n̶d̶e̶r̶s̶ statements: | ||
97 | |||
98 | #[cfg(a)] fn f() {} // Item statement | ||
99 | //^^^^^^^^^^^^^^^^^^^ InactiveCode | ||
100 | #[cfg(a)] {} // Expression statement | ||
101 | //^^^^^^^^^^^^ InactiveCode | ||
102 | #[cfg(a)] let x = 0; // let statement | ||
103 | //^^^^^^^^^^^^^^^^^^^^ InactiveCode | ||
104 | |||
105 | abc(#[cfg(a)] 0); | ||
106 | //^^^^^^^^^^^ InactiveCode | ||
107 | let x = Struct { | ||
108 | #[cfg(a)] f: 0, | ||
109 | //^^^^^^^^^^^^^^ InactiveCode | ||
110 | }; | ||
111 | match () { | ||
112 | () => (), | ||
113 | #[cfg(a)] () => (), | ||
114 | //^^^^^^^^^^^^^^^^^^ InactiveCode | ||
115 | } | ||
116 | |||
117 | #[cfg(a)] 0 // Trailing expression of block | ||
118 | //^^^^^^^^^^^ InactiveCode | ||
119 | } | ||
120 | ", | ||
121 | ); | ||
122 | } | ||
123 | |||
124 | #[test] | ||
125 | fn macro_diag_builtin() { | ||
126 | check_diagnostics( | ||
127 | r#" | ||
128 | #[rustc_builtin_macro] | ||
129 | macro_rules! env {} | ||
130 | |||
131 | #[rustc_builtin_macro] | ||
132 | macro_rules! include {} | ||
133 | |||
134 | #[rustc_builtin_macro] | ||
135 | macro_rules! compile_error {} | ||
136 | |||
137 | #[rustc_builtin_macro] | ||
138 | macro_rules! format_args { | ||
139 | () => {} | ||
140 | } | ||
141 | |||
142 | fn f() { | ||
143 | // Test a handful of built-in (eager) macros: | ||
144 | |||
145 | include!(invalid); | ||
146 | //^^^^^^^^^^^^^^^^^ could not convert tokens | ||
147 | include!("does not exist"); | ||
148 | //^^^^^^^^^^^^^^^^^^^^^^^^^^ failed to load file `does not exist` | ||
149 | |||
150 | env!(invalid); | ||
151 | //^^^^^^^^^^^^^ could not convert tokens | ||
152 | |||
153 | env!("OUT_DIR"); | ||
154 | //^^^^^^^^^^^^^^^ `OUT_DIR` not set, enable "run build scripts" to fix | ||
155 | |||
156 | compile_error!("compile_error works"); | ||
157 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ compile_error works | ||
158 | |||
159 | // Lazy: | ||
160 | |||
161 | format_args!(); | ||
162 | //^^^^^^^^^^^^^^ no rule matches input tokens | ||
163 | } | ||
164 | "#, | ||
165 | ); | ||
166 | } | ||
167 | |||
168 | #[test] | ||
169 | fn macro_rules_diag() { | ||
170 | check_diagnostics( | ||
171 | r#" | ||
172 | macro_rules! m { | ||
173 | () => {}; | ||
174 | } | ||
175 | fn f() { | ||
176 | m!(); | ||
177 | |||
178 | m!(hi); | ||
179 | //^^^^^^ leftover tokens | ||
180 | } | ||
181 | "#, | ||
182 | ); | 83 | ); |
183 | } | 84 | } |
184 | |||
185 | #[test] | ||
186 | fn unresolved_macro_diag() { | ||
187 | check_diagnostics( | ||
188 | r#" | ||
189 | fn f() { | ||
190 | m!(); | ||
191 | //^^^^ UnresolvedMacroCall | ||
192 | } | ||
193 | "#, | ||
194 | ); | ||
195 | } | ||
196 | |||
197 | #[test] | ||
198 | fn dollar_crate_in_builtin_macro() { | ||
199 | check_diagnostics( | ||
200 | r#" | ||
201 | #[macro_export] | ||
202 | #[rustc_builtin_macro] | ||
203 | macro_rules! format_args {} | ||
204 | |||
205 | #[macro_export] | ||
206 | macro_rules! arg { | ||
207 | () => {} | ||
208 | } | ||
209 | |||
210 | #[macro_export] | ||
211 | macro_rules! outer { | ||
212 | () => { | ||
213 | $crate::format_args!( "", $crate::arg!(1) ) | ||
214 | }; | ||
215 | } | ||
216 | |||
217 | fn f() { | ||
218 | outer!(); | ||
219 | //^^^^^^^^ leftover tokens | ||
220 | } | ||
221 | "#, | ||
222 | ) | ||
223 | } | ||
diff --git a/crates/hir_def/src/body/tests/block.rs b/crates/hir_def/src/body/tests/block.rs index bc3d0f138..15c10d053 100644 --- a/crates/hir_def/src/body/tests/block.rs +++ b/crates/hir_def/src/body/tests/block.rs | |||
@@ -163,14 +163,14 @@ fn legacy_macro_items() { | |||
163 | // correctly. | 163 | // correctly. |
164 | check_at( | 164 | check_at( |
165 | r#" | 165 | r#" |
166 | macro_rules! hit { | 166 | macro_rules! mark { |
167 | () => { | 167 | () => { |
168 | struct Hit {} | 168 | struct Hit {} |
169 | } | 169 | } |
170 | } | 170 | } |
171 | 171 | ||
172 | fn f() { | 172 | fn f() { |
173 | hit!(); | 173 | mark!(); |
174 | $0 | 174 | $0 |
175 | } | 175 | } |
176 | "#, | 176 | "#, |
@@ -193,20 +193,20 @@ use core::cov_mark; | |||
193 | 193 | ||
194 | fn f() { | 194 | fn f() { |
195 | fn nested() { | 195 | fn nested() { |
196 | cov_mark::hit!(Hit); | 196 | cov_mark::mark!(Hit); |
197 | $0 | 197 | $0 |
198 | } | 198 | } |
199 | } | 199 | } |
200 | //- /core.rs crate:core | 200 | //- /core.rs crate:core |
201 | pub mod cov_mark { | 201 | pub mod cov_mark { |
202 | #[macro_export] | 202 | #[macro_export] |
203 | macro_rules! _hit { | 203 | macro_rules! _mark { |
204 | ($name:ident) => { | 204 | ($name:ident) => { |
205 | struct $name {} | 205 | struct $name {} |
206 | } | 206 | } |
207 | } | 207 | } |
208 | 208 | ||
209 | pub use crate::_hit as hit; | 209 | pub use crate::_mark as mark; |
210 | } | 210 | } |
211 | "#, | 211 | "#, |
212 | expect![[r#" | 212 | expect![[r#" |
diff --git a/crates/hir_def/src/builtin_attr.rs b/crates/hir_def/src/builtin_attr.rs index d5d7f0f47..39c7f84f7 100644 --- a/crates/hir_def/src/builtin_attr.rs +++ b/crates/hir_def/src/builtin_attr.rs | |||
@@ -2,7 +2,7 @@ | |||
2 | //! | 2 | //! |
3 | //! The actual definitions were copied from rustc's `compiler/rustc_feature/src/builtin_attrs.rs`. | 3 | //! The actual definitions were copied from rustc's `compiler/rustc_feature/src/builtin_attrs.rs`. |
4 | //! | 4 | //! |
5 | //! It was last synchronized with upstream commit 2225ee1b62ff089917434aefd9b2bf509cfa087f. | 5 | //! It was last synchronized with upstream commit 835150e70288535bc57bb624792229b9dc94991d. |
6 | //! | 6 | //! |
7 | //! The macros were adjusted to only expand to the attribute name, since that is all we need to do | 7 | //! The macros were adjusted to only expand to the attribute name, since that is all we need to do |
8 | //! name resolution, and `BUILTIN_ATTRIBUTES` is almost entirely unchanged from the original, to | 8 | //! name resolution, and `BUILTIN_ATTRIBUTES` is almost entirely unchanged from the original, to |
@@ -58,7 +58,6 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ | |||
58 | ungated!(reexport_test_harness_main, Normal, template!(NameValueStr: "name")), | 58 | ungated!(reexport_test_harness_main, Normal, template!(NameValueStr: "name")), |
59 | 59 | ||
60 | // Macros: | 60 | // Macros: |
61 | ungated!(derive, Normal, template!(List: "Trait1, Trait2, ...")), | ||
62 | ungated!(automatically_derived, Normal, template!(Word)), | 61 | ungated!(automatically_derived, Normal, template!(Word)), |
63 | // FIXME(#14407) | 62 | // FIXME(#14407) |
64 | ungated!(macro_use, Normal, template!(Word, List: "name1, name2, ...")), | 63 | ungated!(macro_use, Normal, template!(Word, List: "name1, name2, ...")), |
@@ -98,8 +97,8 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ | |||
98 | template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...""#), | 97 | template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...""#), |
99 | ), | 98 | ), |
100 | ungated!(link_name, AssumedUsed, template!(NameValueStr: "name")), | 99 | ungated!(link_name, AssumedUsed, template!(NameValueStr: "name")), |
101 | ungated!(no_link, Normal, template!(Word)), | 100 | ungated!(no_link, AssumedUsed, template!(Word)), |
102 | ungated!(repr, Normal, template!(List: "C")), | 101 | ungated!(repr, AssumedUsed, template!(List: "C")), |
103 | ungated!(export_name, AssumedUsed, template!(NameValueStr: "name")), | 102 | ungated!(export_name, AssumedUsed, template!(NameValueStr: "name")), |
104 | ungated!(link_section, AssumedUsed, template!(NameValueStr: "name")), | 103 | ungated!(link_section, AssumedUsed, template!(NameValueStr: "name")), |
105 | ungated!(no_mangle, AssumedUsed, template!(Word)), | 104 | ungated!(no_mangle, AssumedUsed, template!(Word)), |
@@ -112,6 +111,10 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ | |||
112 | const_eval_limit, CrateLevel, template!(NameValueStr: "N"), const_eval_limit, | 111 | const_eval_limit, CrateLevel, template!(NameValueStr: "N"), const_eval_limit, |
113 | experimental!(const_eval_limit) | 112 | experimental!(const_eval_limit) |
114 | ), | 113 | ), |
114 | gated!( | ||
115 | move_size_limit, CrateLevel, template!(NameValueStr: "N"), large_assignments, | ||
116 | experimental!(move_size_limit) | ||
117 | ), | ||
115 | 118 | ||
116 | // Entry point: | 119 | // Entry point: |
117 | ungated!(main, Normal, template!(Word)), | 120 | ungated!(main, Normal, template!(Word)), |
@@ -140,6 +143,7 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ | |||
140 | template!(List: "address, memory, thread"), | 143 | template!(List: "address, memory, thread"), |
141 | experimental!(no_sanitize) | 144 | experimental!(no_sanitize) |
142 | ), | 145 | ), |
146 | gated!(no_coverage, AssumedUsed, template!(Word), experimental!(no_coverage)), | ||
143 | 147 | ||
144 | // FIXME: #14408 assume docs are used since rustdoc looks at them. | 148 | // FIXME: #14408 assume docs are used since rustdoc looks at them. |
145 | ungated!(doc, AssumedUsed, template!(List: "hidden|inline|...", NameValueStr: "string")), | 149 | ungated!(doc, AssumedUsed, template!(List: "hidden|inline|...", NameValueStr: "string")), |
@@ -151,11 +155,6 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ | |||
151 | // Linking: | 155 | // Linking: |
152 | gated!(naked, AssumedUsed, template!(Word), naked_functions, experimental!(naked)), | 156 | gated!(naked, AssumedUsed, template!(Word), naked_functions, experimental!(naked)), |
153 | gated!( | 157 | gated!( |
154 | link_args, Normal, template!(NameValueStr: "args"), | ||
155 | "the `link_args` attribute is experimental and not portable across platforms, \ | ||
156 | it is recommended to use `#[link(name = \"foo\")] instead", | ||
157 | ), | ||
158 | gated!( | ||
159 | link_ordinal, AssumedUsed, template!(List: "ordinal"), raw_dylib, | 158 | link_ordinal, AssumedUsed, template!(List: "ordinal"), raw_dylib, |
160 | experimental!(link_ordinal) | 159 | experimental!(link_ordinal) |
161 | ), | 160 | ), |
@@ -172,7 +171,7 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ | |||
172 | "custom test frameworks are an unstable feature", | 171 | "custom test frameworks are an unstable feature", |
173 | ), | 172 | ), |
174 | // RFC #1268 | 173 | // RFC #1268 |
175 | gated!(marker, Normal, template!(Word), marker_trait_attr, experimental!(marker)), | 174 | gated!(marker, AssumedUsed, template!(Word), marker_trait_attr, experimental!(marker)), |
176 | gated!( | 175 | gated!( |
177 | thread_local, AssumedUsed, template!(Word), | 176 | thread_local, AssumedUsed, template!(Word), |
178 | "`#[thread_local]` is an experimental feature, and does not currently handle destructors", | 177 | "`#[thread_local]` is an experimental feature, and does not currently handle destructors", |
@@ -291,7 +290,7 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ | |||
291 | // Internal attributes, Macro related: | 290 | // Internal attributes, Macro related: |
292 | // ========================================================================== | 291 | // ========================================================================== |
293 | 292 | ||
294 | rustc_attr!(rustc_builtin_macro, AssumedUsed, template!(Word), IMPL_DETAIL), | 293 | rustc_attr!(rustc_builtin_macro, AssumedUsed, template!(Word, NameValueStr: "name"), IMPL_DETAIL), |
295 | rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), INTERNAL_UNSTABLE), | 294 | rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), INTERNAL_UNSTABLE), |
296 | rustc_attr!( | 295 | rustc_attr!( |
297 | rustc_macro_transparency, AssumedUsed, | 296 | rustc_macro_transparency, AssumedUsed, |
@@ -319,7 +318,7 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ | |||
319 | // ========================================================================== | 318 | // ========================================================================== |
320 | 319 | ||
321 | rustc_attr!(rustc_promotable, AssumedUsed, template!(Word), IMPL_DETAIL), | 320 | rustc_attr!(rustc_promotable, AssumedUsed, template!(Word), IMPL_DETAIL), |
322 | rustc_attr!(rustc_args_required_const, AssumedUsed, template!(List: "N"), INTERNAL_UNSTABLE), | 321 | rustc_attr!(rustc_legacy_const_generics, AssumedUsed, template!(List: "N"), INTERNAL_UNSTABLE), |
323 | 322 | ||
324 | // ========================================================================== | 323 | // ========================================================================== |
325 | // Internal attributes, Layout related: | 324 | // Internal attributes, Layout related: |
@@ -380,6 +379,15 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ | |||
380 | rustc_specialization_trait, Normal, template!(Word), | 379 | rustc_specialization_trait, Normal, template!(Word), |
381 | "the `#[rustc_specialization_trait]` attribute is used to check specializations" | 380 | "the `#[rustc_specialization_trait]` attribute is used to check specializations" |
382 | ), | 381 | ), |
382 | rustc_attr!( | ||
383 | rustc_main, Normal, template!(Word), | ||
384 | "the `#[rustc_main]` attribute is used internally to specify test entry point function", | ||
385 | ), | ||
386 | rustc_attr!( | ||
387 | rustc_skip_array_during_method_dispatch, Normal, template!(Word), | ||
388 | "the `#[rustc_skip_array_during_method_dispatch]` attribute is used to exclude a trait \ | ||
389 | from method dispatch when the receiver is an array, for compatibility in editions < 2021." | ||
390 | ), | ||
383 | 391 | ||
384 | // ========================================================================== | 392 | // ========================================================================== |
385 | // Internal attributes, Testing: | 393 | // Internal attributes, Testing: |
@@ -387,6 +395,7 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ | |||
387 | 395 | ||
388 | rustc_attr!(TEST, rustc_outlives, Normal, template!(Word)), | 396 | rustc_attr!(TEST, rustc_outlives, Normal, template!(Word)), |
389 | rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word)), | 397 | rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word)), |
398 | rustc_attr!(TEST, rustc_insignificant_dtor, Normal, template!(Word)), | ||
390 | rustc_attr!(TEST, rustc_variance, Normal, template!(Word)), | 399 | rustc_attr!(TEST, rustc_variance, Normal, template!(Word)), |
391 | rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ...")), | 400 | rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ...")), |
392 | rustc_attr!(TEST, rustc_regions, Normal, template!(Word)), | 401 | rustc_attr!(TEST, rustc_regions, Normal, template!(Word)), |
@@ -395,13 +404,10 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ | |||
395 | template!(Word, List: "delay_span_bug_from_inside_query") | 404 | template!(Word, List: "delay_span_bug_from_inside_query") |
396 | ), | 405 | ), |
397 | rustc_attr!(TEST, rustc_dump_user_substs, AssumedUsed, template!(Word)), | 406 | rustc_attr!(TEST, rustc_dump_user_substs, AssumedUsed, template!(Word)), |
407 | rustc_attr!(TEST, rustc_evaluate_where_clauses, AssumedUsed, template!(Word)), | ||
398 | rustc_attr!(TEST, rustc_if_this_changed, AssumedUsed, template!(Word, List: "DepNode")), | 408 | rustc_attr!(TEST, rustc_if_this_changed, AssumedUsed, template!(Word, List: "DepNode")), |
399 | rustc_attr!(TEST, rustc_then_this_would_need, AssumedUsed, template!(List: "DepNode")), | 409 | rustc_attr!(TEST, rustc_then_this_would_need, AssumedUsed, template!(List: "DepNode")), |
400 | rustc_attr!( | 410 | rustc_attr!( |
401 | TEST, rustc_dirty, AssumedUsed, | ||
402 | template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#), | ||
403 | ), | ||
404 | rustc_attr!( | ||
405 | TEST, rustc_clean, AssumedUsed, | 411 | TEST, rustc_clean, AssumedUsed, |
406 | template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#), | 412 | template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#), |
407 | ), | 413 | ), |
diff --git a/crates/hir_def/src/child_by_source.rs b/crates/hir_def/src/child_by_source.rs index f2e809ca9..f22383e22 100644 --- a/crates/hir_def/src/child_by_source.rs +++ b/crates/hir_def/src/child_by_source.rs | |||
@@ -85,6 +85,10 @@ impl ChildBySource for ItemScope { | |||
85 | res[keys::CONST].insert(src, konst); | 85 | res[keys::CONST].insert(src, konst); |
86 | }); | 86 | }); |
87 | self.impls().for_each(|imp| add_impl(db, res, imp)); | 87 | self.impls().for_each(|imp| add_impl(db, res, imp)); |
88 | self.attr_macro_invocs().for_each(|(ast_id, call_id)| { | ||
89 | let item = ast_id.with_value(ast_id.to_node(db.upcast())); | ||
90 | res[keys::ATTR_MACRO].insert(item, call_id); | ||
91 | }); | ||
88 | 92 | ||
89 | fn add_module_def(db: &dyn DefDatabase, map: &mut DynMap, item: ModuleDefId) { | 93 | fn add_module_def(db: &dyn DefDatabase, map: &mut DynMap, item: ModuleDefId) { |
90 | match item { | 94 | match item { |
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index d2bb381be..52cb7777b 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs | |||
@@ -143,6 +143,10 @@ pub struct TraitData { | |||
143 | pub is_auto: bool, | 143 | pub is_auto: bool, |
144 | pub is_unsafe: bool, | 144 | pub is_unsafe: bool, |
145 | pub visibility: RawVisibility, | 145 | pub visibility: RawVisibility, |
146 | /// Whether the trait has `#[rust_skip_array_during_method_dispatch]`. `hir_ty` will ignore | ||
147 | /// method calls to this trait's methods when the receiver is an array and the crate edition is | ||
148 | /// 2015 or 2018. | ||
149 | pub skip_array_during_method_dispatch: bool, | ||
146 | } | 150 | } |
147 | 151 | ||
148 | impl TraitData { | 152 | impl TraitData { |
@@ -157,6 +161,10 @@ impl TraitData { | |||
157 | let container = AssocContainerId::TraitId(tr); | 161 | let container = AssocContainerId::TraitId(tr); |
158 | let visibility = item_tree[tr_def.visibility].clone(); | 162 | let visibility = item_tree[tr_def.visibility].clone(); |
159 | let mut expander = Expander::new(db, tr_loc.id.file_id(), module_id); | 163 | let mut expander = Expander::new(db, tr_loc.id.file_id(), module_id); |
164 | let skip_array_during_method_dispatch = item_tree | ||
165 | .attrs(db, tr_loc.container.krate(), ModItem::from(tr_loc.id.value).into()) | ||
166 | .by_key("rustc_skip_array_during_method_dispatch") | ||
167 | .exists(); | ||
160 | 168 | ||
161 | let items = collect_items( | 169 | let items = collect_items( |
162 | db, | 170 | db, |
@@ -168,7 +176,14 @@ impl TraitData { | |||
168 | 100, | 176 | 100, |
169 | ); | 177 | ); |
170 | 178 | ||
171 | Arc::new(TraitData { name, items, is_auto, is_unsafe, visibility }) | 179 | Arc::new(TraitData { |
180 | name, | ||
181 | items, | ||
182 | is_auto, | ||
183 | is_unsafe, | ||
184 | visibility, | ||
185 | skip_array_during_method_dispatch, | ||
186 | }) | ||
172 | } | 187 | } |
173 | 188 | ||
174 | pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ { | 189 | pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ { |
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs index 7eadc8e0d..c977971cd 100644 --- a/crates/hir_def/src/db.rs +++ b/crates/hir_def/src/db.rs | |||
@@ -51,6 +51,9 @@ pub trait InternDatabase: SourceDatabase { | |||
51 | 51 | ||
52 | #[salsa::query_group(DefDatabaseStorage)] | 52 | #[salsa::query_group(DefDatabaseStorage)] |
53 | pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { | 53 | pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { |
54 | #[salsa::input] | ||
55 | fn enable_proc_attr_macros(&self) -> bool; | ||
56 | |||
54 | #[salsa::invoke(ItemTree::file_item_tree_query)] | 57 | #[salsa::invoke(ItemTree::file_item_tree_query)] |
55 | fn file_item_tree(&self, file_id: HirFileId) -> Arc<ItemTree>; | 58 | fn file_item_tree(&self, file_id: HirFileId) -> Arc<ItemTree>; |
56 | 59 | ||
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs index 44d22b918..6933f6e3c 100644 --- a/crates/hir_def/src/generics.rs +++ b/crates/hir_def/src/generics.rs | |||
@@ -280,7 +280,7 @@ impl GenericParams { | |||
280 | sm.type_params.insert(param_id, Either::Right(type_param.clone())); | 280 | sm.type_params.insert(param_id, Either::Right(type_param.clone())); |
281 | 281 | ||
282 | let type_ref = TypeRef::Path(name.into()); | 282 | let type_ref = TypeRef::Path(name.into()); |
283 | self.fill_bounds(&lower_ctx, &type_param, Either::Left(type_ref)); | 283 | self.fill_bounds(lower_ctx, &type_param, Either::Left(type_ref)); |
284 | } | 284 | } |
285 | for lifetime_param in params.lifetime_params() { | 285 | for lifetime_param in params.lifetime_params() { |
286 | let name = | 286 | let name = |
@@ -289,7 +289,7 @@ impl GenericParams { | |||
289 | let param_id = self.lifetimes.alloc(param); | 289 | let param_id = self.lifetimes.alloc(param); |
290 | sm.lifetime_params.insert(param_id, lifetime_param.clone()); | 290 | sm.lifetime_params.insert(param_id, lifetime_param.clone()); |
291 | let lifetime_ref = LifetimeRef::new_name(name); | 291 | let lifetime_ref = LifetimeRef::new_name(name); |
292 | self.fill_bounds(&lower_ctx, &lifetime_param, Either::Right(lifetime_ref)); | 292 | self.fill_bounds(lower_ctx, &lifetime_param, Either::Right(lifetime_ref)); |
293 | } | 293 | } |
294 | for const_param in params.const_params() { | 294 | for const_param in params.const_params() { |
295 | let name = const_param.name().map_or_else(Name::missing, |it| it.as_name()); | 295 | let name = const_param.name().map_or_else(Name::missing, |it| it.as_name()); |
diff --git a/crates/hir_def/src/import_map.rs b/crates/hir_def/src/import_map.rs index 960cabb5f..404e3e153 100644 --- a/crates/hir_def/src/import_map.rs +++ b/crates/hir_def/src/import_map.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! A map of all publicly exported items in a crate. | 1 | //! A map of all publicly exported items in a crate. |
2 | 2 | ||
3 | use std::{cmp::Ordering, fmt, hash::BuildHasherDefault, sync::Arc}; | 3 | use std::{fmt, hash::BuildHasherDefault, sync::Arc}; |
4 | 4 | ||
5 | use base_db::CrateId; | 5 | use base_db::CrateId; |
6 | use fst::{self, Streamer}; | 6 | use fst::{self, Streamer}; |
@@ -69,81 +69,11 @@ pub struct ImportMap { | |||
69 | impl ImportMap { | 69 | impl ImportMap { |
70 | pub fn import_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<Self> { | 70 | pub fn import_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<Self> { |
71 | let _p = profile::span("import_map_query"); | 71 | let _p = profile::span("import_map_query"); |
72 | let def_map = db.crate_def_map(krate); | ||
73 | let mut import_map = Self::default(); | ||
74 | |||
75 | // We look only into modules that are public(ly reexported), starting with the crate root. | ||
76 | let empty = ImportPath { segments: vec![] }; | ||
77 | let root = def_map.module_id(def_map.root()); | ||
78 | let mut worklist = vec![(root, empty)]; | ||
79 | while let Some((module, mod_path)) = worklist.pop() { | ||
80 | let ext_def_map; | ||
81 | let mod_data = if module.krate == krate { | ||
82 | &def_map[module.local_id] | ||
83 | } else { | ||
84 | // The crate might reexport a module defined in another crate. | ||
85 | ext_def_map = module.def_map(db); | ||
86 | &ext_def_map[module.local_id] | ||
87 | }; | ||
88 | |||
89 | let visible_items = mod_data.scope.entries().filter_map(|(name, per_ns)| { | ||
90 | let per_ns = per_ns.filter_visibility(|vis| vis == Visibility::Public); | ||
91 | if per_ns.is_none() { | ||
92 | None | ||
93 | } else { | ||
94 | Some((name, per_ns)) | ||
95 | } | ||
96 | }); | ||
97 | |||
98 | for (name, per_ns) in visible_items { | ||
99 | let mk_path = || { | ||
100 | let mut path = mod_path.clone(); | ||
101 | path.segments.push(name.clone()); | ||
102 | path | ||
103 | }; | ||
104 | |||
105 | for item in per_ns.iter_items() { | ||
106 | let path = mk_path(); | ||
107 | let path_len = path.len(); | ||
108 | let import_info = | ||
109 | ImportInfo { path, container: module, is_trait_assoc_item: false }; | ||
110 | |||
111 | if let Some(ModuleDefId::TraitId(tr)) = item.as_module_def_id() { | ||
112 | import_map.collect_trait_assoc_items( | ||
113 | db, | ||
114 | tr, | ||
115 | matches!(item, ItemInNs::Types(_)), | ||
116 | &import_info, | ||
117 | ); | ||
118 | } | ||
119 | 72 | ||
120 | match import_map.map.entry(item) { | 73 | let mut import_map = collect_import_map(db, krate); |
121 | Entry::Vacant(entry) => { | ||
122 | entry.insert(import_info); | ||
123 | } | ||
124 | Entry::Occupied(mut entry) => { | ||
125 | // If the new path is shorter, prefer that one. | ||
126 | if path_len < entry.get().path.len() { | ||
127 | *entry.get_mut() = import_info; | ||
128 | } else { | ||
129 | continue; | ||
130 | } | ||
131 | } | ||
132 | } | ||
133 | |||
134 | // If we've just added a path to a module, descend into it. We might traverse | ||
135 | // modules multiple times, but only if the new path to it is shorter than the | ||
136 | // first (else we `continue` above). | ||
137 | if let Some(ModuleDefId::ModuleId(mod_id)) = item.as_module_def_id() { | ||
138 | worklist.push((mod_id, mk_path())); | ||
139 | } | ||
140 | } | ||
141 | } | ||
142 | } | ||
143 | 74 | ||
144 | let mut importables = import_map.map.iter().collect::<Vec<_>>(); | 75 | let mut importables = import_map.map.iter().collect::<Vec<_>>(); |
145 | 76 | importables.sort_by_cached_key(|(_, import_info)| fst_path(&import_info.path)); | |
146 | importables.sort_by(cmp); | ||
147 | 77 | ||
148 | // Build the FST, taking care not to insert duplicate values. | 78 | // Build the FST, taking care not to insert duplicate values. |
149 | 79 | ||
@@ -151,13 +81,13 @@ impl ImportMap { | |||
151 | let mut last_batch_start = 0; | 81 | let mut last_batch_start = 0; |
152 | 82 | ||
153 | for idx in 0..importables.len() { | 83 | for idx in 0..importables.len() { |
154 | if let Some(next_item) = importables.get(idx + 1) { | 84 | let key = fst_path(&importables[last_batch_start].1.path); |
155 | if cmp(&importables[last_batch_start], next_item) == Ordering::Equal { | 85 | if let Some((_, next_import_info)) = importables.get(idx + 1) { |
86 | if key == fst_path(&next_import_info.path) { | ||
156 | continue; | 87 | continue; |
157 | } | 88 | } |
158 | } | 89 | } |
159 | 90 | ||
160 | let key = fst_path(&importables[last_batch_start].1.path); | ||
161 | builder.insert(key, last_batch_start as u64).unwrap(); | 91 | builder.insert(key, last_batch_start as u64).unwrap(); |
162 | 92 | ||
163 | last_batch_start = idx + 1; | 93 | last_batch_start = idx + 1; |
@@ -185,6 +115,7 @@ impl ImportMap { | |||
185 | is_type_in_ns: bool, | 115 | is_type_in_ns: bool, |
186 | original_import_info: &ImportInfo, | 116 | original_import_info: &ImportInfo, |
187 | ) { | 117 | ) { |
118 | let _p = profile::span("collect_trait_assoc_items"); | ||
188 | for (assoc_item_name, item) in &db.trait_data(tr).items { | 119 | for (assoc_item_name, item) in &db.trait_data(tr).items { |
189 | let module_def_id = match item { | 120 | let module_def_id = match item { |
190 | AssocItemId::FunctionId(f) => ModuleDefId::from(*f), | 121 | AssocItemId::FunctionId(f) => ModuleDefId::from(*f), |
@@ -210,6 +141,84 @@ impl ImportMap { | |||
210 | } | 141 | } |
211 | } | 142 | } |
212 | 143 | ||
144 | fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMap { | ||
145 | let _p = profile::span("collect_import_map"); | ||
146 | |||
147 | let def_map = db.crate_def_map(krate); | ||
148 | let mut import_map = ImportMap::default(); | ||
149 | |||
150 | // We look only into modules that are public(ly reexported), starting with the crate root. | ||
151 | let empty = ImportPath { segments: vec![] }; | ||
152 | let root = def_map.module_id(def_map.root()); | ||
153 | let mut worklist = vec![(root, empty)]; | ||
154 | while let Some((module, mod_path)) = worklist.pop() { | ||
155 | let ext_def_map; | ||
156 | let mod_data = if module.krate == krate { | ||
157 | &def_map[module.local_id] | ||
158 | } else { | ||
159 | // The crate might reexport a module defined in another crate. | ||
160 | ext_def_map = module.def_map(db); | ||
161 | &ext_def_map[module.local_id] | ||
162 | }; | ||
163 | |||
164 | let visible_items = mod_data.scope.entries().filter_map(|(name, per_ns)| { | ||
165 | let per_ns = per_ns.filter_visibility(|vis| vis == Visibility::Public); | ||
166 | if per_ns.is_none() { | ||
167 | None | ||
168 | } else { | ||
169 | Some((name, per_ns)) | ||
170 | } | ||
171 | }); | ||
172 | |||
173 | for (name, per_ns) in visible_items { | ||
174 | let mk_path = || { | ||
175 | let mut path = mod_path.clone(); | ||
176 | path.segments.push(name.clone()); | ||
177 | path | ||
178 | }; | ||
179 | |||
180 | for item in per_ns.iter_items() { | ||
181 | let path = mk_path(); | ||
182 | let path_len = path.len(); | ||
183 | let import_info = | ||
184 | ImportInfo { path, container: module, is_trait_assoc_item: false }; | ||
185 | |||
186 | if let Some(ModuleDefId::TraitId(tr)) = item.as_module_def_id() { | ||
187 | import_map.collect_trait_assoc_items( | ||
188 | db, | ||
189 | tr, | ||
190 | matches!(item, ItemInNs::Types(_)), | ||
191 | &import_info, | ||
192 | ); | ||
193 | } | ||
194 | |||
195 | match import_map.map.entry(item) { | ||
196 | Entry::Vacant(entry) => { | ||
197 | entry.insert(import_info); | ||
198 | } | ||
199 | Entry::Occupied(mut entry) => { | ||
200 | // If the new path is shorter, prefer that one. | ||
201 | if path_len < entry.get().path.len() { | ||
202 | *entry.get_mut() = import_info; | ||
203 | } else { | ||
204 | continue; | ||
205 | } | ||
206 | } | ||
207 | } | ||
208 | |||
209 | // If we've just added a path to a module, descend into it. We might traverse | ||
210 | // modules multiple times, but only if the new path to it is shorter than the | ||
211 | // first (else we `continue` above). | ||
212 | if let Some(ModuleDefId::ModuleId(mod_id)) = item.as_module_def_id() { | ||
213 | worklist.push((mod_id, mk_path())); | ||
214 | } | ||
215 | } | ||
216 | } | ||
217 | } | ||
218 | |||
219 | import_map | ||
220 | } | ||
221 | |||
213 | impl PartialEq for ImportMap { | 222 | impl PartialEq for ImportMap { |
214 | fn eq(&self, other: &Self) -> bool { | 223 | fn eq(&self, other: &Self) -> bool { |
215 | // `fst` and `importables` are built from `map`, so we don't need to compare them. | 224 | // `fst` and `importables` are built from `map`, so we don't need to compare them. |
@@ -240,17 +249,12 @@ impl fmt::Debug for ImportMap { | |||
240 | } | 249 | } |
241 | 250 | ||
242 | fn fst_path(path: &ImportPath) -> String { | 251 | fn fst_path(path: &ImportPath) -> String { |
252 | let _p = profile::span("fst_path"); | ||
243 | let mut s = path.to_string(); | 253 | let mut s = path.to_string(); |
244 | s.make_ascii_lowercase(); | 254 | s.make_ascii_lowercase(); |
245 | s | 255 | s |
246 | } | 256 | } |
247 | 257 | ||
248 | fn cmp((_, lhs): &(&ItemInNs, &ImportInfo), (_, rhs): &(&ItemInNs, &ImportInfo)) -> Ordering { | ||
249 | let lhs_str = fst_path(&lhs.path); | ||
250 | let rhs_str = fst_path(&rhs.path); | ||
251 | lhs_str.cmp(&rhs_str) | ||
252 | } | ||
253 | |||
254 | #[derive(Debug, Eq, PartialEq, Hash)] | 258 | #[derive(Debug, Eq, PartialEq, Hash)] |
255 | pub enum ImportKind { | 259 | pub enum ImportKind { |
256 | Module, | 260 | Module, |
@@ -338,6 +342,7 @@ impl Query { | |||
338 | } | 342 | } |
339 | 343 | ||
340 | fn import_matches(&self, import: &ImportInfo, enforce_lowercase: bool) -> bool { | 344 | fn import_matches(&self, import: &ImportInfo, enforce_lowercase: bool) -> bool { |
345 | let _p = profile::span("import_map::Query::import_matches"); | ||
341 | if import.is_trait_assoc_item { | 346 | if import.is_trait_assoc_item { |
342 | if self.exclude_import_kinds.contains(&ImportKind::AssociatedItem) { | 347 | if self.exclude_import_kinds.contains(&ImportKind::AssociatedItem) { |
343 | return false; | 348 | return false; |
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs index 9014468ea..08407ebfa 100644 --- a/crates/hir_def/src/item_scope.rs +++ b/crates/hir_def/src/item_scope.rs | |||
@@ -4,11 +4,11 @@ | |||
4 | use std::collections::hash_map::Entry; | 4 | use std::collections::hash_map::Entry; |
5 | 5 | ||
6 | use base_db::CrateId; | 6 | use base_db::CrateId; |
7 | use hir_expand::name::Name; | 7 | use hir_expand::{name::Name, AstId, MacroCallId, MacroDefKind}; |
8 | use hir_expand::MacroDefKind; | ||
9 | use once_cell::sync::Lazy; | 8 | use once_cell::sync::Lazy; |
10 | use rustc_hash::{FxHashMap, FxHashSet}; | 9 | use rustc_hash::{FxHashMap, FxHashSet}; |
11 | use stdx::format_to; | 10 | use stdx::format_to; |
11 | use syntax::ast; | ||
12 | 12 | ||
13 | use crate::{ | 13 | use crate::{ |
14 | db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ConstId, ImplId, | 14 | db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ConstId, ImplId, |
@@ -53,12 +53,13 @@ pub struct ItemScope { | |||
53 | // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will | 53 | // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will |
54 | // be all resolved to the last one defined if shadowing happens. | 54 | // be all resolved to the last one defined if shadowing happens. |
55 | legacy_macros: FxHashMap<Name, MacroDefId>, | 55 | legacy_macros: FxHashMap<Name, MacroDefId>, |
56 | attr_macros: FxHashMap<AstId<ast::Item>, MacroCallId>, | ||
56 | } | 57 | } |
57 | 58 | ||
58 | pub(crate) static BUILTIN_SCOPE: Lazy<FxHashMap<Name, PerNs>> = Lazy::new(|| { | 59 | pub(crate) static BUILTIN_SCOPE: Lazy<FxHashMap<Name, PerNs>> = Lazy::new(|| { |
59 | BuiltinType::ALL | 60 | BuiltinType::ALL |
60 | .iter() | 61 | .iter() |
61 | .map(|(name, ty)| (name.clone(), PerNs::types(ty.clone().into(), Visibility::Public))) | 62 | .map(|(name, ty)| (name.clone(), PerNs::types((*ty).into(), Visibility::Public))) |
62 | .collect() | 63 | .collect() |
63 | }); | 64 | }); |
64 | 65 | ||
@@ -169,6 +170,16 @@ impl ItemScope { | |||
169 | self.legacy_macros.insert(name, mac); | 170 | self.legacy_macros.insert(name, mac); |
170 | } | 171 | } |
171 | 172 | ||
173 | pub(crate) fn add_attr_macro_invoc(&mut self, item: AstId<ast::Item>, call: MacroCallId) { | ||
174 | self.attr_macros.insert(item, call); | ||
175 | } | ||
176 | |||
177 | pub(crate) fn attr_macro_invocs( | ||
178 | &self, | ||
179 | ) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ { | ||
180 | self.attr_macros.iter().map(|(k, v)| (*k, *v)) | ||
181 | } | ||
182 | |||
172 | pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option<Visibility> { | 183 | pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option<Visibility> { |
173 | self.unnamed_trait_imports.get(&tr).copied() | 184 | self.unnamed_trait_imports.get(&tr).copied() |
174 | } | 185 | } |
@@ -307,6 +318,7 @@ impl ItemScope { | |||
307 | unnamed_consts, | 318 | unnamed_consts, |
308 | unnamed_trait_imports, | 319 | unnamed_trait_imports, |
309 | legacy_macros, | 320 | legacy_macros, |
321 | attr_macros, | ||
310 | } = self; | 322 | } = self; |
311 | types.shrink_to_fit(); | 323 | types.shrink_to_fit(); |
312 | values.shrink_to_fit(); | 324 | values.shrink_to_fit(); |
@@ -317,6 +329,7 @@ impl ItemScope { | |||
317 | unnamed_consts.shrink_to_fit(); | 329 | unnamed_consts.shrink_to_fit(); |
318 | unnamed_trait_imports.shrink_to_fit(); | 330 | unnamed_trait_imports.shrink_to_fit(); |
319 | legacy_macros.shrink_to_fit(); | 331 | legacy_macros.shrink_to_fit(); |
332 | attr_macros.shrink_to_fit(); | ||
320 | } | 333 | } |
321 | } | 334 | } |
322 | 335 | ||
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 6208facd5..3f90bda74 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs | |||
@@ -130,7 +130,7 @@ impl<'a> Ctx<'a> { | |||
130 | ast::Item::ExternBlock(ast) => self.lower_extern_block(ast).into(), | 130 | ast::Item::ExternBlock(ast) => self.lower_extern_block(ast).into(), |
131 | }; | 131 | }; |
132 | 132 | ||
133 | self.add_attrs(item.into(), attrs.clone()); | 133 | self.add_attrs(item.into(), attrs); |
134 | 134 | ||
135 | Some(item) | 135 | Some(item) |
136 | } | 136 | } |
@@ -276,10 +276,11 @@ impl<'a> Ctx<'a> { | |||
276 | let visibility = self.lower_visibility(enum_); | 276 | let visibility = self.lower_visibility(enum_); |
277 | let name = enum_.name()?.as_name(); | 277 | let name = enum_.name()?.as_name(); |
278 | let generic_params = self.lower_generic_params(GenericsOwner::Enum, enum_); | 278 | let generic_params = self.lower_generic_params(GenericsOwner::Enum, enum_); |
279 | let variants = match &enum_.variant_list() { | 279 | let variants = |
280 | Some(variant_list) => self.lower_variants(variant_list), | 280 | self.with_inherited_visibility(visibility, |this| match &enum_.variant_list() { |
281 | None => IdRange::new(self.next_variant_idx()..self.next_variant_idx()), | 281 | Some(variant_list) => this.lower_variants(variant_list), |
282 | }; | 282 | None => IdRange::new(this.next_variant_idx()..this.next_variant_idx()), |
283 | }); | ||
283 | let ast_id = self.source_ast_id_map.ast_id(enum_); | 284 | let ast_id = self.source_ast_id_map.ast_id(enum_); |
284 | let res = Enum { name, visibility, generic_params, variants, ast_id }; | 285 | let res = Enum { name, visibility, generic_params, variants, ast_id }; |
285 | Some(id(self.data().enums.alloc(res))) | 286 | Some(id(self.data().enums.alloc(res))) |
@@ -822,7 +823,7 @@ fn is_intrinsic_fn_unsafe(name: &Name) -> bool { | |||
822 | known::type_name, | 823 | known::type_name, |
823 | known::variant_count, | 824 | known::variant_count, |
824 | ] | 825 | ] |
825 | .contains(&name) | 826 | .contains(name) |
826 | } | 827 | } |
827 | 828 | ||
828 | fn lower_abi(abi: ast::Abi) -> Interned<str> { | 829 | fn lower_abi(abi: ast::Abi) -> Interned<str> { |
@@ -854,7 +855,7 @@ impl UseTreeLowering<'_> { | |||
854 | // E.g. `use something::{inner}` (prefix is `None`, path is `something`) | 855 | // E.g. `use something::{inner}` (prefix is `None`, path is `something`) |
855 | // or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`) | 856 | // or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`) |
856 | Some(path) => { | 857 | Some(path) => { |
857 | match ModPath::from_src(self.db, path, &self.hygiene) { | 858 | match ModPath::from_src(self.db, path, self.hygiene) { |
858 | Some(it) => Some(it), | 859 | Some(it) => Some(it), |
859 | None => return None, // FIXME: report errors somewhere | 860 | None => return None, // FIXME: report errors somewhere |
860 | } | 861 | } |
@@ -873,7 +874,7 @@ impl UseTreeLowering<'_> { | |||
873 | } else { | 874 | } else { |
874 | let is_glob = tree.star_token().is_some(); | 875 | let is_glob = tree.star_token().is_some(); |
875 | let path = match tree.path() { | 876 | let path = match tree.path() { |
876 | Some(path) => Some(ModPath::from_src(self.db, path, &self.hygiene)?), | 877 | Some(path) => Some(ModPath::from_src(self.db, path, self.hygiene)?), |
877 | None => None, | 878 | None => None, |
878 | }; | 879 | }; |
879 | let alias = tree.rename().map(|a| { | 880 | let alias = tree.rename().map(|a| { |
diff --git a/crates/hir_def/src/item_tree/pretty.rs b/crates/hir_def/src/item_tree/pretty.rs index cc9944a22..b1e1b70d0 100644 --- a/crates/hir_def/src/item_tree/pretty.rs +++ b/crates/hir_def/src/item_tree/pretty.rs | |||
@@ -426,7 +426,7 @@ impl<'a> Printer<'a> { | |||
426 | w!(self, " {{"); | 426 | w!(self, " {{"); |
427 | self.indented(|this| { | 427 | self.indented(|this| { |
428 | for item in &**items { | 428 | for item in &**items { |
429 | this.print_mod_item((*item).into()); | 429 | this.print_mod_item(*item); |
430 | } | 430 | } |
431 | }); | 431 | }); |
432 | wln!(self, "}}"); | 432 | wln!(self, "}}"); |
diff --git a/crates/hir_def/src/item_tree/tests.rs b/crates/hir_def/src/item_tree/tests.rs index b362add5c..57686dc6e 100644 --- a/crates/hir_def/src/item_tree/tests.rs +++ b/crates/hir_def/src/item_tree/tests.rs | |||
@@ -359,3 +359,41 @@ trait Tr<'a, T: 'a>: Super {} | |||
359 | "#]], | 359 | "#]], |
360 | ) | 360 | ) |
361 | } | 361 | } |
362 | |||
363 | #[test] | ||
364 | fn inherit_visibility() { | ||
365 | check( | ||
366 | r#" | ||
367 | pub(crate) enum En { | ||
368 | Var1(u8), | ||
369 | Var2 { | ||
370 | fld: u8, | ||
371 | }, | ||
372 | } | ||
373 | |||
374 | pub(crate) trait Tr { | ||
375 | fn f(); | ||
376 | fn method(&self) {} | ||
377 | } | ||
378 | "#, | ||
379 | expect![[r#" | ||
380 | pub(crate) enum En { | ||
381 | Var1( | ||
382 | pub(crate) 0: u8, | ||
383 | ), | ||
384 | Var2 { | ||
385 | pub(crate) fld: u8, | ||
386 | }, | ||
387 | } | ||
388 | |||
389 | pub(crate) trait Tr<Self> { | ||
390 | pub(crate) fn f() -> (); | ||
391 | |||
392 | // flags = 0x3 | ||
393 | pub(crate) fn method( | ||
394 | _: &Self, | ||
395 | ) -> (); | ||
396 | } | ||
397 | "#]], | ||
398 | ) | ||
399 | } | ||
diff --git a/crates/hir_def/src/keys.rs b/crates/hir_def/src/keys.rs index 89b3ed868..688cd9fcf 100644 --- a/crates/hir_def/src/keys.rs +++ b/crates/hir_def/src/keys.rs | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | use std::marker::PhantomData; | 3 | use std::marker::PhantomData; |
4 | 4 | ||
5 | use hir_expand::{InFile, MacroDefId}; | 5 | use hir_expand::{InFile, MacroCallId, MacroDefId}; |
6 | use rustc_hash::FxHashMap; | 6 | use rustc_hash::FxHashMap; |
7 | use syntax::{ast, AstNode, AstPtr}; | 7 | use syntax::{ast, AstNode, AstPtr}; |
8 | 8 | ||
@@ -32,6 +32,7 @@ pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = Key::new(); | |||
32 | pub const CONST_PARAM: Key<ast::ConstParam, ConstParamId> = Key::new(); | 32 | pub const CONST_PARAM: Key<ast::ConstParam, ConstParamId> = Key::new(); |
33 | 33 | ||
34 | pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new(); | 34 | pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new(); |
35 | pub const ATTR_MACRO: Key<ast::Item, MacroCallId> = Key::new(); | ||
35 | 36 | ||
36 | /// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are | 37 | /// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are |
37 | /// equal if they point to exactly the same object. | 38 | /// equal if they point to exactly the same object. |
diff --git a/crates/hir_def/src/lang_item.rs b/crates/hir_def/src/lang_item.rs index 9e90f745c..3a45cbfa1 100644 --- a/crates/hir_def/src/lang_item.rs +++ b/crates/hir_def/src/lang_item.rs | |||
@@ -141,6 +141,7 @@ impl LangItems { | |||
141 | ) where | 141 | ) where |
142 | T: Into<AttrDefId> + Copy, | 142 | T: Into<AttrDefId> + Copy, |
143 | { | 143 | { |
144 | let _p = profile::span("collect_lang_item"); | ||
144 | if let Some(lang_item_name) = lang_attr(db, item) { | 145 | if let Some(lang_item_name) = lang_attr(db, item) { |
145 | self.items.entry(lang_item_name).or_insert_with(|| constructor(item)); | 146 | self.items.entry(lang_item_name).or_insert_with(|| constructor(item)); |
146 | } | 147 | } |
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index 9aa95720a..bb174aec8 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs | |||
@@ -55,6 +55,7 @@ use std::{ | |||
55 | sync::Arc, | 55 | sync::Arc, |
56 | }; | 56 | }; |
57 | 57 | ||
58 | use attr::Attr; | ||
58 | use base_db::{impl_intern_key, salsa, CrateId}; | 59 | use base_db::{impl_intern_key, salsa, CrateId}; |
59 | use hir_expand::{ | 60 | use hir_expand::{ |
60 | ast_id_map::FileAstId, | 61 | ast_id_map::FileAstId, |
@@ -111,6 +112,10 @@ impl ModuleId { | |||
111 | self.def_map(db).containing_module(self.local_id) | 112 | self.def_map(db).containing_module(self.local_id) |
112 | } | 113 | } |
113 | 114 | ||
115 | pub fn containing_block(&self) -> Option<BlockId> { | ||
116 | self.block | ||
117 | } | ||
118 | |||
114 | /// Returns `true` if this module represents a block expression. | 119 | /// Returns `true` if this module represents a block expression. |
115 | /// | 120 | /// |
116 | /// Returns `false` if this module is a submodule *inside* a block expression | 121 | /// Returns `false` if this module is a submodule *inside* a block expression |
@@ -580,6 +585,18 @@ impl HasModule for GenericDefId { | |||
580 | } | 585 | } |
581 | } | 586 | } |
582 | 587 | ||
588 | impl HasModule for TypeAliasId { | ||
589 | fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { | ||
590 | self.lookup(db).module(db) | ||
591 | } | ||
592 | } | ||
593 | |||
594 | impl HasModule for TraitId { | ||
595 | fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { | ||
596 | self.lookup(db).container | ||
597 | } | ||
598 | } | ||
599 | |||
583 | impl HasModule for StaticLoc { | 600 | impl HasModule for StaticLoc { |
584 | fn module(&self, _db: &dyn db::DefDatabase) -> ModuleId { | 601 | fn module(&self, _db: &dyn db::DefDatabase) -> ModuleId { |
585 | self.container | 602 | self.container |
@@ -730,13 +747,11 @@ fn macro_call_as_call_id( | |||
730 | ) | 747 | ) |
731 | .map(MacroCallId::from) | 748 | .map(MacroCallId::from) |
732 | } else { | 749 | } else { |
733 | Ok(def | 750 | Ok(def.as_lazy_macro( |
734 | .as_lazy_macro( | 751 | db.upcast(), |
735 | db.upcast(), | 752 | krate, |
736 | krate, | 753 | MacroCallKind::FnLike { ast_id: call.ast_id, fragment }, |
737 | MacroCallKind::FnLike { ast_id: call.ast_id, fragment }, | 754 | )) |
738 | ) | ||
739 | .into()) | ||
740 | }; | 755 | }; |
741 | Ok(res) | 756 | Ok(res) |
742 | } | 757 | } |
@@ -755,16 +770,51 @@ fn derive_macro_as_call_id( | |||
755 | .segments() | 770 | .segments() |
756 | .last() | 771 | .last() |
757 | .ok_or_else(|| UnresolvedMacro { path: item_attr.path.clone() })?; | 772 | .ok_or_else(|| UnresolvedMacro { path: item_attr.path.clone() })?; |
758 | let res = def | 773 | let res = def.as_lazy_macro( |
759 | .as_lazy_macro( | 774 | db.upcast(), |
760 | db.upcast(), | 775 | krate, |
761 | krate, | 776 | MacroCallKind::Derive { |
762 | MacroCallKind::Derive { | 777 | ast_id: item_attr.ast_id, |
763 | ast_id: item_attr.ast_id, | 778 | derive_name: last_segment.to_string(), |
764 | derive_name: last_segment.to_string(), | 779 | derive_attr_index: derive_attr.ast_index, |
765 | derive_attr_index: derive_attr.ast_index, | 780 | }, |
766 | }, | 781 | ); |
767 | ) | 782 | Ok(res) |
768 | .into(); | 783 | } |
784 | |||
785 | fn attr_macro_as_call_id( | ||
786 | item_attr: &AstIdWithPath<ast::Item>, | ||
787 | macro_attr: &Attr, | ||
788 | db: &dyn db::DefDatabase, | ||
789 | krate: CrateId, | ||
790 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | ||
791 | ) -> Result<MacroCallId, UnresolvedMacro> { | ||
792 | let def: MacroDefId = resolver(item_attr.path.clone()) | ||
793 | .ok_or_else(|| UnresolvedMacro { path: item_attr.path.clone() })?; | ||
794 | let last_segment = item_attr | ||
795 | .path | ||
796 | .segments() | ||
797 | .last() | ||
798 | .ok_or_else(|| UnresolvedMacro { path: item_attr.path.clone() })?; | ||
799 | let mut arg = match ¯o_attr.input { | ||
800 | Some(input) => match &**input { | ||
801 | attr::AttrInput::Literal(_) => tt::Subtree::default(), | ||
802 | attr::AttrInput::TokenTree(tt) => tt.clone(), | ||
803 | }, | ||
804 | None => tt::Subtree::default(), | ||
805 | }; | ||
806 | // The parentheses are always disposed here. | ||
807 | arg.delimiter = None; | ||
808 | |||
809 | let res = def.as_lazy_macro( | ||
810 | db.upcast(), | ||
811 | krate, | ||
812 | MacroCallKind::Attr { | ||
813 | ast_id: item_attr.ast_id, | ||
814 | attr_name: last_segment.to_string(), | ||
815 | attr_args: arg, | ||
816 | invoc_attr_index: macro_attr.id.ast_index, | ||
817 | }, | ||
818 | ); | ||
769 | Ok(res) | 819 | Ok(res) |
770 | } | 820 | } |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 6b41921ae..6fab58f15 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -9,6 +9,7 @@ use base_db::{CrateId, Edition, FileId, ProcMacroId}; | |||
9 | use cfg::{CfgExpr, CfgOptions}; | 9 | use cfg::{CfgExpr, CfgOptions}; |
10 | use hir_expand::{ | 10 | use hir_expand::{ |
11 | ast_id_map::FileAstId, | 11 | ast_id_map::FileAstId, |
12 | builtin_attr::find_builtin_attr, | ||
12 | builtin_derive::find_builtin_derive, | 13 | builtin_derive::find_builtin_derive, |
13 | builtin_macro::find_builtin_macro, | 14 | builtin_macro::find_builtin_macro, |
14 | name::{name, AsName, Name}, | 15 | name::{name, AsName, Name}, |
@@ -23,7 +24,7 @@ use syntax::ast; | |||
23 | 24 | ||
24 | use crate::{ | 25 | use crate::{ |
25 | attr::{Attr, AttrId, AttrInput, Attrs}, | 26 | attr::{Attr, AttrId, AttrInput, Attrs}, |
26 | builtin_attr, | 27 | attr_macro_as_call_id, builtin_attr, |
27 | db::DefDatabase, | 28 | db::DefDatabase, |
28 | derive_macro_as_call_id, | 29 | derive_macro_as_call_id, |
29 | intern::Interned, | 30 | intern::Interned, |
@@ -223,7 +224,7 @@ struct MacroDirective { | |||
223 | enum MacroDirectiveKind { | 224 | enum MacroDirectiveKind { |
224 | FnLike { ast_id: AstIdWithPath<ast::MacroCall>, fragment: FragmentKind }, | 225 | FnLike { ast_id: AstIdWithPath<ast::MacroCall>, fragment: FragmentKind }, |
225 | Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId }, | 226 | Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId }, |
226 | Attr { ast_id: AstIdWithPath<ast::Item>, attr: AttrId, mod_item: ModItem }, | 227 | Attr { ast_id: AstIdWithPath<ast::Item>, attr: Attr, mod_item: ModItem }, |
227 | } | 228 | } |
228 | 229 | ||
229 | struct DefData<'a> { | 230 | struct DefData<'a> { |
@@ -419,7 +420,7 @@ impl DefCollector<'_> { | |||
419 | let mut unresolved_macros = std::mem::replace(&mut self.unresolved_macros, Vec::new()); | 420 | let mut unresolved_macros = std::mem::replace(&mut self.unresolved_macros, Vec::new()); |
420 | let pos = unresolved_macros.iter().position(|directive| { | 421 | let pos = unresolved_macros.iter().position(|directive| { |
421 | if let MacroDirectiveKind::Attr { ast_id, mod_item, attr } = &directive.kind { | 422 | if let MacroDirectiveKind::Attr { ast_id, mod_item, attr } = &directive.kind { |
422 | self.skip_attrs.insert(ast_id.ast_id.with_value(*mod_item), *attr); | 423 | self.skip_attrs.insert(ast_id.ast_id.with_value(*mod_item), attr.id); |
423 | 424 | ||
424 | let file_id = ast_id.ast_id.file_id; | 425 | let file_id = ast_id.ast_id.file_id; |
425 | let item_tree = self.db.file_item_tree(file_id); | 426 | let item_tree = self.db.file_item_tree(file_id); |
@@ -499,7 +500,7 @@ impl DefCollector<'_> { | |||
499 | let (per_ns, _) = self.def_map.resolve_path( | 500 | let (per_ns, _) = self.def_map.resolve_path( |
500 | self.db, | 501 | self.db, |
501 | self.def_map.root, | 502 | self.def_map.root, |
502 | &path, | 503 | path, |
503 | BuiltinShadowMode::Other, | 504 | BuiltinShadowMode::Other, |
504 | ); | 505 | ); |
505 | 506 | ||
@@ -721,7 +722,7 @@ impl DefCollector<'_> { | |||
721 | if import.is_extern_crate { | 722 | if import.is_extern_crate { |
722 | let res = self.def_map.resolve_name_in_extern_prelude( | 723 | let res = self.def_map.resolve_name_in_extern_prelude( |
723 | self.db, | 724 | self.db, |
724 | &import | 725 | import |
725 | .path | 726 | .path |
726 | .as_ident() | 727 | .as_ident() |
727 | .expect("extern crate should have been desugared to one-element path"), | 728 | .expect("extern crate should have been desugared to one-element path"), |
@@ -1050,7 +1051,7 @@ impl DefCollector<'_> { | |||
1050 | let file_id = ast_id.ast_id.file_id; | 1051 | let file_id = ast_id.ast_id.file_id; |
1051 | let item_tree = self.db.file_item_tree(file_id); | 1052 | let item_tree = self.db.file_item_tree(file_id); |
1052 | let mod_dir = self.mod_dirs[&directive.module_id].clone(); | 1053 | let mod_dir = self.mod_dirs[&directive.module_id].clone(); |
1053 | self.skip_attrs.insert(InFile::new(file_id, *mod_item), *attr); | 1054 | self.skip_attrs.insert(InFile::new(file_id, *mod_item), attr.id); |
1054 | ModCollector { | 1055 | ModCollector { |
1055 | def_collector: &mut *self, | 1056 | def_collector: &mut *self, |
1056 | macro_depth: directive.depth, | 1057 | macro_depth: directive.depth, |
@@ -1062,13 +1063,67 @@ impl DefCollector<'_> { | |||
1062 | .collect(&[*mod_item]); | 1063 | .collect(&[*mod_item]); |
1063 | 1064 | ||
1064 | // Remove the original directive since we resolved it. | 1065 | // Remove the original directive since we resolved it. |
1066 | res = ReachedFixedPoint::No; | ||
1065 | return false; | 1067 | return false; |
1066 | } | 1068 | } |
1067 | } | 1069 | } |
1068 | } | 1070 | } |
1069 | 1071 | ||
1072 | if !self.db.enable_proc_attr_macros() { | ||
1073 | return true; | ||
1074 | } | ||
1075 | |||
1070 | // Not resolved to a derive helper, so try to resolve as a macro. | 1076 | // Not resolved to a derive helper, so try to resolve as a macro. |
1071 | // FIXME: not yet :) | 1077 | match attr_macro_as_call_id( |
1078 | ast_id, | ||
1079 | attr, | ||
1080 | self.db, | ||
1081 | self.def_map.krate, | ||
1082 | &resolver, | ||
1083 | ) { | ||
1084 | Ok(call_id) => { | ||
1085 | let loc: MacroCallLoc = self.db.lookup_intern_macro(call_id); | ||
1086 | if let MacroDefKind::ProcMacro(exp, ..) = &loc.def.kind { | ||
1087 | if exp.is_dummy() { | ||
1088 | // Proc macros that cannot be expanded are treated as not | ||
1089 | // resolved, in order to fall back later. | ||
1090 | self.def_map.diagnostics.push( | ||
1091 | DefDiagnostic::unresolved_proc_macro( | ||
1092 | directive.module_id, | ||
1093 | loc.kind, | ||
1094 | ), | ||
1095 | ); | ||
1096 | |||
1097 | let file_id = ast_id.ast_id.file_id; | ||
1098 | let item_tree = self.db.file_item_tree(file_id); | ||
1099 | let mod_dir = self.mod_dirs[&directive.module_id].clone(); | ||
1100 | self.skip_attrs | ||
1101 | .insert(InFile::new(file_id, *mod_item), attr.id); | ||
1102 | ModCollector { | ||
1103 | def_collector: &mut *self, | ||
1104 | macro_depth: directive.depth, | ||
1105 | module_id: directive.module_id, | ||
1106 | file_id, | ||
1107 | item_tree: &item_tree, | ||
1108 | mod_dir, | ||
1109 | } | ||
1110 | .collect(&[*mod_item]); | ||
1111 | |||
1112 | // Remove the macro directive. | ||
1113 | return false; | ||
1114 | } | ||
1115 | } | ||
1116 | |||
1117 | self.def_map.modules[directive.module_id] | ||
1118 | .scope | ||
1119 | .add_attr_macro_invoc(ast_id.ast_id, call_id); | ||
1120 | |||
1121 | resolved.push((directive.module_id, call_id, directive.depth)); | ||
1122 | res = ReachedFixedPoint::No; | ||
1123 | return false; | ||
1124 | } | ||
1125 | Err(UnresolvedMacro { .. }) => (), | ||
1126 | } | ||
1072 | } | 1127 | } |
1073 | } | 1128 | } |
1074 | 1129 | ||
@@ -1296,7 +1351,7 @@ impl ModCollector<'_, '_> { | |||
1296 | let imports = Import::from_use( | 1351 | let imports = Import::from_use( |
1297 | self.def_collector.db, | 1352 | self.def_collector.db, |
1298 | krate, | 1353 | krate, |
1299 | &self.item_tree, | 1354 | self.item_tree, |
1300 | ItemTreeId::new(self.file_id, import_id), | 1355 | ItemTreeId::new(self.file_id, import_id), |
1301 | ); | 1356 | ); |
1302 | self.def_collector.unresolved_imports.extend(imports.into_iter().map( | 1357 | self.def_collector.unresolved_imports.extend(imports.into_iter().map( |
@@ -1313,7 +1368,7 @@ impl ModCollector<'_, '_> { | |||
1313 | import: Import::from_extern_crate( | 1368 | import: Import::from_extern_crate( |
1314 | self.def_collector.db, | 1369 | self.def_collector.db, |
1315 | krate, | 1370 | krate, |
1316 | &self.item_tree, | 1371 | self.item_tree, |
1317 | ItemTreeId::new(self.file_id, import_id), | 1372 | ItemTreeId::new(self.file_id, import_id), |
1318 | ), | 1373 | ), |
1319 | status: PartialResolvedImport::Unresolved, | 1374 | status: PartialResolvedImport::Unresolved, |
@@ -1628,7 +1683,7 @@ impl ModCollector<'_, '_> { | |||
1628 | self.def_collector.unresolved_macros.push(MacroDirective { | 1683 | self.def_collector.unresolved_macros.push(MacroDirective { |
1629 | module_id: self.module_id, | 1684 | module_id: self.module_id, |
1630 | depth: self.macro_depth + 1, | 1685 | depth: self.macro_depth + 1, |
1631 | kind: MacroDirectiveKind::Attr { ast_id, attr: attr.id, mod_item }, | 1686 | kind: MacroDirectiveKind::Attr { ast_id, attr: attr.clone(), mod_item }, |
1632 | }); | 1687 | }); |
1633 | 1688 | ||
1634 | return Err(()); | 1689 | return Err(()); |
@@ -1782,7 +1837,8 @@ impl ModCollector<'_, '_> { | |||
1782 | let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into()); | 1837 | let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into()); |
1783 | if attrs.by_key("rustc_builtin_macro").exists() { | 1838 | if attrs.by_key("rustc_builtin_macro").exists() { |
1784 | let macro_id = find_builtin_macro(&mac.name, krate, ast_id) | 1839 | let macro_id = find_builtin_macro(&mac.name, krate, ast_id) |
1785 | .or_else(|| find_builtin_derive(&mac.name, krate, ast_id)); | 1840 | .or_else(|| find_builtin_derive(&mac.name, krate, ast_id)) |
1841 | .or_else(|| find_builtin_attr(&mac.name, krate, ast_id)); | ||
1786 | 1842 | ||
1787 | match macro_id { | 1843 | match macro_id { |
1788 | Some(macro_id) => { | 1844 | Some(macro_id) => { |
@@ -1833,7 +1889,7 @@ impl ModCollector<'_, '_> { | |||
1833 | self.def_collector.def_map.with_ancestor_maps( | 1889 | self.def_collector.def_map.with_ancestor_maps( |
1834 | self.def_collector.db, | 1890 | self.def_collector.db, |
1835 | self.module_id, | 1891 | self.module_id, |
1836 | &mut |map, module| map[module].scope.get_legacy_macro(&name), | 1892 | &mut |map, module| map[module].scope.get_legacy_macro(name), |
1837 | ) | 1893 | ) |
1838 | }) | 1894 | }) |
1839 | }, | 1895 | }, |
@@ -1937,7 +1993,7 @@ mod tests { | |||
1937 | } | 1993 | } |
1938 | 1994 | ||
1939 | fn do_resolve(code: &str) -> DefMap { | 1995 | fn do_resolve(code: &str) -> DefMap { |
1940 | let (db, _file_id) = TestDB::with_single_file(&code); | 1996 | let (db, _file_id) = TestDB::with_single_file(code); |
1941 | let krate = db.test_crate(); | 1997 | let krate = db.test_crate(); |
1942 | 1998 | ||
1943 | let edition = db.crate_graph()[krate].edition; | 1999 | let edition = db.crate_graph()[krate].edition; |
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs index c984148c3..629bc7952 100644 --- a/crates/hir_def/src/nameres/path_resolution.rs +++ b/crates/hir_def/src/nameres/path_resolution.rs | |||
@@ -93,7 +93,7 @@ impl DefMap { | |||
93 | let mut vis = match visibility { | 93 | let mut vis = match visibility { |
94 | RawVisibility::Module(path) => { | 94 | RawVisibility::Module(path) => { |
95 | let (result, remaining) = | 95 | let (result, remaining) = |
96 | self.resolve_path(db, original_module, &path, BuiltinShadowMode::Module); | 96 | self.resolve_path(db, original_module, path, BuiltinShadowMode::Module); |
97 | if remaining.is_some() { | 97 | if remaining.is_some() { |
98 | return None; | 98 | return None; |
99 | } | 99 | } |
@@ -205,7 +205,7 @@ impl DefMap { | |||
205 | None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), | 205 | None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), |
206 | }; | 206 | }; |
207 | log::debug!("resolving {:?} in crate root (+ extern prelude)", segment); | 207 | log::debug!("resolving {:?} in crate root (+ extern prelude)", segment); |
208 | self.resolve_name_in_crate_root_or_extern_prelude(db, &segment) | 208 | self.resolve_name_in_crate_root_or_extern_prelude(db, segment) |
209 | } | 209 | } |
210 | PathKind::Plain => { | 210 | PathKind::Plain => { |
211 | let (_, segment) = match segments.next() { | 211 | let (_, segment) = match segments.next() { |
@@ -222,7 +222,7 @@ impl DefMap { | |||
222 | if path.segments().len() == 1 { shadow } else { BuiltinShadowMode::Module }; | 222 | if path.segments().len() == 1 { shadow } else { BuiltinShadowMode::Module }; |
223 | 223 | ||
224 | log::debug!("resolving {:?} in module", segment); | 224 | log::debug!("resolving {:?} in module", segment); |
225 | self.resolve_name_in_module(db, original_module, &segment, prefer_module) | 225 | self.resolve_name_in_module(db, original_module, segment, prefer_module) |
226 | } | 226 | } |
227 | PathKind::Super(lvl) => { | 227 | PathKind::Super(lvl) => { |
228 | let mut module = original_module; | 228 | let mut module = original_module; |
@@ -269,7 +269,7 @@ impl DefMap { | |||
269 | Some((_, segment)) => segment, | 269 | Some((_, segment)) => segment, |
270 | None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), | 270 | None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), |
271 | }; | 271 | }; |
272 | if let Some(def) = self.extern_prelude.get(&segment) { | 272 | if let Some(def) = self.extern_prelude.get(segment) { |
273 | log::debug!("absolute path {:?} resolved to crate {:?}", path, def); | 273 | log::debug!("absolute path {:?} resolved to crate {:?}", path, def); |
274 | PerNs::types(*def, Visibility::Public) | 274 | PerNs::types(*def, Visibility::Public) |
275 | } else { | 275 | } else { |
@@ -319,13 +319,13 @@ impl DefMap { | |||
319 | }; | 319 | }; |
320 | 320 | ||
321 | // Since it is a qualified path here, it should not contains legacy macros | 321 | // Since it is a qualified path here, it should not contains legacy macros |
322 | module_data.scope.get(&segment) | 322 | module_data.scope.get(segment) |
323 | } | 323 | } |
324 | ModuleDefId::AdtId(AdtId::EnumId(e)) => { | 324 | ModuleDefId::AdtId(AdtId::EnumId(e)) => { |
325 | // enum variant | 325 | // enum variant |
326 | cov_mark::hit!(can_import_enum_variant); | 326 | cov_mark::hit!(can_import_enum_variant); |
327 | let enum_data = db.enum_data(e); | 327 | let enum_data = db.enum_data(e); |
328 | match enum_data.variant(&segment) { | 328 | match enum_data.variant(segment) { |
329 | Some(local_id) => { | 329 | Some(local_id) => { |
330 | let variant = EnumVariantId { parent: e, local_id }; | 330 | let variant = EnumVariantId { parent: e, local_id }; |
331 | match &*enum_data.variants[local_id].variant_data { | 331 | match &*enum_data.variants[local_id].variant_data { |
diff --git a/crates/hir_def/src/nameres/tests.rs b/crates/hir_def/src/nameres/tests.rs index 58c01354a..cf43f2a96 100644 --- a/crates/hir_def/src/nameres/tests.rs +++ b/crates/hir_def/src/nameres/tests.rs | |||
@@ -2,7 +2,6 @@ mod globs; | |||
2 | mod incremental; | 2 | mod incremental; |
3 | mod macros; | 3 | mod macros; |
4 | mod mod_resolution; | 4 | mod mod_resolution; |
5 | mod diagnostics; | ||
6 | mod primitives; | 5 | mod primitives; |
7 | 6 | ||
8 | use std::sync::Arc; | 7 | use std::sync::Arc; |
diff --git a/crates/hir_def/src/nameres/tests/diagnostics.rs b/crates/hir_def/src/nameres/tests/diagnostics.rs deleted file mode 100644 index ec6670952..000000000 --- a/crates/hir_def/src/nameres/tests/diagnostics.rs +++ /dev/null | |||
@@ -1,229 +0,0 @@ | |||
1 | use base_db::fixture::WithFixture; | ||
2 | |||
3 | use crate::test_db::TestDB; | ||
4 | |||
5 | fn check_diagnostics(ra_fixture: &str) { | ||
6 | let db: TestDB = TestDB::with_files(ra_fixture); | ||
7 | db.check_diagnostics(); | ||
8 | } | ||
9 | |||
10 | fn check_no_diagnostics(ra_fixture: &str) { | ||
11 | let db: TestDB = TestDB::with_files(ra_fixture); | ||
12 | db.check_no_diagnostics(); | ||
13 | } | ||
14 | |||
15 | #[test] | ||
16 | fn unresolved_import() { | ||
17 | check_diagnostics( | ||
18 | r" | ||
19 | use does_exist; | ||
20 | use does_not_exist; | ||
21 | //^^^^^^^^^^^^^^^^^^^ UnresolvedImport | ||
22 | |||
23 | mod does_exist {} | ||
24 | ", | ||
25 | ); | ||
26 | } | ||
27 | |||
28 | #[test] | ||
29 | fn unresolved_extern_crate() { | ||
30 | check_diagnostics( | ||
31 | r" | ||
32 | //- /main.rs crate:main deps:core | ||
33 | extern crate core; | ||
34 | extern crate doesnotexist; | ||
35 | //^^^^^^^^^^^^^^^^^^^^^^^^^^ UnresolvedExternCrate | ||
36 | //- /lib.rs crate:core | ||
37 | ", | ||
38 | ); | ||
39 | } | ||
40 | |||
41 | #[test] | ||
42 | fn extern_crate_self_as() { | ||
43 | cov_mark::check!(extern_crate_self_as); | ||
44 | check_diagnostics( | ||
45 | r" | ||
46 | //- /lib.rs | ||
47 | extern crate doesnotexist; | ||
48 | //^^^^^^^^^^^^^^^^^^^^^^^^^^ UnresolvedExternCrate | ||
49 | // Should not error. | ||
50 | extern crate self as foo; | ||
51 | struct Foo; | ||
52 | use foo::Foo as Bar; | ||
53 | ", | ||
54 | ); | ||
55 | } | ||
56 | |||
57 | #[test] | ||
58 | fn dedup_unresolved_import_from_unresolved_crate() { | ||
59 | check_diagnostics( | ||
60 | r" | ||
61 | //- /main.rs crate:main | ||
62 | mod a { | ||
63 | extern crate doesnotexist; | ||
64 | //^^^^^^^^^^^^^^^^^^^^^^^^^^ UnresolvedExternCrate | ||
65 | |||
66 | // Should not error, since we already errored for the missing crate. | ||
67 | use doesnotexist::{self, bla, *}; | ||
68 | |||
69 | use crate::doesnotexist; | ||
70 | //^^^^^^^^^^^^^^^^^^^^^^^^ UnresolvedImport | ||
71 | } | ||
72 | |||
73 | mod m { | ||
74 | use super::doesnotexist; | ||
75 | //^^^^^^^^^^^^^^^^^^^^^^^^ UnresolvedImport | ||
76 | } | ||
77 | ", | ||
78 | ); | ||
79 | } | ||
80 | |||
81 | #[test] | ||
82 | fn unresolved_module() { | ||
83 | check_diagnostics( | ||
84 | r" | ||
85 | //- /lib.rs | ||
86 | mod foo; | ||
87 | mod bar; | ||
88 | //^^^^^^^^ UnresolvedModule | ||
89 | mod baz {} | ||
90 | //- /foo.rs | ||
91 | ", | ||
92 | ); | ||
93 | } | ||
94 | |||
95 | #[test] | ||
96 | fn inactive_item() { | ||
97 | // Additional tests in `cfg` crate. This only tests disabled cfgs. | ||
98 | |||
99 | check_diagnostics( | ||
100 | r#" | ||
101 | //- /lib.rs | ||
102 | #[cfg(no)] pub fn f() {} | ||
103 | //^^^^^^^^^^^^^^^^^^^^^^^^ UnconfiguredCode | ||
104 | |||
105 | #[cfg(no)] #[cfg(no2)] mod m; | ||
106 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UnconfiguredCode | ||
107 | |||
108 | #[cfg(all(not(a), b))] enum E {} | ||
109 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UnconfiguredCode | ||
110 | |||
111 | #[cfg(feature = "std")] use std; | ||
112 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UnconfiguredCode | ||
113 | "#, | ||
114 | ); | ||
115 | } | ||
116 | |||
117 | /// Tests that `cfg` attributes behind `cfg_attr` is handled properly. | ||
118 | #[test] | ||
119 | fn inactive_via_cfg_attr() { | ||
120 | cov_mark::check!(cfg_attr_active); | ||
121 | check_diagnostics( | ||
122 | r#" | ||
123 | //- /lib.rs | ||
124 | #[cfg_attr(not(never), cfg(no))] fn f() {} | ||
125 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UnconfiguredCode | ||
126 | |||
127 | #[cfg_attr(not(never), cfg(not(no)))] fn f() {} | ||
128 | |||
129 | #[cfg_attr(never, cfg(no))] fn g() {} | ||
130 | |||
131 | #[cfg_attr(not(never), inline, cfg(no))] fn h() {} | ||
132 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UnconfiguredCode | ||
133 | "#, | ||
134 | ); | ||
135 | } | ||
136 | |||
137 | #[test] | ||
138 | fn unresolved_legacy_scope_macro() { | ||
139 | check_diagnostics( | ||
140 | r#" | ||
141 | //- /lib.rs | ||
142 | macro_rules! m { () => {} } | ||
143 | |||
144 | m!(); | ||
145 | m2!(); | ||
146 | //^^^^^^ UnresolvedMacroCall | ||
147 | "#, | ||
148 | ); | ||
149 | } | ||
150 | |||
151 | #[test] | ||
152 | fn unresolved_module_scope_macro() { | ||
153 | check_diagnostics( | ||
154 | r#" | ||
155 | //- /lib.rs | ||
156 | mod mac { | ||
157 | #[macro_export] | ||
158 | macro_rules! m { () => {} } | ||
159 | } | ||
160 | |||
161 | self::m!(); | ||
162 | self::m2!(); | ||
163 | //^^^^^^^^^^^^ UnresolvedMacroCall | ||
164 | "#, | ||
165 | ); | ||
166 | } | ||
167 | |||
168 | #[test] | ||
169 | fn builtin_macro_fails_expansion() { | ||
170 | check_diagnostics( | ||
171 | r#" | ||
172 | //- /lib.rs | ||
173 | #[rustc_builtin_macro] | ||
174 | macro_rules! include { () => {} } | ||
175 | |||
176 | include!("doesntexist"); | ||
177 | //^^^^^^^^^^^^^^^^^^^^^^^^ failed to load file `doesntexist` | ||
178 | "#, | ||
179 | ); | ||
180 | } | ||
181 | |||
182 | #[test] | ||
183 | fn include_macro_should_allow_empty_content() { | ||
184 | check_no_diagnostics( | ||
185 | r#" | ||
186 | //- /lib.rs | ||
187 | #[rustc_builtin_macro] | ||
188 | macro_rules! include { () => {} } | ||
189 | |||
190 | include!("bar.rs"); | ||
191 | //- /bar.rs | ||
192 | // empty | ||
193 | "#, | ||
194 | ); | ||
195 | } | ||
196 | |||
197 | #[test] | ||
198 | fn good_out_dir_diagnostic() { | ||
199 | check_diagnostics( | ||
200 | r#" | ||
201 | #[rustc_builtin_macro] | ||
202 | macro_rules! include { () => {} } | ||
203 | #[rustc_builtin_macro] | ||
204 | macro_rules! env { () => {} } | ||
205 | #[rustc_builtin_macro] | ||
206 | macro_rules! concat { () => {} } | ||
207 | |||
208 | include!(concat!(env!("OUT_DIR"), "/out.rs")); | ||
209 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `OUT_DIR` not set, enable "run build scripts" to fix | ||
210 | "#, | ||
211 | ); | ||
212 | } | ||
213 | |||
214 | #[test] | ||
215 | fn register_attr_and_tool() { | ||
216 | cov_mark::check!(register_attr); | ||
217 | cov_mark::check!(register_tool); | ||
218 | check_no_diagnostics( | ||
219 | r#" | ||
220 | #![register_tool(tool)] | ||
221 | #![register_attr(attr)] | ||
222 | |||
223 | #[tool::path] | ||
224 | #[attr] | ||
225 | struct S; | ||
226 | "#, | ||
227 | ); | ||
228 | // NB: we don't currently emit diagnostics here | ||
229 | } | ||
diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs index f6220aa92..27345d07c 100644 --- a/crates/hir_def/src/path/lower.rs +++ b/crates/hir_def/src/path/lower.rs | |||
@@ -208,13 +208,13 @@ fn lower_generic_args_from_fn_path( | |||
208 | let params = params?; | 208 | let params = params?; |
209 | let mut param_types = Vec::new(); | 209 | let mut param_types = Vec::new(); |
210 | for param in params.params() { | 210 | for param in params.params() { |
211 | let type_ref = TypeRef::from_ast_opt(&ctx, param.ty()); | 211 | let type_ref = TypeRef::from_ast_opt(ctx, param.ty()); |
212 | param_types.push(type_ref); | 212 | param_types.push(type_ref); |
213 | } | 213 | } |
214 | let arg = GenericArg::Type(TypeRef::Tuple(param_types)); | 214 | let arg = GenericArg::Type(TypeRef::Tuple(param_types)); |
215 | args.push(arg); | 215 | args.push(arg); |
216 | if let Some(ret_type) = ret_type { | 216 | if let Some(ret_type) = ret_type { |
217 | let type_ref = TypeRef::from_ast_opt(&ctx, ret_type.ty()); | 217 | let type_ref = TypeRef::from_ast_opt(ctx, ret_type.ty()); |
218 | bindings.push(AssociatedTypeBinding { | 218 | bindings.push(AssociatedTypeBinding { |
219 | name: name![Output], | 219 | name: name![Output], |
220 | type_ref: Some(type_ref), | 220 | type_ref: Some(type_ref), |
diff --git a/crates/hir_def/src/per_ns.rs b/crates/hir_def/src/per_ns.rs index a594afce6..a9f13cb82 100644 --- a/crates/hir_def/src/per_ns.rs +++ b/crates/hir_def/src/per_ns.rs | |||
@@ -62,6 +62,7 @@ impl PerNs { | |||
62 | } | 62 | } |
63 | 63 | ||
64 | pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs { | 64 | pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs { |
65 | let _p = profile::span("PerNs::filter_visibility"); | ||
65 | PerNs { | 66 | PerNs { |
66 | types: self.types.filter(|(_, v)| f(*v)), | 67 | types: self.types.filter(|(_, v)| f(*v)), |
67 | values: self.values.filter(|(_, v)| f(*v)), | 68 | values: self.values.filter(|(_, v)| f(*v)), |
@@ -86,6 +87,7 @@ impl PerNs { | |||
86 | } | 87 | } |
87 | 88 | ||
88 | pub fn iter_items(self) -> impl Iterator<Item = ItemInNs> { | 89 | pub fn iter_items(self) -> impl Iterator<Item = ItemInNs> { |
90 | let _p = profile::span("PerNs::iter_items"); | ||
89 | self.types | 91 | self.types |
90 | .map(|it| ItemInNs::Types(it.0)) | 92 | .map(|it| ItemInNs::Types(it.0)) |
91 | .into_iter() | 93 | .into_iter() |
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index fb8a6f260..d4681fa3e 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs | |||
@@ -133,7 +133,7 @@ impl Resolver { | |||
133 | Some(it) => it, | 133 | Some(it) => it, |
134 | None => return PerNs::none(), | 134 | None => return PerNs::none(), |
135 | }; | 135 | }; |
136 | let (module_res, segment_index) = item_map.resolve_path(db, module, &path, shadow); | 136 | let (module_res, segment_index) = item_map.resolve_path(db, module, path, shadow); |
137 | if segment_index.is_some() { | 137 | if segment_index.is_some() { |
138 | return PerNs::none(); | 138 | return PerNs::none(); |
139 | } | 139 | } |
@@ -150,7 +150,7 @@ impl Resolver { | |||
150 | path: &ModPath, | 150 | path: &ModPath, |
151 | ) -> Option<TraitId> { | 151 | ) -> Option<TraitId> { |
152 | let (item_map, module) = self.module_scope()?; | 152 | let (item_map, module) = self.module_scope()?; |
153 | let (module_res, ..) = item_map.resolve_path(db, module, &path, BuiltinShadowMode::Module); | 153 | let (module_res, ..) = item_map.resolve_path(db, module, path, BuiltinShadowMode::Module); |
154 | match module_res.take_types()? { | 154 | match module_res.take_types()? { |
155 | ModuleDefId::TraitId(it) => Some(it), | 155 | ModuleDefId::TraitId(it) => Some(it), |
156 | _ => None, | 156 | _ => None, |
@@ -325,7 +325,7 @@ impl Resolver { | |||
325 | path: &ModPath, | 325 | path: &ModPath, |
326 | ) -> Option<MacroDefId> { | 326 | ) -> Option<MacroDefId> { |
327 | let (item_map, module) = self.module_scope()?; | 327 | let (item_map, module) = self.module_scope()?; |
328 | item_map.resolve_path(db, module, &path, BuiltinShadowMode::Other).0.take_macros() | 328 | item_map.resolve_path(db, module, path, BuiltinShadowMode::Other).0.take_macros() |
329 | } | 329 | } |
330 | 330 | ||
331 | pub fn process_all_names(&self, db: &dyn DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) { | 331 | pub fn process_all_names(&self, db: &dyn DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) { |
@@ -561,7 +561,7 @@ impl ModuleItemMap { | |||
561 | path: &ModPath, | 561 | path: &ModPath, |
562 | ) -> Option<ResolveValueResult> { | 562 | ) -> Option<ResolveValueResult> { |
563 | let (module_def, idx) = | 563 | let (module_def, idx) = |
564 | self.def_map.resolve_path_locally(db, self.module_id, &path, BuiltinShadowMode::Other); | 564 | self.def_map.resolve_path_locally(db, self.module_id, path, BuiltinShadowMode::Other); |
565 | match idx { | 565 | match idx { |
566 | None => { | 566 | None => { |
567 | let value = to_value_ns(module_def)?; | 567 | let value = to_value_ns(module_def)?; |
@@ -591,7 +591,7 @@ impl ModuleItemMap { | |||
591 | path: &ModPath, | 591 | path: &ModPath, |
592 | ) -> Option<(TypeNs, Option<usize>)> { | 592 | ) -> Option<(TypeNs, Option<usize>)> { |
593 | let (module_def, idx) = | 593 | let (module_def, idx) = |
594 | self.def_map.resolve_path_locally(db, self.module_id, &path, BuiltinShadowMode::Other); | 594 | self.def_map.resolve_path_locally(db, self.module_id, path, BuiltinShadowMode::Other); |
595 | let res = to_type_ns(module_def)?; | 595 | let res = to_type_ns(module_def)?; |
596 | Some((res, idx)) | 596 | Some((res, idx)) |
597 | } | 597 | } |
diff --git a/crates/hir_def/src/test_db.rs b/crates/hir_def/src/test_db.rs index e840fe5e8..2635b556e 100644 --- a/crates/hir_def/src/test_db.rs +++ b/crates/hir_def/src/test_db.rs | |||
@@ -6,19 +6,16 @@ use std::{ | |||
6 | }; | 6 | }; |
7 | 7 | ||
8 | use base_db::{ | 8 | use base_db::{ |
9 | salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, FilePosition, FileRange, Upcast, | 9 | salsa, AnchoredPath, CrateId, FileId, FileLoader, FileLoaderDelegate, FilePosition, |
10 | SourceDatabase, Upcast, | ||
10 | }; | 11 | }; |
11 | use base_db::{AnchoredPath, SourceDatabase}; | ||
12 | use hir_expand::{db::AstDatabase, InFile}; | 12 | use hir_expand::{db::AstDatabase, InFile}; |
13 | use rustc_hash::FxHashMap; | ||
14 | use rustc_hash::FxHashSet; | 13 | use rustc_hash::FxHashSet; |
15 | use syntax::{algo, ast, AstNode, SyntaxNode, SyntaxNodePtr, TextRange, TextSize}; | 14 | use syntax::{algo, ast, AstNode}; |
16 | use test_utils::extract_annotations; | ||
17 | 15 | ||
18 | use crate::{ | 16 | use crate::{ |
19 | body::BodyDiagnostic, | ||
20 | db::DefDatabase, | 17 | db::DefDatabase, |
21 | nameres::{diagnostics::DefDiagnosticKind, DefMap, ModuleSource}, | 18 | nameres::{DefMap, ModuleSource}, |
22 | src::HasSource, | 19 | src::HasSource, |
23 | LocalModuleId, Lookup, ModuleDefId, ModuleId, | 20 | LocalModuleId, Lookup, ModuleDefId, ModuleId, |
24 | }; | 21 | }; |
@@ -30,12 +27,19 @@ use crate::{ | |||
30 | crate::db::InternDatabaseStorage, | 27 | crate::db::InternDatabaseStorage, |
31 | crate::db::DefDatabaseStorage | 28 | crate::db::DefDatabaseStorage |
32 | )] | 29 | )] |
33 | #[derive(Default)] | ||
34 | pub(crate) struct TestDB { | 30 | pub(crate) struct TestDB { |
35 | storage: salsa::Storage<TestDB>, | 31 | storage: salsa::Storage<TestDB>, |
36 | events: Mutex<Option<Vec<salsa::Event>>>, | 32 | events: Mutex<Option<Vec<salsa::Event>>>, |
37 | } | 33 | } |
38 | 34 | ||
35 | impl Default for TestDB { | ||
36 | fn default() -> Self { | ||
37 | let mut this = Self { storage: Default::default(), events: Default::default() }; | ||
38 | this.set_enable_proc_attr_macros(true); | ||
39 | this | ||
40 | } | ||
41 | } | ||
42 | |||
39 | impl Upcast<dyn AstDatabase> for TestDB { | 43 | impl Upcast<dyn AstDatabase> for TestDB { |
40 | fn upcast(&self) -> &(dyn AstDatabase + 'static) { | 44 | fn upcast(&self) -> &(dyn AstDatabase + 'static) { |
41 | &*self | 45 | &*self |
@@ -238,145 +242,4 @@ impl TestDB { | |||
238 | }) | 242 | }) |
239 | .collect() | 243 | .collect() |
240 | } | 244 | } |
241 | |||
242 | pub(crate) fn extract_annotations(&self) -> FxHashMap<FileId, Vec<(TextRange, String)>> { | ||
243 | let mut files = Vec::new(); | ||
244 | let crate_graph = self.crate_graph(); | ||
245 | for krate in crate_graph.iter() { | ||
246 | let crate_def_map = self.crate_def_map(krate); | ||
247 | for (module_id, _) in crate_def_map.modules() { | ||
248 | let file_id = crate_def_map[module_id].origin.file_id(); | ||
249 | files.extend(file_id) | ||
250 | } | ||
251 | } | ||
252 | assert!(!files.is_empty()); | ||
253 | files | ||
254 | .into_iter() | ||
255 | .filter_map(|file_id| { | ||
256 | let text = self.file_text(file_id); | ||
257 | let annotations = extract_annotations(&text); | ||
258 | if annotations.is_empty() { | ||
259 | return None; | ||
260 | } | ||
261 | Some((file_id, annotations)) | ||
262 | }) | ||
263 | .collect() | ||
264 | } | ||
265 | |||
266 | pub(crate) fn diagnostics(&self, cb: &mut dyn FnMut(FileRange, String)) { | ||
267 | let crate_graph = self.crate_graph(); | ||
268 | for krate in crate_graph.iter() { | ||
269 | let crate_def_map = self.crate_def_map(krate); | ||
270 | |||
271 | for diag in crate_def_map.diagnostics() { | ||
272 | let (node, message): (InFile<SyntaxNode>, &str) = match &diag.kind { | ||
273 | DefDiagnosticKind::UnresolvedModule { ast, .. } => { | ||
274 | let node = ast.to_node(self.upcast()); | ||
275 | (InFile::new(ast.file_id, node.syntax().clone()), "UnresolvedModule") | ||
276 | } | ||
277 | DefDiagnosticKind::UnresolvedExternCrate { ast, .. } => { | ||
278 | let node = ast.to_node(self.upcast()); | ||
279 | (InFile::new(ast.file_id, node.syntax().clone()), "UnresolvedExternCrate") | ||
280 | } | ||
281 | DefDiagnosticKind::UnresolvedImport { id, .. } => { | ||
282 | let item_tree = id.item_tree(self.upcast()); | ||
283 | let import = &item_tree[id.value]; | ||
284 | let node = InFile::new(id.file_id(), import.ast_id).to_node(self.upcast()); | ||
285 | (InFile::new(id.file_id(), node.syntax().clone()), "UnresolvedImport") | ||
286 | } | ||
287 | DefDiagnosticKind::UnconfiguredCode { ast, .. } => { | ||
288 | let node = ast.to_node(self.upcast()); | ||
289 | (InFile::new(ast.file_id, node.syntax().clone()), "UnconfiguredCode") | ||
290 | } | ||
291 | DefDiagnosticKind::UnresolvedProcMacro { ast, .. } => { | ||
292 | (ast.to_node(self.upcast()), "UnresolvedProcMacro") | ||
293 | } | ||
294 | DefDiagnosticKind::UnresolvedMacroCall { ast, .. } => { | ||
295 | let node = ast.to_node(self.upcast()); | ||
296 | (InFile::new(ast.file_id, node.syntax().clone()), "UnresolvedMacroCall") | ||
297 | } | ||
298 | DefDiagnosticKind::MacroError { ast, message } => { | ||
299 | (ast.to_node(self.upcast()), message.as_str()) | ||
300 | } | ||
301 | DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => { | ||
302 | let node = ast.to_node(self.upcast()); | ||
303 | ( | ||
304 | InFile::new(ast.file_id, node.syntax().clone()), | ||
305 | "UnimplementedBuiltinMacro", | ||
306 | ) | ||
307 | } | ||
308 | }; | ||
309 | |||
310 | let frange = node.as_ref().original_file_range(self); | ||
311 | cb(frange, message.to_string()) | ||
312 | } | ||
313 | |||
314 | for (_module_id, module) in crate_def_map.modules() { | ||
315 | for decl in module.scope.declarations() { | ||
316 | if let ModuleDefId::FunctionId(it) = decl { | ||
317 | let source_map = self.body_with_source_map(it.into()).1; | ||
318 | for diag in source_map.diagnostics() { | ||
319 | let (ptr, message): (InFile<SyntaxNodePtr>, &str) = match diag { | ||
320 | BodyDiagnostic::InactiveCode { node, .. } => { | ||
321 | (node.clone().map(|it| it.into()), "InactiveCode") | ||
322 | } | ||
323 | BodyDiagnostic::MacroError { node, message } => { | ||
324 | (node.clone().map(|it| it.into()), message.as_str()) | ||
325 | } | ||
326 | BodyDiagnostic::UnresolvedProcMacro { node } => { | ||
327 | (node.clone().map(|it| it.into()), "UnresolvedProcMacro") | ||
328 | } | ||
329 | BodyDiagnostic::UnresolvedMacroCall { node, .. } => { | ||
330 | (node.clone().map(|it| it.into()), "UnresolvedMacroCall") | ||
331 | } | ||
332 | }; | ||
333 | |||
334 | let root = self.parse_or_expand(ptr.file_id).unwrap(); | ||
335 | let node = ptr.map(|ptr| ptr.to_node(&root)); | ||
336 | let frange = node.as_ref().original_file_range(self); | ||
337 | cb(frange, message.to_string()) | ||
338 | } | ||
339 | } | ||
340 | } | ||
341 | } | ||
342 | } | ||
343 | } | ||
344 | |||
345 | pub(crate) fn check_diagnostics(&self) { | ||
346 | let db: &TestDB = self; | ||
347 | let annotations = db.extract_annotations(); | ||
348 | assert!(!annotations.is_empty()); | ||
349 | |||
350 | let mut actual: FxHashMap<FileId, Vec<(TextRange, String)>> = FxHashMap::default(); | ||
351 | db.diagnostics(&mut |frange, message| { | ||
352 | actual.entry(frange.file_id).or_default().push((frange.range, message)); | ||
353 | }); | ||
354 | |||
355 | for (file_id, diags) in actual.iter_mut() { | ||
356 | diags.sort_by_key(|it| it.0.start()); | ||
357 | let text = db.file_text(*file_id); | ||
358 | // For multiline spans, place them on line start | ||
359 | for (range, content) in diags { | ||
360 | if text[*range].contains('\n') { | ||
361 | *range = TextRange::new(range.start(), range.start() + TextSize::from(1)); | ||
362 | *content = format!("... {}", content); | ||
363 | } | ||
364 | } | ||
365 | } | ||
366 | |||
367 | assert_eq!(annotations, actual); | ||
368 | } | ||
369 | |||
370 | pub(crate) fn check_no_diagnostics(&self) { | ||
371 | let db: &TestDB = self; | ||
372 | let annotations = db.extract_annotations(); | ||
373 | assert!(annotations.is_empty()); | ||
374 | |||
375 | let mut has_diagnostics = false; | ||
376 | db.diagnostics(&mut |_, _| { | ||
377 | has_diagnostics = true; | ||
378 | }); | ||
379 | |||
380 | assert!(!has_diagnostics); | ||
381 | } | ||
382 | } | 245 | } |
diff --git a/crates/hir_def/src/type_ref.rs b/crates/hir_def/src/type_ref.rs index cbde6b940..ffe499973 100644 --- a/crates/hir_def/src/type_ref.rs +++ b/crates/hir_def/src/type_ref.rs | |||
@@ -128,7 +128,7 @@ impl TypeRef { | |||
128 | /// Converts an `ast::TypeRef` to a `hir::TypeRef`. | 128 | /// Converts an `ast::TypeRef` to a `hir::TypeRef`. |
129 | pub fn from_ast(ctx: &LowerCtx, node: ast::Type) -> Self { | 129 | pub fn from_ast(ctx: &LowerCtx, node: ast::Type) -> Self { |
130 | match node { | 130 | match node { |
131 | ast::Type::ParenType(inner) => TypeRef::from_ast_opt(&ctx, inner.ty()), | 131 | ast::Type::ParenType(inner) => TypeRef::from_ast_opt(ctx, inner.ty()), |
132 | ast::Type::TupleType(inner) => { | 132 | ast::Type::TupleType(inner) => { |
133 | TypeRef::Tuple(inner.fields().map(|it| TypeRef::from_ast(ctx, it)).collect()) | 133 | TypeRef::Tuple(inner.fields().map(|it| TypeRef::from_ast(ctx, it)).collect()) |
134 | } | 134 | } |
@@ -142,7 +142,7 @@ impl TypeRef { | |||
142 | .unwrap_or(TypeRef::Error) | 142 | .unwrap_or(TypeRef::Error) |
143 | } | 143 | } |
144 | ast::Type::PtrType(inner) => { | 144 | ast::Type::PtrType(inner) => { |
145 | let inner_ty = TypeRef::from_ast_opt(&ctx, inner.ty()); | 145 | let inner_ty = TypeRef::from_ast_opt(ctx, inner.ty()); |
146 | let mutability = Mutability::from_mutable(inner.mut_token().is_some()); | 146 | let mutability = Mutability::from_mutable(inner.mut_token().is_some()); |
147 | TypeRef::RawPtr(Box::new(inner_ty), mutability) | 147 | TypeRef::RawPtr(Box::new(inner_ty), mutability) |
148 | } | 148 | } |
@@ -156,13 +156,13 @@ impl TypeRef { | |||
156 | .map(ConstScalar::usize_from_literal_expr) | 156 | .map(ConstScalar::usize_from_literal_expr) |
157 | .unwrap_or(ConstScalar::Unknown); | 157 | .unwrap_or(ConstScalar::Unknown); |
158 | 158 | ||
159 | TypeRef::Array(Box::new(TypeRef::from_ast_opt(&ctx, inner.ty())), len) | 159 | TypeRef::Array(Box::new(TypeRef::from_ast_opt(ctx, inner.ty())), len) |
160 | } | 160 | } |
161 | ast::Type::SliceType(inner) => { | 161 | ast::Type::SliceType(inner) => { |
162 | TypeRef::Slice(Box::new(TypeRef::from_ast_opt(&ctx, inner.ty()))) | 162 | TypeRef::Slice(Box::new(TypeRef::from_ast_opt(ctx, inner.ty()))) |
163 | } | 163 | } |
164 | ast::Type::RefType(inner) => { | 164 | ast::Type::RefType(inner) => { |
165 | let inner_ty = TypeRef::from_ast_opt(&ctx, inner.ty()); | 165 | let inner_ty = TypeRef::from_ast_opt(ctx, inner.ty()); |
166 | let lifetime = inner.lifetime().map(|lt| LifetimeRef::new(<)); | 166 | let lifetime = inner.lifetime().map(|lt| LifetimeRef::new(<)); |
167 | let mutability = Mutability::from_mutable(inner.mut_token().is_some()); | 167 | let mutability = Mutability::from_mutable(inner.mut_token().is_some()); |
168 | TypeRef::Reference(Box::new(inner_ty), lifetime, mutability) | 168 | TypeRef::Reference(Box::new(inner_ty), lifetime, mutability) |
@@ -180,7 +180,7 @@ impl TypeRef { | |||
180 | is_varargs = param.dotdotdot_token().is_some(); | 180 | is_varargs = param.dotdotdot_token().is_some(); |
181 | } | 181 | } |
182 | 182 | ||
183 | pl.params().map(|p| p.ty()).map(|it| TypeRef::from_ast_opt(&ctx, it)).collect() | 183 | pl.params().map(|p| p.ty()).map(|it| TypeRef::from_ast_opt(ctx, it)).collect() |
184 | } else { | 184 | } else { |
185 | Vec::new() | 185 | Vec::new() |
186 | }; | 186 | }; |
@@ -188,7 +188,7 @@ impl TypeRef { | |||
188 | TypeRef::Fn(params, is_varargs) | 188 | TypeRef::Fn(params, is_varargs) |
189 | } | 189 | } |
190 | // for types are close enough for our purposes to the inner type for now... | 190 | // for types are close enough for our purposes to the inner type for now... |
191 | ast::Type::ForType(inner) => TypeRef::from_ast_opt(&ctx, inner.ty()), | 191 | ast::Type::ForType(inner) => TypeRef::from_ast_opt(ctx, inner.ty()), |
192 | ast::Type::ImplTraitType(inner) => { | 192 | ast::Type::ImplTraitType(inner) => { |
193 | TypeRef::ImplTrait(type_bounds_from_ast(ctx, inner.type_bound_list())) | 193 | TypeRef::ImplTrait(type_bounds_from_ast(ctx, inner.type_bound_list())) |
194 | } | 194 | } |
@@ -229,7 +229,7 @@ impl TypeRef { | |||
229 | TypeRef::RawPtr(type_ref, _) | 229 | TypeRef::RawPtr(type_ref, _) |
230 | | TypeRef::Reference(type_ref, ..) | 230 | | TypeRef::Reference(type_ref, ..) |
231 | | TypeRef::Array(type_ref, _) | 231 | | TypeRef::Array(type_ref, _) |
232 | | TypeRef::Slice(type_ref) => go(&type_ref, f), | 232 | | TypeRef::Slice(type_ref) => go(type_ref, f), |
233 | TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => { | 233 | TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => { |
234 | for bound in bounds { | 234 | for bound in bounds { |
235 | match bound.as_ref() { | 235 | match bound.as_ref() { |