aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/release.yaml17
-rw-r--r--Cargo.lock11
-rw-r--r--crates/hir/Cargo.toml1
-rw-r--r--crates/hir/src/display.rs441
-rw-r--r--crates/hir/src/lib.rs90
-rw-r--r--crates/hir/src/semantics.rs38
-rw-r--r--crates/hir/src/semantics/source_to_def.rs22
-rw-r--r--crates/hir_def/src/adt.rs10
-rw-r--r--crates/hir_def/src/body/lower.rs105
-rw-r--r--crates/hir_def/src/data.rs22
-rw-r--r--crates/hir_def/src/diagnostics.rs2
-rw-r--r--crates/hir_def/src/item_tree.rs24
-rw-r--r--crates/hir_def/src/item_tree/lower.rs35
-rw-r--r--crates/hir_def/src/nameres/collector.rs33
-rw-r--r--crates/hir_def/src/nameres/tests/diagnostics.rs45
-rw-r--r--crates/hir_def/src/path.rs11
-rw-r--r--crates/hir_expand/src/db.rs3
-rw-r--r--crates/hir_expand/src/lib.rs5
-rw-r--r--crates/hir_expand/src/name.rs2
-rw-r--r--crates/hir_ty/src/diagnostics/decl_check.rs2
-rw-r--r--crates/hir_ty/src/diagnostics/unsafe_check.rs6
-rw-r--r--crates/hir_ty/src/display.rs203
-rw-r--r--crates/hir_ty/src/infer/unify.rs2
-rw-r--r--crates/hir_ty/src/lib.rs27
-rw-r--r--crates/hir_ty/src/lower.rs9
-rw-r--r--crates/hir_ty/src/tests/macros.rs16
-rw-r--r--crates/hir_ty/src/tests/traits.rs216
-rw-r--r--crates/hir_ty/src/traits/chalk.rs2
-rw-r--r--crates/hir_ty/src/traits/chalk/interner.rs7
-rw-r--r--crates/ide/src/call_hierarchy.rs11
-rw-r--r--crates/ide/src/display.rs1
-rw-r--r--crates/ide/src/display/navigation_target.rs14
-rw-r--r--crates/ide/src/doc_links.rs2
-rw-r--r--crates/ide/src/extend_selection.rs13
-rw-r--r--crates/ide/src/goto_definition.rs4
-rw-r--r--crates/ide/src/goto_type_definition.rs2
-rw-r--r--crates/ide/src/hover.rs186
-rw-r--r--crates/ide/src/join_lines.rs44
-rw-r--r--crates/ide/src/matching_brace.rs2
-rw-r--r--crates/ide/src/parent_module.rs79
-rw-r--r--crates/ide/src/references.rs7
-rw-r--r--crates/ide/src/runnables.rs3
-rw-r--r--crates/ide/src/syntax_highlighting.rs19
-rw-r--r--crates/ide/src/syntax_highlighting/format.rs2
-rw-r--r--crates/ide/src/syntax_tree.rs2
-rw-r--r--crates/ide/src/typing.rs2
-rw-r--r--crates/ide_assists/src/handlers/add_turbo_fish.rs2
-rw-r--r--crates/ide_assists/src/handlers/change_visibility.rs2
-rw-r--r--crates/ide_assists/src/handlers/expand_glob_import.rs2
-rw-r--r--crates/ide_assists/src/handlers/extract_function.rs20
-rw-r--r--crates/ide_assists/src/handlers/flip_trait_bound.rs2
-rw-r--r--crates/ide_assists/src/handlers/generate_is_empty_from_len.rs272
-rw-r--r--crates/ide_assists/src/handlers/invert_if.rs2
-rw-r--r--crates/ide_assists/src/handlers/move_bounds.rs62
-rw-r--r--crates/ide_assists/src/handlers/split_import.rs2
-rw-r--r--crates/ide_assists/src/handlers/unwrap_block.rs2
-rw-r--r--crates/ide_assists/src/lib.rs2
-rw-r--r--crates/ide_assists/src/tests/generated.rs29
-rw-r--r--crates/ide_completion/src/completions/dot.rs24
-rw-r--r--crates/ide_completion/src/completions/flyimport.rs8
-rw-r--r--crates/ide_completion/src/completions/fn_param.rs2
-rw-r--r--crates/ide_completion/src/completions/pattern.rs116
-rw-r--r--crates/ide_completion/src/completions/qualified_path.rs56
-rw-r--r--crates/ide_completion/src/completions/trait_impl.rs7
-rw-r--r--crates/ide_completion/src/completions/unqualified_path.rs138
-rw-r--r--crates/ide_completion/src/context.rs21
-rw-r--r--crates/ide_completion/src/lib.rs6
-rw-r--r--crates/ide_completion/src/patterns.rs16
-rw-r--r--crates/ide_completion/src/render.rs230
-rw-r--r--crates/ide_completion/src/render/enum_variant.rs13
-rw-r--r--crates/ide_completion/src/render/function.rs66
-rw-r--r--crates/ide_completion/src/render/pattern.rs36
-rw-r--r--crates/ide_db/src/call_info.rs2
-rw-r--r--crates/ide_ssr/src/resolving.rs2
-rw-r--r--crates/mbe/src/tests.rs11
-rw-r--r--crates/parser/src/grammar.rs6
-rw-r--r--crates/parser/src/grammar/expressions.rs6
-rw-r--r--crates/syntax/Cargo.toml2
-rw-r--r--crates/syntax/src/algo.rs35
-rw-r--r--crates/syntax/src/ast.rs7
-rw-r--r--crates/syntax/src/ast/edit_in_place.rs105
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs10
-rw-r--r--crates/syntax/src/ast/make.rs14
-rw-r--r--crates/syntax/src/ast/node_ext.rs4
-rw-r--r--crates/syntax/src/lib.rs1
-rw-r--r--crates/syntax/src/parsing/reparsing.rs6
-rw-r--r--crates/syntax/src/ted.rs78
-rw-r--r--docs/dev/style.md21
-rw-r--r--editors/code/src/commands.ts24
-rw-r--r--xtask/Cargo.toml2
90 files changed, 2479 insertions, 795 deletions
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index 32c7cf7ef..ae9dccce9 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -13,6 +13,7 @@ env:
13 CARGO_NET_RETRY: 10 13 CARGO_NET_RETRY: 10
14 RUSTFLAGS: "-D warnings -W unreachable-pub" 14 RUSTFLAGS: "-D warnings -W unreachable-pub"
15 RUSTUP_MAX_RETRIES: 10 15 RUSTUP_MAX_RETRIES: 10
16 FETCH_DEPTH: 200
16 17
17jobs: 18jobs:
18 dist-x86_64-pc-windows-msvc: 19 dist-x86_64-pc-windows-msvc:
@@ -24,6 +25,8 @@ jobs:
24 steps: 25 steps:
25 - name: Checkout repository 26 - name: Checkout repository
26 uses: actions/checkout@v2 27 uses: actions/checkout@v2
28 with:
29 fetch-depth: ${{ env.FETCH_DEPTH }}
27 30
28 # We need to disable the existing toolchain to avoid updating rust-docs 31 # We need to disable the existing toolchain to avoid updating rust-docs
29 # which takes a long time. The fastest way to do this is to rename the 32 # which takes a long time. The fastest way to do this is to rename the
@@ -57,6 +60,8 @@ jobs:
57 steps: 60 steps:
58 - name: Checkout repository 61 - name: Checkout repository
59 uses: actions/checkout@v2 62 uses: actions/checkout@v2
63 with:
64 fetch-depth: ${{ env.FETCH_DEPTH }}
60 65
61 - name: Rename existing rust toolchain 66 - name: Rename existing rust toolchain
62 run: Rename-Item C:\Users\runneradmin\.rustup\toolchains\stable-x86_64-pc-windows-msvc C:\Users\runneradmin\.rustup\toolchains\stable-x86_64-pc-windows-msvc.old 67 run: Rename-Item C:\Users\runneradmin\.rustup\toolchains\stable-x86_64-pc-windows-msvc C:\Users\runneradmin\.rustup\toolchains\stable-x86_64-pc-windows-msvc.old
@@ -87,6 +92,8 @@ jobs:
87 steps: 92 steps:
88 - name: Checkout repository 93 - name: Checkout repository
89 uses: actions/checkout@v2 94 uses: actions/checkout@v2
95 with:
96 fetch-depth: ${{ env.FETCH_DEPTH }}
90 97
91 - name: Install Rust toolchain 98 - name: Install Rust toolchain
92 uses: actions-rs/toolchain@v1 99 uses: actions-rs/toolchain@v1
@@ -139,6 +146,8 @@ jobs:
139 146
140 - name: Checkout repository 147 - name: Checkout repository
141 uses: actions/checkout@v2 148 uses: actions/checkout@v2
149 with:
150 fetch-depth: ${{ env.FETCH_DEPTH }}
142 151
143 - name: Dist 152 - name: Dist
144 run: cargo xtask dist 153 run: cargo xtask dist
@@ -159,6 +168,8 @@ jobs:
159 steps: 168 steps:
160 - name: Checkout repository 169 - name: Checkout repository
161 uses: actions/checkout@v2 170 uses: actions/checkout@v2
171 with:
172 fetch-depth: ${{ env.FETCH_DEPTH }}
162 173
163 - name: Install Rust toolchain 174 - name: Install Rust toolchain
164 uses: actions-rs/toolchain@v1 175 uses: actions-rs/toolchain@v1
@@ -193,6 +204,8 @@ jobs:
193 204
194 - name: Checkout repository 205 - name: Checkout repository
195 uses: actions/checkout@v2 206 uses: actions/checkout@v2
207 with:
208 fetch-depth: ${{ env.FETCH_DEPTH }}
196 209
197 - name: Install Rust toolchain 210 - name: Install Rust toolchain
198 uses: actions-rs/toolchain@v1 211 uses: actions-rs/toolchain@v1
@@ -223,6 +236,8 @@ jobs:
223 236
224 - name: Checkout repository 237 - name: Checkout repository
225 uses: actions/checkout@v2 238 uses: actions/checkout@v2
239 with:
240 fetch-depth: ${{ env.FETCH_DEPTH }}
226 241
227 - name: Install Rust toolchain 242 - name: Install Rust toolchain
228 uses: actions-rs/toolchain@v1 243 uses: actions-rs/toolchain@v1
@@ -259,6 +274,8 @@ jobs:
259 274
260 - name: Checkout repository 275 - name: Checkout repository
261 uses: actions/checkout@v2 276 uses: actions/checkout@v2
277 with:
278 fetch-depth: ${{ env.FETCH_DEPTH }}
262 279
263 - run: echo "HEAD_SHA=$(git rev-parse HEAD)" >> $GITHUB_ENV 280 - run: echo "HEAD_SHA=$(git rev-parse HEAD)" >> $GITHUB_ENV
264 - run: 'echo "HEAD_SHA: $HEAD_SHA"' 281 - run: 'echo "HEAD_SHA: $HEAD_SHA"'
diff --git a/Cargo.lock b/Cargo.lock
index b1fef2e80..b99c243a4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,7 +1,5 @@
1# This file is automatically @generated by Cargo. 1# This file is automatically @generated by Cargo.
2# It is not intended for manual editing. 2# It is not intended for manual editing.
3version = 3
4
5[[package]] 3[[package]]
6name = "addr2line" 4name = "addr2line"
7version = "0.14.1" 5version = "0.14.1"
@@ -486,6 +484,7 @@ dependencies = [
486 "log", 484 "log",
487 "profile", 485 "profile",
488 "rustc-hash", 486 "rustc-hash",
487 "smallvec",
489 "stdx", 488 "stdx",
490 "syntax", 489 "syntax",
491 "tt", 490 "tt",
@@ -1325,9 +1324,9 @@ checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"
1325 1324
1326[[package]] 1325[[package]]
1327name = "rowan" 1326name = "rowan"
1328version = "0.12.6" 1327version = "0.13.0-pre.2"
1329source = "registry+https://github.com/rust-lang/crates.io-index" 1328source = "registry+https://github.com/rust-lang/crates.io-index"
1330checksum = "a1b36e449f3702f3b0c821411db1cbdf30fb451726a9456dce5dabcd44420043" 1329checksum = "8f300be7fa17c3fa563d2bc6ab5b1a8d5163162f9111599eda4f86a563714724"
1331dependencies = [ 1330dependencies = [
1332 "countme", 1331 "countme",
1333 "hashbrown", 1332 "hashbrown",
@@ -1810,9 +1809,9 @@ checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
1810 1809
1811[[package]] 1810[[package]]
1812name = "ungrammar" 1811name = "ungrammar"
1813version = "1.11.0" 1812version = "1.12.2"
1814source = "registry+https://github.com/rust-lang/crates.io-index" 1813source = "registry+https://github.com/rust-lang/crates.io-index"
1815checksum = "84c629795d377049f2a1dc5f42cf505dc5ba8b28a5df0a03f4183a24480e4a6a" 1814checksum = "df6586a7c530704efe803d49a0b4132dcbdb4063163df39110548e6b5f2373ba"
1816 1815
1817[[package]] 1816[[package]]
1818name = "unicase" 1817name = "unicase"
diff --git a/crates/hir/Cargo.toml b/crates/hir/Cargo.toml
index d4ea7327e..55e9c3f0c 100644
--- a/crates/hir/Cargo.toml
+++ b/crates/hir/Cargo.toml
@@ -15,6 +15,7 @@ rustc-hash = "1.1.0"
15either = "1.5.3" 15either = "1.5.3"
16arrayvec = "0.5.1" 16arrayvec = "0.5.1"
17itertools = "0.10.0" 17itertools = "0.10.0"
18smallvec = "1.4.0"
18 19
19stdx = { path = "../stdx", version = "0.0.0" } 20stdx = { path = "../stdx", version = "0.0.0" }
20syntax = { path = "../syntax", version = "0.0.0" } 21syntax = { path = "../syntax", version = "0.0.0" }
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
new file mode 100644
index 000000000..44cdcc296
--- /dev/null
+++ b/crates/hir/src/display.rs
@@ -0,0 +1,441 @@
1//! HirDisplay implementations for various hir types.
2use hir_def::{
3 adt::VariantData,
4 generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget},
5 type_ref::{TypeBound, TypeRef},
6 AdtId, GenericDefId,
7};
8use hir_ty::display::{
9 write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError,
10 HirFormatter,
11};
12use syntax::ast::{self, NameOwner};
13
14use crate::{
15 Const, ConstParam, Enum, Field, Function, HasVisibility, Module, Static, Struct, Substs, Trait,
16 Type, TypeAlias, TypeParam, Union, Variant,
17};
18
19impl HirDisplay for Function {
20 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
21 let data = f.db.function_data(self.id);
22 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
23 let qual = &data.qualifier;
24 if qual.is_default {
25 write!(f, "default ")?;
26 }
27 if qual.is_const {
28 write!(f, "const ")?;
29 }
30 if qual.is_async {
31 write!(f, "async ")?;
32 }
33 if qual.is_unsafe {
34 write!(f, "unsafe ")?;
35 }
36 if let Some(abi) = &qual.abi {
37 // FIXME: String escape?
38 write!(f, "extern \"{}\" ", abi)?;
39 }
40 write!(f, "fn {}", data.name)?;
41
42 write_generic_params(GenericDefId::FunctionId(self.id), f)?;
43
44 write!(f, "(")?;
45
46 let write_self_param = |ty: &TypeRef, f: &mut HirFormatter| match ty {
47 TypeRef::Path(p) if p.is_self_type() => write!(f, "self"),
48 TypeRef::Reference(inner, lifetime, mut_) if matches!(&**inner,TypeRef::Path(p) if p.is_self_type()) =>
49 {
50 write!(f, "&")?;
51 if let Some(lifetime) = lifetime {
52 write!(f, "{} ", lifetime.name)?;
53 }
54 if let hir_def::type_ref::Mutability::Mut = mut_ {
55 write!(f, "mut ")?;
56 }
57 write!(f, "self")
58 }
59 _ => {
60 write!(f, "self: ")?;
61 ty.hir_fmt(f)
62 }
63 };
64
65 let mut first = true;
66 for (param, type_ref) in self.assoc_fn_params(f.db).into_iter().zip(&data.params) {
67 if !first {
68 write!(f, ", ")?;
69 } else {
70 first = false;
71 if data.has_self_param {
72 write_self_param(type_ref, f)?;
73 continue;
74 }
75 }
76 match param.pattern_source(f.db) {
77 Some(ast::Pat::IdentPat(p)) if p.name().is_some() => {
78 write!(f, "{}: ", p.name().unwrap())?
79 }
80 _ => write!(f, "_: ")?,
81 }
82 // FIXME: Use resolved `param.ty` or raw `type_ref`?
83 // The former will ignore lifetime arguments currently.
84 type_ref.hir_fmt(f)?;
85 }
86 write!(f, ")")?;
87
88 // `FunctionData::ret_type` will be `::core::future::Future<Output = ...>` for async fns.
89 // Use ugly pattern match to strip the Future trait.
90 // Better way?
91 let ret_type = if !qual.is_async {
92 &data.ret_type
93 } else {
94 match &data.ret_type {
95 TypeRef::ImplTrait(bounds) => match &bounds[0] {
96 TypeBound::Path(path) => {
97 path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings
98 [0]
99 .type_ref
100 .as_ref()
101 .unwrap()
102 }
103 _ => panic!("Async fn ret_type should be impl Future"),
104 },
105 _ => panic!("Async fn ret_type should be impl Future"),
106 }
107 };
108
109 match ret_type {
110 TypeRef::Tuple(tup) if tup.is_empty() => {}
111 ty => {
112 write!(f, " -> ")?;
113 ty.hir_fmt(f)?;
114 }
115 }
116
117 write_where_clause(GenericDefId::FunctionId(self.id), f)?;
118
119 Ok(())
120 }
121}
122
123impl HirDisplay for Struct {
124 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
125 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
126 write!(f, "struct ")?;
127 write!(f, "{}", self.name(f.db))?;
128 let def_id = GenericDefId::AdtId(AdtId::StructId(self.id));
129 write_generic_params(def_id, f)?;
130 write_where_clause(def_id, f)?;
131 Ok(())
132 }
133}
134
135impl HirDisplay for Enum {
136 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
137 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
138 write!(f, "enum ")?;
139 write!(f, "{}", self.name(f.db))?;
140 let def_id = GenericDefId::AdtId(AdtId::EnumId(self.id));
141 write_generic_params(def_id, f)?;
142 write_where_clause(def_id, f)?;
143 Ok(())
144 }
145}
146
147impl HirDisplay for Union {
148 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
149 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
150 write!(f, "union ")?;
151 write!(f, "{}", self.name(f.db))?;
152 let def_id = GenericDefId::AdtId(AdtId::UnionId(self.id));
153 write_generic_params(def_id, f)?;
154 write_where_clause(def_id, f)?;
155 Ok(())
156 }
157}
158
159impl HirDisplay for Field {
160 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
161 write_visibility(self.parent.module(f.db).id, self.visibility(f.db), f)?;
162 write!(f, "{}: ", self.name(f.db))?;
163 self.signature_ty(f.db).hir_fmt(f)
164 }
165}
166
167impl HirDisplay for Variant {
168 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
169 write!(f, "{}", self.name(f.db))?;
170 let data = self.variant_data(f.db);
171 match &*data {
172 VariantData::Unit => {}
173 VariantData::Tuple(fields) => {
174 write!(f, "(")?;
175 let mut first = true;
176 for (_, field) in fields.iter() {
177 if first {
178 first = false;
179 } else {
180 write!(f, ", ")?;
181 }
182 // Enum variant fields must be pub.
183 field.type_ref.hir_fmt(f)?;
184 }
185 write!(f, ")")?;
186 }
187 VariantData::Record(fields) => {
188 write!(f, " {{")?;
189 let mut first = true;
190 for (_, field) in fields.iter() {
191 if first {
192 first = false;
193 write!(f, " ")?;
194 } else {
195 write!(f, ", ")?;
196 }
197 // Enum variant fields must be pub.
198 write!(f, "{}: ", field.name)?;
199 field.type_ref.hir_fmt(f)?;
200 }
201 write!(f, " }}")?;
202 }
203 }
204 Ok(())
205 }
206}
207
208impl HirDisplay for Type {
209 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
210 self.ty.value.hir_fmt(f)
211 }
212}
213
214impl HirDisplay for TypeParam {
215 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
216 write!(f, "{}", self.name(f.db))?;
217 let bounds = f.db.generic_predicates_for_param(self.id);
218 let substs = Substs::type_params(f.db, self.id.parent);
219 let predicates = bounds.iter().cloned().map(|b| b.subst(&substs)).collect::<Vec<_>>();
220 if !(predicates.is_empty() || f.omit_verbose_types()) {
221 write_bounds_like_dyn_trait_with_prefix(":", &predicates, f)?;
222 }
223 Ok(())
224 }
225}
226
227impl HirDisplay for ConstParam {
228 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
229 write!(f, "const {}: ", self.name(f.db))?;
230 self.ty(f.db).hir_fmt(f)
231 }
232}
233
234fn write_generic_params(def: GenericDefId, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
235 let params = f.db.generic_params(def);
236 if params.lifetimes.is_empty()
237 && params.consts.is_empty()
238 && params
239 .types
240 .iter()
241 .all(|(_, param)| !matches!(param.provenance, TypeParamProvenance::TypeParamList))
242 {
243 return Ok(());
244 }
245 write!(f, "<")?;
246
247 let mut first = true;
248 let mut delim = |f: &mut HirFormatter| {
249 if first {
250 first = false;
251 Ok(())
252 } else {
253 write!(f, ", ")
254 }
255 };
256 for (_, lifetime) in params.lifetimes.iter() {
257 delim(f)?;
258 write!(f, "{}", lifetime.name)?;
259 }
260 for (_, ty) in params.types.iter() {
261 if ty.provenance != TypeParamProvenance::TypeParamList {
262 continue;
263 }
264 if let Some(name) = &ty.name {
265 delim(f)?;
266 write!(f, "{}", name)?;
267 if let Some(default) = &ty.default {
268 write!(f, " = ")?;
269 default.hir_fmt(f)?;
270 }
271 }
272 }
273 for (_, konst) in params.consts.iter() {
274 delim(f)?;
275 write!(f, "const {}: ", konst.name)?;
276 konst.ty.hir_fmt(f)?;
277 }
278
279 write!(f, ">")?;
280 Ok(())
281}
282
283fn write_where_clause(def: GenericDefId, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
284 let params = f.db.generic_params(def);
285 if params.where_predicates.is_empty() {
286 return Ok(());
287 }
288
289 let write_target = |target: &WherePredicateTypeTarget, f: &mut HirFormatter| match target {
290 WherePredicateTypeTarget::TypeRef(ty) => ty.hir_fmt(f),
291 WherePredicateTypeTarget::TypeParam(id) => match &params.types[*id].name {
292 Some(name) => write!(f, "{}", name),
293 None => write!(f, "{{unnamed}}"),
294 },
295 };
296
297 write!(f, "\nwhere")?;
298
299 for (pred_idx, pred) in params.where_predicates.iter().enumerate() {
300 let prev_pred =
301 if pred_idx == 0 { None } else { Some(&params.where_predicates[pred_idx - 1]) };
302
303 let new_predicate = |f: &mut HirFormatter| {
304 write!(f, "{}", if pred_idx == 0 { "\n " } else { ",\n " })
305 };
306
307 match pred {
308 WherePredicate::TypeBound { target, bound } => {
309 if matches!(prev_pred, Some(WherePredicate::TypeBound { target: target_, .. }) if target_ == target)
310 {
311 write!(f, " + ")?;
312 } else {
313 new_predicate(f)?;
314 write_target(target, f)?;
315 write!(f, ": ")?;
316 }
317 bound.hir_fmt(f)?;
318 }
319 WherePredicate::Lifetime { target, bound } => {
320 if matches!(prev_pred, Some(WherePredicate::Lifetime { target: target_, .. }) if target_ == target)
321 {
322 write!(f, " + {}", bound.name)?;
323 } else {
324 new_predicate(f)?;
325 write!(f, "{}: {}", target.name, bound.name)?;
326 }
327 }
328 WherePredicate::ForLifetime { lifetimes, target, bound } => {
329 if matches!(
330 prev_pred,
331 Some(WherePredicate::ForLifetime { lifetimes: lifetimes_, target: target_, .. })
332 if lifetimes_ == lifetimes && target_ == target,
333 ) {
334 write!(f, " + ")?;
335 } else {
336 new_predicate(f)?;
337 write!(f, "for<")?;
338 for (idx, lifetime) in lifetimes.iter().enumerate() {
339 if idx != 0 {
340 write!(f, ", ")?;
341 }
342 write!(f, "{}", lifetime)?;
343 }
344 write!(f, "> ")?;
345 write_target(target, f)?;
346 write!(f, ": ")?;
347 }
348 bound.hir_fmt(f)?;
349 }
350 }
351 }
352
353 // End of final predicate. There must be at least one predicate here.
354 write!(f, ",")?;
355
356 Ok(())
357}
358
359impl HirDisplay for Const {
360 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
361 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
362 let data = f.db.const_data(self.id);
363 write!(f, "const ")?;
364 match &data.name {
365 Some(name) => write!(f, "{}: ", name)?,
366 None => write!(f, "_: ")?,
367 }
368 data.type_ref.hir_fmt(f)?;
369 Ok(())
370 }
371}
372
373impl HirDisplay for Static {
374 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
375 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
376 let data = f.db.static_data(self.id);
377 write!(f, "static ")?;
378 if data.mutable {
379 write!(f, "mut ")?;
380 }
381 match &data.name {
382 Some(name) => write!(f, "{}: ", name)?,
383 None => write!(f, "_: ")?,
384 }
385 data.type_ref.hir_fmt(f)?;
386 Ok(())
387 }
388}
389
390impl HirDisplay for Trait {
391 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
392 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
393 let data = f.db.trait_data(self.id);
394 if data.is_unsafe {
395 write!(f, "unsafe ")?;
396 }
397 if data.is_auto {
398 write!(f, "auto ")?;
399 }
400 write!(f, "trait {}", data.name)?;
401 let def_id = GenericDefId::TraitId(self.id);
402 write_generic_params(def_id, f)?;
403 if !data.bounds.is_empty() {
404 write!(f, ": ")?;
405 f.write_joined(&*data.bounds, " + ")?;
406 }
407 write_where_clause(def_id, f)?;
408 Ok(())
409 }
410}
411
412impl HirDisplay for TypeAlias {
413 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
414 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
415 let data = f.db.type_alias_data(self.id);
416 write!(f, "type {}", data.name)?;
417 if !data.bounds.is_empty() {
418 write!(f, ": ")?;
419 f.write_joined(&data.bounds, " + ")?;
420 }
421 if let Some(ty) = &data.type_ref {
422 write!(f, " = ")?;
423 ty.hir_fmt(f)?;
424 }
425 Ok(())
426 }
427}
428
429impl HirDisplay for Module {
430 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
431 // FIXME: Module doesn't have visibility saved in data.
432 match self.name(f.db) {
433 Some(name) => write!(f, "mod {}", name),
434 None if self.crate_root(f.db) == *self => match self.krate().display_name(f.db) {
435 Some(name) => write!(f, "extern crate {}", name),
436 None => write!(f, "extern crate {{unknown}}"),
437 },
438 None => write!(f, "mod {{unnamed}}"),
439 }
440 }
441}
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 079a5f7b8..ad79a79f8 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -29,6 +29,8 @@ mod has_source;
29pub mod diagnostics; 29pub mod diagnostics;
30pub mod db; 30pub mod db;
31 31
32mod display;
33
32use std::{iter, sync::Arc}; 34use std::{iter, sync::Arc};
33 35
34use arrayvec::ArrayVec; 36use arrayvec::ArrayVec;
@@ -50,8 +52,8 @@ use hir_def::{
50use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind}; 52use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind};
51use hir_ty::{ 53use hir_ty::{
52 autoderef, 54 autoderef,
53 display::{write_bounds_like_dyn_trait_with_prefix, HirDisplayError, HirFormatter},
54 method_resolution::{self, TyFingerprint}, 55 method_resolution::{self, TyFingerprint},
56 primitive::UintTy,
55 to_assoc_type_id, 57 to_assoc_type_id,
56 traits::{FnTrait, Solution, SolutionVariables}, 58 traits::{FnTrait, Solution, SolutionVariables},
57 AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate, 59 AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate,
@@ -579,6 +581,12 @@ impl Struct {
579 } 581 }
580} 582}
581 583
584impl HasVisibility for Struct {
585 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
586 db.struct_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
587 }
588}
589
582#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 590#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
583pub struct Union { 591pub struct Union {
584 pub(crate) id: UnionId, 592 pub(crate) id: UnionId,
@@ -611,6 +619,12 @@ impl Union {
611 } 619 }
612} 620}
613 621
622impl HasVisibility for Union {
623 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
624 db.union_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
625 }
626}
627
614#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 628#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
615pub struct Enum { 629pub struct Enum {
616 pub(crate) id: EnumId, 630 pub(crate) id: EnumId,
@@ -638,6 +652,12 @@ impl Enum {
638 } 652 }
639} 653}
640 654
655impl HasVisibility for Enum {
656 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
657 db.enum_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
658 }
659}
660
641#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 661#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
642pub struct Variant { 662pub struct Variant {
643 pub(crate) parent: Enum, 663 pub(crate) parent: Enum,
@@ -829,7 +849,8 @@ impl Function {
829 db.function_data(self.id) 849 db.function_data(self.id)
830 .params 850 .params
831 .iter() 851 .iter()
832 .map(|type_ref| { 852 .enumerate()
853 .map(|(idx, type_ref)| {
833 let ty = Type { 854 let ty = Type {
834 krate, 855 krate,
835 ty: InEnvironment { 856 ty: InEnvironment {
@@ -837,7 +858,7 @@ impl Function {
837 environment: environment.clone(), 858 environment: environment.clone(),
838 }, 859 },
839 }; 860 };
840 Param { ty } 861 Param { func: self, ty, idx }
841 }) 862 })
842 .collect() 863 .collect()
843 } 864 }
@@ -851,7 +872,7 @@ impl Function {
851 } 872 }
852 873
853 pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool { 874 pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
854 db.function_data(self.id).is_unsafe 875 db.function_data(self.id).qualifier.is_unsafe
855 } 876 }
856 877
857 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { 878 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
@@ -900,6 +921,9 @@ impl From<hir_ty::Mutability> for Access {
900 921
901#[derive(Debug)] 922#[derive(Debug)]
902pub struct Param { 923pub struct Param {
924 func: Function,
925 /// The index in parameter list, including self parameter.
926 idx: usize,
903 ty: Type, 927 ty: Type,
904} 928}
905 929
@@ -907,6 +931,15 @@ impl Param {
907 pub fn ty(&self) -> &Type { 931 pub fn ty(&self) -> &Type {
908 &self.ty 932 &self.ty
909 } 933 }
934
935 pub fn pattern_source(&self, db: &dyn HirDatabase) -> Option<ast::Pat> {
936 let params = self.func.source(db)?.value.param_list()?;
937 if params.self_param().is_some() {
938 params.params().nth(self.idx.checked_sub(1)?)?.pat()
939 } else {
940 params.params().nth(self.idx)?.pat()
941 }
942 }
910} 943}
911 944
912#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 945#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -929,6 +962,14 @@ impl SelfParam {
929 }) 962 })
930 .unwrap_or(Access::Owned) 963 .unwrap_or(Access::Owned)
931 } 964 }
965
966 pub fn display(self, db: &dyn HirDatabase) -> &'static str {
967 match self.access(db) {
968 Access::Shared => "&self",
969 Access::Exclusive => "&mut self",
970 Access::Owned => "self",
971 }
972 }
932} 973}
933 974
934impl HasVisibility for Function { 975impl HasVisibility for Function {
@@ -956,6 +997,10 @@ impl Const {
956 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { 997 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
957 db.const_data(self.id).name.clone() 998 db.const_data(self.id).name.clone()
958 } 999 }
1000
1001 pub fn type_ref(self, db: &dyn HirDatabase) -> TypeRef {
1002 db.const_data(self.id).type_ref.clone()
1003 }
959} 1004}
960 1005
961impl HasVisibility for Const { 1006impl HasVisibility for Const {
@@ -989,6 +1034,12 @@ impl Static {
989 } 1034 }
990} 1035}
991 1036
1037impl HasVisibility for Static {
1038 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1039 db.static_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
1040 }
1041}
1042
992#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 1043#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
993pub struct Trait { 1044pub struct Trait {
994 pub(crate) id: TraitId, 1045 pub(crate) id: TraitId,
@@ -1008,7 +1059,13 @@ impl Trait {
1008 } 1059 }
1009 1060
1010 pub fn is_auto(self, db: &dyn HirDatabase) -> bool { 1061 pub fn is_auto(self, db: &dyn HirDatabase) -> bool {
1011 db.trait_data(self.id).auto 1062 db.trait_data(self.id).is_auto
1063 }
1064}
1065
1066impl HasVisibility for Trait {
1067 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1068 db.trait_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
1012 } 1069 }
1013} 1070}
1014 1071
@@ -1420,19 +1477,6 @@ impl TypeParam {
1420 } 1477 }
1421} 1478}
1422 1479
1423impl HirDisplay for TypeParam {
1424 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
1425 write!(f, "{}", self.name(f.db))?;
1426 let bounds = f.db.generic_predicates_for_param(self.id);
1427 let substs = Substs::type_params(f.db, self.id.parent);
1428 let predicates = bounds.iter().cloned().map(|b| b.subst(&substs)).collect::<Vec<_>>();
1429 if !(predicates.is_empty() || f.omit_verbose_types()) {
1430 write_bounds_like_dyn_trait_with_prefix(":", &predicates, f)?;
1431 }
1432 Ok(())
1433 }
1434}
1435
1436#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 1480#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1437pub struct LifetimeParam { 1481pub struct LifetimeParam {
1438 pub(crate) id: LifetimeParamId, 1482 pub(crate) id: LifetimeParamId,
@@ -1646,6 +1690,10 @@ impl Type {
1646 matches!(self.ty.value.interned(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..)) 1690 matches!(self.ty.value.interned(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..))
1647 } 1691 }
1648 1692
1693 pub fn is_usize(&self) -> bool {
1694 matches!(self.ty.value.interned(&Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize)))
1695 }
1696
1649 pub fn remove_ref(&self) -> Option<Type> { 1697 pub fn remove_ref(&self) -> Option<Type> {
1650 match &self.ty.value.interned(&Interner) { 1698 match &self.ty.value.interned(&Interner) {
1651 TyKind::Ref(.., ty) => Some(self.derived(ty.clone())), 1699 TyKind::Ref(.., ty) => Some(self.derived(ty.clone())),
@@ -2069,12 +2117,6 @@ impl Type {
2069 } 2117 }
2070} 2118}
2071 2119
2072impl HirDisplay for Type {
2073 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
2074 self.ty.value.hir_fmt(f)
2075 }
2076}
2077
2078// FIXME: closures 2120// FIXME: closures
2079#[derive(Debug)] 2121#[derive(Debug)]
2080pub struct Callable { 2122pub struct Callable {
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 945638cc5..03c9371b5 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -143,6 +143,12 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
143 self.imp.diagnostics_display_range(diagnostics) 143 self.imp.diagnostics_display_range(diagnostics)
144 } 144 }
145 145
146 pub fn token_ancestors_with_macros(
147 &self,
148 token: SyntaxToken,
149 ) -> impl Iterator<Item = SyntaxNode> + '_ {
150 token.parent().into_iter().flat_map(move |it| self.ancestors_with_macros(it))
151 }
146 pub fn ancestors_with_macros(&self, node: SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ { 152 pub fn ancestors_with_macros(&self, node: SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ {
147 self.imp.ancestors_with_macros(node) 153 self.imp.ancestors_with_macros(node)
148 } 154 }
@@ -259,6 +265,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
259 } 265 }
260 266
261 pub fn to_module_def(&self, file: FileId) -> Option<Module> { 267 pub fn to_module_def(&self, file: FileId) -> Option<Module> {
268 self.imp.to_module_def(file).next()
269 }
270
271 pub fn to_module_defs(&self, file: FileId) -> impl Iterator<Item = Module> {
262 self.imp.to_module_def(file) 272 self.imp.to_module_def(file)
263 } 273 }
264 274
@@ -266,8 +276,8 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
266 self.imp.scope(node) 276 self.imp.scope(node)
267 } 277 }
268 278
269 pub fn scope_at_offset(&self, node: &SyntaxNode, offset: TextSize) -> SemanticsScope<'db> { 279 pub fn scope_at_offset(&self, token: &SyntaxToken, offset: TextSize) -> SemanticsScope<'db> {
270 self.imp.scope_at_offset(node, offset) 280 self.imp.scope_at_offset(&token.parent().unwrap(), offset)
271 } 281 }
272 282
273 pub fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db> { 283 pub fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db> {
@@ -337,7 +347,10 @@ impl<'db> SemanticsImpl<'db> {
337 347
338 fn descend_into_macros(&self, token: SyntaxToken) -> SyntaxToken { 348 fn descend_into_macros(&self, token: SyntaxToken) -> SyntaxToken {
339 let _p = profile::span("descend_into_macros"); 349 let _p = profile::span("descend_into_macros");
340 let parent = token.parent(); 350 let parent = match token.parent() {
351 Some(it) => it,
352 None => return token,
353 };
341 let sa = self.analyze(&parent); 354 let sa = self.analyze(&parent);
342 355
343 let token = successors(Some(InFile::new(sa.file_id, token)), |token| { 356 let token = successors(Some(InFile::new(sa.file_id, token)), |token| {
@@ -356,7 +369,9 @@ impl<'db> SemanticsImpl<'db> {
356 .as_ref()? 369 .as_ref()?
357 .map_token_down(token.as_ref())?; 370 .map_token_down(token.as_ref())?;
358 371
359 self.cache(find_root(&token.value.parent()), token.file_id); 372 if let Some(parent) = token.value.parent() {
373 self.cache(find_root(&parent), token.file_id);
374 }
360 375
361 Some(token) 376 Some(token)
362 }) 377 })
@@ -374,7 +389,7 @@ impl<'db> SemanticsImpl<'db> {
374 // Handle macro token cases 389 // Handle macro token cases
375 node.token_at_offset(offset) 390 node.token_at_offset(offset)
376 .map(|token| self.descend_into_macros(token)) 391 .map(|token| self.descend_into_macros(token))
377 .map(|it| self.ancestors_with_macros(it.parent())) 392 .map(|it| self.token_ancestors_with_macros(it))
378 .flatten() 393 .flatten()
379 } 394 }
380 395
@@ -390,6 +405,13 @@ impl<'db> SemanticsImpl<'db> {
390 src.with_value(&node).original_file_range(self.db.upcast()) 405 src.with_value(&node).original_file_range(self.db.upcast())
391 } 406 }
392 407
408 fn token_ancestors_with_macros(
409 &self,
410 token: SyntaxToken,
411 ) -> impl Iterator<Item = SyntaxNode> + '_ {
412 token.parent().into_iter().flat_map(move |parent| self.ancestors_with_macros(parent))
413 }
414
393 fn ancestors_with_macros(&self, node: SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ { 415 fn ancestors_with_macros(&self, node: SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ {
394 let node = self.find_file(node); 416 let node = self.find_file(node);
395 node.ancestors_with_macros(self.db.upcast()).map(|it| it.value) 417 node.ancestors_with_macros(self.db.upcast()).map(|it| it.value)
@@ -401,7 +423,7 @@ impl<'db> SemanticsImpl<'db> {
401 offset: TextSize, 423 offset: TextSize,
402 ) -> impl Iterator<Item = SyntaxNode> + '_ { 424 ) -> impl Iterator<Item = SyntaxNode> + '_ {
403 node.token_at_offset(offset) 425 node.token_at_offset(offset)
404 .map(|token| self.ancestors_with_macros(token.parent())) 426 .map(|token| self.token_ancestors_with_macros(token))
405 .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len()) 427 .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len())
406 } 428 }
407 429
@@ -537,8 +559,8 @@ impl<'db> SemanticsImpl<'db> {
537 f(&mut ctx) 559 f(&mut ctx)
538 } 560 }
539 561
540 fn to_module_def(&self, file: FileId) -> Option<Module> { 562 fn to_module_def(&self, file: FileId) -> impl Iterator<Item = Module> {
541 self.with_ctx(|ctx| ctx.file_to_def(file)).map(Module::from) 563 self.with_ctx(|ctx| ctx.file_to_def(file)).into_iter().map(Module::from)
542 } 564 }
543 565
544 fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db> { 566 fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db> {
diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs
index 6c612ee86..e9d820140 100644
--- a/crates/hir/src/semantics/source_to_def.rs
+++ b/crates/hir/src/semantics/source_to_def.rs
@@ -12,6 +12,7 @@ use hir_def::{
12}; 12};
13use hir_expand::{name::AsName, AstId, MacroDefKind}; 13use hir_expand::{name::AsName, AstId, MacroDefKind};
14use rustc_hash::FxHashMap; 14use rustc_hash::FxHashMap;
15use smallvec::SmallVec;
15use stdx::impl_from; 16use stdx::impl_from;
16use syntax::{ 17use syntax::{
17 ast::{self, NameOwner}, 18 ast::{self, NameOwner},
@@ -28,14 +29,19 @@ pub(super) struct SourceToDefCtx<'a, 'b> {
28} 29}
29 30
30impl SourceToDefCtx<'_, '_> { 31impl SourceToDefCtx<'_, '_> {
31 pub(super) fn file_to_def(&mut self, file: FileId) -> Option<ModuleId> { 32 pub(super) fn file_to_def(&mut self, file: FileId) -> SmallVec<[ModuleId; 1]> {
32 let _p = profile::span("SourceBinder::to_module_def"); 33 let _p = profile::span("SourceBinder::to_module_def");
33 self.db.relevant_crates(file).iter().find_map(|&crate_id| { 34 let mut mods = SmallVec::new();
35 for &crate_id in self.db.relevant_crates(file).iter() {
34 // FIXME: inner items 36 // FIXME: inner items
35 let crate_def_map = self.db.crate_def_map(crate_id); 37 let crate_def_map = self.db.crate_def_map(crate_id);
36 let local_id = crate_def_map.modules_for_file(file).next()?; 38 mods.extend(
37 Some(crate_def_map.module_id(local_id)) 39 crate_def_map
38 }) 40 .modules_for_file(file)
41 .map(|local_id| crate_def_map.module_id(local_id)),
42 )
43 }
44 mods
39 } 45 }
40 46
41 pub(super) fn module_to_def(&mut self, src: InFile<ast::Module>) -> Option<ModuleId> { 47 pub(super) fn module_to_def(&mut self, src: InFile<ast::Module>) -> Option<ModuleId> {
@@ -55,7 +61,7 @@ impl SourceToDefCtx<'_, '_> {
55 Some(parent_declaration) => self.module_to_def(parent_declaration), 61 Some(parent_declaration) => self.module_to_def(parent_declaration),
56 None => { 62 None => {
57 let file_id = src.file_id.original_file(self.db.upcast()); 63 let file_id = src.file_id.original_file(self.db.upcast());
58 self.file_to_def(file_id) 64 self.file_to_def(file_id).get(0).copied()
59 } 65 }
60 }?; 66 }?;
61 67
@@ -185,7 +191,7 @@ impl SourceToDefCtx<'_, '_> {
185 ) -> Option<MacroDefId> { 191 ) -> Option<MacroDefId> {
186 let kind = MacroDefKind::Declarative; 192 let kind = MacroDefKind::Declarative;
187 let file_id = src.file_id.original_file(self.db.upcast()); 193 let file_id = src.file_id.original_file(self.db.upcast());
188 let krate = self.file_to_def(file_id)?.krate(); 194 let krate = self.file_to_def(file_id).get(0).copied()?.krate();
189 let file_ast_id = self.db.ast_id_map(src.file_id).ast_id(&src.value); 195 let file_ast_id = self.db.ast_id_map(src.file_id).ast_id(&src.value);
190 let ast_id = Some(AstId::new(src.file_id, file_ast_id.upcast())); 196 let ast_id = Some(AstId::new(src.file_id, file_ast_id.upcast()));
191 Some(MacroDefId { krate, ast_id, kind, local_inner: false }) 197 Some(MacroDefId { krate, ast_id, kind, local_inner: false })
@@ -245,7 +251,7 @@ impl SourceToDefCtx<'_, '_> {
245 return Some(res); 251 return Some(res);
246 } 252 }
247 253
248 let def = self.file_to_def(src.file_id.original_file(self.db.upcast()))?; 254 let def = self.file_to_def(src.file_id.original_file(self.db.upcast())).get(0).copied()?;
249 Some(def.into()) 255 Some(def.into())
250 } 256 }
251 257
diff --git a/crates/hir_def/src/adt.rs b/crates/hir_def/src/adt.rs
index efbde17d8..1b9bb8235 100644
--- a/crates/hir_def/src/adt.rs
+++ b/crates/hir_def/src/adt.rs
@@ -31,12 +31,14 @@ pub struct StructData {
31 pub name: Name, 31 pub name: Name,
32 pub variant_data: Arc<VariantData>, 32 pub variant_data: Arc<VariantData>,
33 pub repr: Option<ReprKind>, 33 pub repr: Option<ReprKind>,
34 pub visibility: RawVisibility,
34} 35}
35 36
36#[derive(Debug, Clone, PartialEq, Eq)] 37#[derive(Debug, Clone, PartialEq, Eq)]
37pub struct EnumData { 38pub struct EnumData {
38 pub name: Name, 39 pub name: Name,
39 pub variants: Arena<EnumVariantData>, 40 pub variants: Arena<EnumVariantData>,
41 pub visibility: RawVisibility,
40} 42}
41 43
42#[derive(Debug, Clone, PartialEq, Eq)] 44#[derive(Debug, Clone, PartialEq, Eq)]
@@ -102,6 +104,7 @@ impl StructData {
102 name: strukt.name.clone(), 104 name: strukt.name.clone(),
103 variant_data: Arc::new(variant_data), 105 variant_data: Arc::new(variant_data),
104 repr, 106 repr,
107 visibility: item_tree[strukt.visibility].clone(),
105 }) 108 })
106 } 109 }
107 pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> { 110 pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> {
@@ -118,6 +121,7 @@ impl StructData {
118 name: union.name.clone(), 121 name: union.name.clone(),
119 variant_data: Arc::new(variant_data), 122 variant_data: Arc::new(variant_data),
120 repr, 123 repr,
124 visibility: item_tree[union.visibility].clone(),
121 }) 125 })
122 } 126 }
123} 127}
@@ -150,7 +154,11 @@ impl EnumData {
150 } 154 }
151 } 155 }
152 156
153 Arc::new(EnumData { name: enum_.name.clone(), variants }) 157 Arc::new(EnumData {
158 name: enum_.name.clone(),
159 variants,
160 visibility: item_tree[enum_.visibility].clone(),
161 })
154 } 162 }
155 163
156 pub fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> { 164 pub fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> {
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 8934ae6c9..7052058f2 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -519,7 +519,7 @@ impl ExprCollector<'_> {
519 } 519 }
520 ast::Expr::MacroCall(e) => { 520 ast::Expr::MacroCall(e) => {
521 let mut ids = vec![]; 521 let mut ids = vec![];
522 self.collect_macro_call(e, syntax_ptr.clone(), |this, expansion| { 522 self.collect_macro_call(e, syntax_ptr.clone(), true, |this, expansion| {
523 ids.push(match expansion { 523 ids.push(match expansion {
524 Some(it) => this.collect_expr(it), 524 Some(it) => this.collect_expr(it),
525 None => this.alloc_expr(Expr::Missing, syntax_ptr.clone()), 525 None => this.alloc_expr(Expr::Missing, syntax_ptr.clone()),
@@ -527,6 +527,17 @@ impl ExprCollector<'_> {
527 }); 527 });
528 ids[0] 528 ids[0]
529 } 529 }
530 ast::Expr::MacroStmts(e) => {
531 // FIXME: these statements should be held by some hir containter
532 for stmt in e.statements() {
533 self.collect_stmt(stmt);
534 }
535 if let Some(expr) = e.expr() {
536 self.collect_expr(expr)
537 } else {
538 self.alloc_expr(Expr::Missing, syntax_ptr)
539 }
540 }
530 } 541 }
531 } 542 }
532 543
@@ -534,6 +545,7 @@ impl ExprCollector<'_> {
534 &mut self, 545 &mut self,
535 e: ast::MacroCall, 546 e: ast::MacroCall,
536 syntax_ptr: AstPtr<ast::Expr>, 547 syntax_ptr: AstPtr<ast::Expr>,
548 is_error_recoverable: bool,
537 mut collector: F, 549 mut collector: F,
538 ) { 550 ) {
539 // File containing the macro call. Expansion errors will be attached here. 551 // File containing the macro call. Expansion errors will be attached here.
@@ -567,7 +579,7 @@ impl ExprCollector<'_> {
567 Some((mark, expansion)) => { 579 Some((mark, expansion)) => {
568 // FIXME: Statements are too complicated to recover from error for now. 580 // FIXME: Statements are too complicated to recover from error for now.
569 // It is because we don't have any hygiene for local variable expansion right now. 581 // It is because we don't have any hygiene for local variable expansion right now.
570 if T::can_cast(syntax::SyntaxKind::MACRO_STMTS) && res.err.is_some() { 582 if !is_error_recoverable && res.err.is_some() {
571 self.expander.exit(self.db, mark); 583 self.expander.exit(self.db, mark);
572 collector(self, None); 584 collector(self, None);
573 } else { 585 } else {
@@ -591,56 +603,55 @@ impl ExprCollector<'_> {
591 } 603 }
592 604
593 fn collect_stmt(&mut self, s: ast::Stmt) -> Option<Vec<Statement>> { 605 fn collect_stmt(&mut self, s: ast::Stmt) -> Option<Vec<Statement>> {
594 let stmt = 606 let stmt = match s {
595 match s { 607 ast::Stmt::LetStmt(stmt) => {
596 ast::Stmt::LetStmt(stmt) => { 608 self.check_cfg(&stmt)?;
597 self.check_cfg(&stmt)?; 609
598 610 let pat = self.collect_pat_opt(stmt.pat());
599 let pat = self.collect_pat_opt(stmt.pat()); 611 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it));
600 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); 612 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
601 let initializer = stmt.initializer().map(|e| self.collect_expr(e)); 613 vec![Statement::Let { pat, type_ref, initializer }]
602 vec![Statement::Let { pat, type_ref, initializer }] 614 }
603 } 615 ast::Stmt::ExprStmt(stmt) => {
604 ast::Stmt::ExprStmt(stmt) => { 616 self.check_cfg(&stmt)?;
605 self.check_cfg(&stmt)?; 617
606 618 // Note that macro could be expended to multiple statements
607 // Note that macro could be expended to multiple statements 619 if let Some(ast::Expr::MacroCall(m)) = stmt.expr() {
608 if let Some(ast::Expr::MacroCall(m)) = stmt.expr() { 620 let syntax_ptr = AstPtr::new(&stmt.expr().unwrap());
609 let syntax_ptr = AstPtr::new(&stmt.expr().unwrap()); 621 let mut stmts = vec![];
610 let mut stmts = vec![]; 622
611 623 self.collect_macro_call(m, syntax_ptr.clone(), false, |this, expansion| {
612 self.collect_macro_call(m, syntax_ptr.clone(), |this, expansion| { 624 match expansion {
613 match expansion { 625 Some(expansion) => {
614 Some(expansion) => { 626 let statements: ast::MacroStmts = expansion;
615 let statements: ast::MacroStmts = expansion; 627
616 628 statements.statements().for_each(|stmt| {
617 statements.statements().for_each(|stmt| { 629 if let Some(mut r) = this.collect_stmt(stmt) {
618 if let Some(mut r) = this.collect_stmt(stmt) { 630 stmts.append(&mut r);
619 stmts.append(&mut r);
620 }
621 });
622 if let Some(expr) = statements.expr() {
623 stmts.push(Statement::Expr(this.collect_expr(expr)));
624 } 631 }
625 } 632 });
626 None => { 633 if let Some(expr) = statements.expr() {
627 stmts.push(Statement::Expr( 634 stmts.push(Statement::Expr(this.collect_expr(expr)));
628 this.alloc_expr(Expr::Missing, syntax_ptr.clone()),
629 ));
630 } 635 }
631 } 636 }
632 }); 637 None => {
633 stmts 638 stmts.push(Statement::Expr(
634 } else { 639 this.alloc_expr(Expr::Missing, syntax_ptr.clone()),
635 vec![Statement::Expr(self.collect_expr_opt(stmt.expr()))] 640 ));
636 } 641 }
642 }
643 });
644 stmts
645 } else {
646 vec![Statement::Expr(self.collect_expr_opt(stmt.expr()))]
637 } 647 }
638 ast::Stmt::Item(item) => { 648 }
639 self.check_cfg(&item)?; 649 ast::Stmt::Item(item) => {
650 self.check_cfg(&item)?;
640 651
641 return None; 652 return None;
642 } 653 }
643 }; 654 };
644 655
645 Some(stmt) 656 Some(stmt)
646 } 657 }
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs
index aea53d527..74a2194e5 100644
--- a/crates/hir_def/src/data.rs
+++ b/crates/hir_def/src/data.rs
@@ -9,7 +9,7 @@ use crate::{
9 attr::Attrs, 9 attr::Attrs,
10 body::Expander, 10 body::Expander,
11 db::DefDatabase, 11 db::DefDatabase,
12 item_tree::{AssocItem, ItemTreeId, ModItem}, 12 item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem},
13 type_ref::{TypeBound, TypeRef}, 13 type_ref::{TypeBound, TypeRef},
14 visibility::RawVisibility, 14 visibility::RawVisibility,
15 AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, 15 AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId,
@@ -26,9 +26,9 @@ pub struct FunctionData {
26 /// can be called as a method. 26 /// can be called as a method.
27 pub has_self_param: bool, 27 pub has_self_param: bool,
28 pub has_body: bool, 28 pub has_body: bool,
29 pub is_unsafe: bool, 29 pub qualifier: FunctionQualifier,
30 pub is_in_extern_block: bool,
30 pub is_varargs: bool, 31 pub is_varargs: bool,
31 pub is_extern: bool,
32 pub visibility: RawVisibility, 32 pub visibility: RawVisibility,
33} 33}
34 34
@@ -46,9 +46,9 @@ impl FunctionData {
46 attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), 46 attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()),
47 has_self_param: func.has_self_param, 47 has_self_param: func.has_self_param,
48 has_body: func.has_body, 48 has_body: func.has_body,
49 is_unsafe: func.is_unsafe, 49 qualifier: func.qualifier.clone(),
50 is_in_extern_block: func.is_in_extern_block,
50 is_varargs: func.is_varargs, 51 is_varargs: func.is_varargs,
51 is_extern: func.is_extern,
52 visibility: item_tree[func.visibility].clone(), 52 visibility: item_tree[func.visibility].clone(),
53 }) 53 })
54 } 54 }
@@ -87,7 +87,10 @@ impl TypeAliasData {
87pub struct TraitData { 87pub struct TraitData {
88 pub name: Name, 88 pub name: Name,
89 pub items: Vec<(Name, AssocItemId)>, 89 pub items: Vec<(Name, AssocItemId)>,
90 pub auto: bool, 90 pub is_auto: bool,
91 pub is_unsafe: bool,
92 pub visibility: RawVisibility,
93 pub bounds: Box<[TypeBound]>,
91} 94}
92 95
93impl TraitData { 96impl TraitData {
@@ -96,10 +99,13 @@ impl TraitData {
96 let item_tree = db.item_tree(tr_loc.id.file_id); 99 let item_tree = db.item_tree(tr_loc.id.file_id);
97 let tr_def = &item_tree[tr_loc.id.value]; 100 let tr_def = &item_tree[tr_loc.id.value];
98 let name = tr_def.name.clone(); 101 let name = tr_def.name.clone();
99 let auto = tr_def.auto; 102 let is_auto = tr_def.is_auto;
103 let is_unsafe = tr_def.is_unsafe;
100 let module_id = tr_loc.container; 104 let module_id = tr_loc.container;
101 let container = AssocContainerId::TraitId(tr); 105 let container = AssocContainerId::TraitId(tr);
102 let mut expander = Expander::new(db, tr_loc.id.file_id, module_id); 106 let mut expander = Expander::new(db, tr_loc.id.file_id, module_id);
107 let visibility = item_tree[tr_def.visibility].clone();
108 let bounds = tr_def.bounds.clone();
103 109
104 let items = collect_items( 110 let items = collect_items(
105 db, 111 db,
@@ -111,7 +117,7 @@ impl TraitData {
111 100, 117 100,
112 ); 118 );
113 119
114 Arc::new(TraitData { name, items, auto }) 120 Arc::new(TraitData { name, items, is_auto, is_unsafe, visibility, bounds })
115 } 121 }
116 122
117 pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ { 123 pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ {
diff --git a/crates/hir_def/src/diagnostics.rs b/crates/hir_def/src/diagnostics.rs
index ac7474f63..7188bb299 100644
--- a/crates/hir_def/src/diagnostics.rs
+++ b/crates/hir_def/src/diagnostics.rs
@@ -97,7 +97,7 @@ impl Diagnostic for UnresolvedImport {
97 97
98// Diagnostic: unresolved-macro-call 98// Diagnostic: unresolved-macro-call
99// 99//
100// This diagnostic is triggered if rust-analyzer is unable to resolove path to a 100// This diagnostic is triggered if rust-analyzer is unable to resolve the path to a
101// macro in a macro invocation. 101// macro in a macro invocation.
102#[derive(Debug)] 102#[derive(Debug)]
103pub struct UnresolvedMacroCall { 103pub struct UnresolvedMacroCall {
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index 09bcb10dc..7bb22c4c4 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -24,7 +24,7 @@ use la_arena::{Arena, Idx, RawIdx};
24use profile::Count; 24use profile::Count;
25use rustc_hash::FxHashMap; 25use rustc_hash::FxHashMap;
26use smallvec::SmallVec; 26use smallvec::SmallVec;
27use syntax::{ast, match_ast, SyntaxKind}; 27use syntax::{ast, match_ast, SmolStr, SyntaxKind};
28 28
29use crate::{ 29use crate::{
30 attr::{Attrs, RawAttrs}, 30 attr::{Attrs, RawAttrs},
@@ -110,6 +110,11 @@ impl ItemTree {
110 // still need to collect inner items. 110 // still need to collect inner items.
111 ctx.lower_inner_items(e.syntax()) 111 ctx.lower_inner_items(e.syntax())
112 }, 112 },
113 ast::ExprStmt(stmt) => {
114 // Macros can expand to stmt. We return an empty item tree in this case, but
115 // still need to collect inner items.
116 ctx.lower_inner_items(stmt.syntax())
117 },
113 _ => { 118 _ => {
114 panic!("cannot create item tree from {:?} {}", syntax, syntax); 119 panic!("cannot create item tree from {:?} {}", syntax, syntax);
115 }, 120 },
@@ -551,16 +556,25 @@ pub struct Function {
551 pub generic_params: GenericParamsId, 556 pub generic_params: GenericParamsId,
552 pub has_self_param: bool, 557 pub has_self_param: bool,
553 pub has_body: bool, 558 pub has_body: bool,
554 pub is_unsafe: bool, 559 pub qualifier: FunctionQualifier,
555 /// Whether the function is located in an `extern` block (*not* whether it is an 560 /// Whether the function is located in an `extern` block (*not* whether it is an
556 /// `extern "abi" fn`). 561 /// `extern "abi" fn`).
557 pub is_extern: bool, 562 pub is_in_extern_block: bool,
558 pub params: Box<[Idx<TypeRef>]>, 563 pub params: Box<[Idx<TypeRef>]>,
559 pub is_varargs: bool, 564 pub is_varargs: bool,
560 pub ret_type: Idx<TypeRef>, 565 pub ret_type: Idx<TypeRef>,
561 pub ast_id: FileAstId<ast::Fn>, 566 pub ast_id: FileAstId<ast::Fn>,
562} 567}
563 568
569#[derive(Debug, Clone, PartialEq, Eq)]
570pub struct FunctionQualifier {
571 pub is_default: bool,
572 pub is_const: bool,
573 pub is_async: bool,
574 pub is_unsafe: bool,
575 pub abi: Option<SmolStr>,
576}
577
564#[derive(Debug, Clone, Eq, PartialEq)] 578#[derive(Debug, Clone, Eq, PartialEq)]
565pub struct Struct { 579pub struct Struct {
566 pub name: Name, 580 pub name: Name,
@@ -624,7 +638,9 @@ pub struct Trait {
624 pub name: Name, 638 pub name: Name,
625 pub visibility: RawVisibilityId, 639 pub visibility: RawVisibilityId,
626 pub generic_params: GenericParamsId, 640 pub generic_params: GenericParamsId,
627 pub auto: bool, 641 pub is_auto: bool,
642 pub is_unsafe: bool,
643 pub bounds: Box<[TypeBound]>,
628 pub items: Box<[AssocItem]>, 644 pub items: Box<[AssocItem]>,
629 pub ast_id: FileAstId<ast::Trait>, 645 pub ast_id: FileAstId<ast::Trait>,
630} 646}
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index 240fdacf9..7e91b991d 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -391,14 +391,33 @@ impl Ctx {
391 let has_body = func.body().is_some(); 391 let has_body = func.body().is_some();
392 392
393 let ast_id = self.source_ast_id_map.ast_id(func); 393 let ast_id = self.source_ast_id_map.ast_id(func);
394 let qualifier = FunctionQualifier {
395 is_default: func.default_token().is_some(),
396 is_const: func.const_token().is_some(),
397 is_async: func.async_token().is_some(),
398 is_unsafe: func.unsafe_token().is_some(),
399 abi: func.abi().map(|abi| {
400 // FIXME: Abi::abi() -> Option<SyntaxToken>?
401 match abi.syntax().last_token() {
402 Some(tok) if tok.kind() == SyntaxKind::STRING => {
403 // FIXME: Better way to unescape?
404 tok.text().trim_matches('"').into()
405 }
406 _ => {
407 // `extern` default to be `extern "C"`.
408 "C".into()
409 }
410 }
411 }),
412 };
394 let mut res = Function { 413 let mut res = Function {
395 name, 414 name,
396 visibility, 415 visibility,
397 generic_params: GenericParamsId::EMPTY, 416 generic_params: GenericParamsId::EMPTY,
398 has_self_param, 417 has_self_param,
399 has_body, 418 has_body,
400 is_unsafe: func.unsafe_token().is_some(), 419 qualifier,
401 is_extern: false, 420 is_in_extern_block: false,
402 params, 421 params,
403 is_varargs, 422 is_varargs,
404 ret_type, 423 ret_type,
@@ -481,7 +500,9 @@ impl Ctx {
481 let visibility = self.lower_visibility(trait_def); 500 let visibility = self.lower_visibility(trait_def);
482 let generic_params = 501 let generic_params =
483 self.lower_generic_params_and_inner_items(GenericsOwner::Trait(trait_def), trait_def); 502 self.lower_generic_params_and_inner_items(GenericsOwner::Trait(trait_def), trait_def);
484 let auto = trait_def.auto_token().is_some(); 503 let is_auto = trait_def.auto_token().is_some();
504 let is_unsafe = trait_def.unsafe_token().is_some();
505 let bounds = self.lower_type_bounds(trait_def);
485 let items = trait_def.assoc_item_list().map(|list| { 506 let items = trait_def.assoc_item_list().map(|list| {
486 self.with_inherited_visibility(visibility, |this| { 507 self.with_inherited_visibility(visibility, |this| {
487 list.assoc_items() 508 list.assoc_items()
@@ -501,7 +522,9 @@ impl Ctx {
501 name, 522 name,
502 visibility, 523 visibility,
503 generic_params, 524 generic_params,
504 auto, 525 is_auto,
526 is_unsafe,
527 bounds: bounds.into(),
505 items: items.unwrap_or_default(), 528 items: items.unwrap_or_default(),
506 ast_id, 529 ast_id,
507 }; 530 };
@@ -608,8 +631,8 @@ impl Ctx {
608 ast::ExternItem::Fn(ast) => { 631 ast::ExternItem::Fn(ast) => {
609 let func_id = self.lower_function(&ast)?; 632 let func_id = self.lower_function(&ast)?;
610 let func = &mut self.data().functions[func_id.index]; 633 let func = &mut self.data().functions[func_id.index];
611 func.is_unsafe = is_intrinsic_fn_unsafe(&func.name); 634 func.qualifier.is_unsafe = is_intrinsic_fn_unsafe(&func.name);
612 func.is_extern = true; 635 func.is_in_extern_block = true;
613 func_id.into() 636 func_id.into()
614 } 637 }
615 ast::ExternItem::Static(ast) => { 638 ast::ExternItem::Static(ast) => {
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 9ed48c506..81cf652b0 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -13,7 +13,7 @@ use hir_expand::{
13 builtin_macro::find_builtin_macro, 13 builtin_macro::find_builtin_macro,
14 name::{AsName, Name}, 14 name::{AsName, Name},
15 proc_macro::ProcMacroExpander, 15 proc_macro::ProcMacroExpander,
16 HirFileId, MacroCallId, MacroDefId, MacroDefKind, 16 HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
17}; 17};
18use hir_expand::{InFile, MacroCallLoc}; 18use hir_expand::{InFile, MacroCallLoc};
19use rustc_hash::{FxHashMap, FxHashSet}; 19use rustc_hash::{FxHashMap, FxHashSet};
@@ -1455,7 +1455,8 @@ impl ModCollector<'_, '_> {
1455 let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); 1455 let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone());
1456 1456
1457 // Case 1: try to resolve in legacy scope and expand macro_rules 1457 // Case 1: try to resolve in legacy scope and expand macro_rules
1458 if let Ok(Ok(macro_call_id)) = macro_call_as_call_id( 1458 let mut error = None;
1459 match macro_call_as_call_id(
1459 &ast_id, 1460 &ast_id,
1460 self.def_collector.db, 1461 self.def_collector.db,
1461 self.def_collector.def_map.krate, 1462 self.def_collector.def_map.krate,
@@ -1468,16 +1469,28 @@ impl ModCollector<'_, '_> {
1468 ) 1469 )
1469 }) 1470 })
1470 }, 1471 },
1471 &mut |_err| (), 1472 &mut |err| error = Some(err),
1472 ) { 1473 ) {
1473 self.def_collector.unexpanded_macros.push(MacroDirective { 1474 Ok(Ok(macro_call_id)) => {
1474 module_id: self.module_id, 1475 self.def_collector.unexpanded_macros.push(MacroDirective {
1475 ast_id, 1476 module_id: self.module_id,
1476 legacy: Some(macro_call_id), 1477 ast_id,
1477 depth: self.macro_depth + 1, 1478 legacy: Some(macro_call_id),
1478 }); 1479 depth: self.macro_depth + 1,
1480 });
1479 1481
1480 return; 1482 return;
1483 }
1484 Ok(Err(_)) => {
1485 // Built-in macro failed eager expansion.
1486 self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error(
1487 self.module_id,
1488 MacroCallKind::FnLike(ast_id.ast_id),
1489 error.unwrap().to_string(),
1490 ));
1491 return;
1492 }
1493 Err(UnresolvedMacro) => (),
1481 } 1494 }
1482 1495
1483 // Case 2: resolve in module scope, expand during name resolution. 1496 // Case 2: resolve in module scope, expand during name resolution.
diff --git a/crates/hir_def/src/nameres/tests/diagnostics.rs b/crates/hir_def/src/nameres/tests/diagnostics.rs
index 1b8e885b0..c22ef46fd 100644
--- a/crates/hir_def/src/nameres/tests/diagnostics.rs
+++ b/crates/hir_def/src/nameres/tests/diagnostics.rs
@@ -155,3 +155,48 @@ fn inactive_via_cfg_attr() {
155 "#, 155 "#,
156 ); 156 );
157} 157}
158
159#[test]
160fn unresolved_legacy_scope_macro() {
161 check_diagnostics(
162 r#"
163 //- /lib.rs
164 macro_rules! m { () => {} }
165
166 m!();
167 m2!();
168 //^^^^^^ unresolved macro call
169 "#,
170 );
171}
172
173#[test]
174fn unresolved_module_scope_macro() {
175 check_diagnostics(
176 r#"
177 //- /lib.rs
178 mod mac {
179 #[macro_export]
180 macro_rules! m { () => {} }
181 }
182
183 self::m!();
184 self::m2!();
185 //^^^^^^^^^^^^ unresolved macro call
186 "#,
187 );
188}
189
190#[test]
191fn builtin_macro_fails_expansion() {
192 check_diagnostics(
193 r#"
194 //- /lib.rs
195 #[rustc_builtin_macro]
196 macro_rules! include { () => {} }
197
198 include!("doesntexist");
199 //^^^^^^^^^^^^^^^^^^^^^^^^ could not convert tokens
200 "#,
201 );
202}
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs
index 0e60dc2b6..8c923bb7b 100644
--- a/crates/hir_def/src/path.rs
+++ b/crates/hir_def/src/path.rs
@@ -9,7 +9,10 @@ use std::{
9 9
10use crate::{body::LowerCtx, type_ref::LifetimeRef}; 10use crate::{body::LowerCtx, type_ref::LifetimeRef};
11use base_db::CrateId; 11use base_db::CrateId;
12use hir_expand::{hygiene::Hygiene, name::Name}; 12use hir_expand::{
13 hygiene::Hygiene,
14 name::{name, Name},
15};
13use syntax::ast; 16use syntax::ast;
14 17
15use crate::{ 18use crate::{
@@ -209,6 +212,12 @@ impl Path {
209 }; 212 };
210 Some(res) 213 Some(res)
211 } 214 }
215
216 pub fn is_self_type(&self) -> bool {
217 self.type_anchor.is_none()
218 && self.generic_args == &[None]
219 && self.mod_path.as_ident() == Some(&name!(Self))
220 }
212} 221}
213 222
214#[derive(Debug, Clone, PartialEq, Eq, Hash)] 223#[derive(Debug, Clone, PartialEq, Eq, Hash)]
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index 9086e6c17..a3070f1f9 100644
--- a/crates/hir_expand/src/db.rs
+++ b/crates/hir_expand/src/db.rs
@@ -401,13 +401,14 @@ fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind {
401 401
402 match parent.kind() { 402 match parent.kind() {
403 MACRO_ITEMS | SOURCE_FILE => FragmentKind::Items, 403 MACRO_ITEMS | SOURCE_FILE => FragmentKind::Items,
404 MACRO_STMTS => FragmentKind::Statement,
404 ITEM_LIST => FragmentKind::Items, 405 ITEM_LIST => FragmentKind::Items,
405 LET_STMT => { 406 LET_STMT => {
406 // FIXME: Handle Pattern 407 // FIXME: Handle Pattern
407 FragmentKind::Expr 408 FragmentKind::Expr
408 } 409 }
409 EXPR_STMT => FragmentKind::Statements, 410 EXPR_STMT => FragmentKind::Statements,
410 BLOCK_EXPR => FragmentKind::Expr, 411 BLOCK_EXPR => FragmentKind::Statements,
411 ARG_LIST => FragmentKind::Expr, 412 ARG_LIST => FragmentKind::Expr,
412 TRY_EXPR => FragmentKind::Expr, 413 TRY_EXPR => FragmentKind::Expr,
413 TUPLE_EXPR => FragmentKind::Expr, 414 TUPLE_EXPR => FragmentKind::Expr,
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs
index e388ddacc..eee430af1 100644
--- a/crates/hir_expand/src/lib.rs
+++ b/crates/hir_expand/src/lib.rs
@@ -510,7 +510,10 @@ impl InFile<SyntaxToken> {
510 self, 510 self,
511 db: &dyn db::AstDatabase, 511 db: &dyn db::AstDatabase,
512 ) -> impl Iterator<Item = InFile<SyntaxNode>> + '_ { 512 ) -> impl Iterator<Item = InFile<SyntaxNode>> + '_ {
513 self.map(|it| it.parent()).ancestors_with_macros(db) 513 self.value
514 .parent()
515 .into_iter()
516 .flat_map(move |parent| InFile::new(self.file_id, parent).ancestors_with_macros(db))
514 } 517 }
515} 518}
516 519
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs
index e833e032c..43de9edd6 100644
--- a/crates/hir_expand/src/name.rs
+++ b/crates/hir_expand/src/name.rs
@@ -191,6 +191,8 @@ pub mod known {
191 filter_map, 191 filter_map,
192 next, 192 next,
193 iter_mut, 193 iter_mut,
194 len,
195 is_empty,
194 // Builtin macros 196 // Builtin macros
195 file, 197 file,
196 column, 198 column,
diff --git a/crates/hir_ty/src/diagnostics/decl_check.rs b/crates/hir_ty/src/diagnostics/decl_check.rs
index 3605ca581..982ad5b9e 100644
--- a/crates/hir_ty/src/diagnostics/decl_check.rs
+++ b/crates/hir_ty/src/diagnostics/decl_check.rs
@@ -91,7 +91,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
91 91
92 fn validate_func(&mut self, func: FunctionId) { 92 fn validate_func(&mut self, func: FunctionId) {
93 let data = self.db.function_data(func); 93 let data = self.db.function_data(func);
94 if data.is_extern { 94 if data.is_in_extern_block {
95 cov_mark::hit!(extern_func_incorrect_case_ignored); 95 cov_mark::hit!(extern_func_incorrect_case_ignored);
96 return; 96 return;
97 } 97 }
diff --git a/crates/hir_ty/src/diagnostics/unsafe_check.rs b/crates/hir_ty/src/diagnostics/unsafe_check.rs
index 20bb64827..44a7e5506 100644
--- a/crates/hir_ty/src/diagnostics/unsafe_check.rs
+++ b/crates/hir_ty/src/diagnostics/unsafe_check.rs
@@ -32,7 +32,7 @@ impl<'a, 'b> UnsafeValidator<'a, 'b> {
32 let def = self.owner.into(); 32 let def = self.owner.into();
33 let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def); 33 let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def);
34 let is_unsafe = match self.owner { 34 let is_unsafe = match self.owner {
35 DefWithBodyId::FunctionId(it) => db.function_data(it).is_unsafe, 35 DefWithBodyId::FunctionId(it) => db.function_data(it).qualifier.is_unsafe,
36 DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) => false, 36 DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) => false,
37 }; 37 };
38 if is_unsafe 38 if is_unsafe
@@ -86,7 +86,7 @@ fn walk_unsafe(
86 match expr { 86 match expr {
87 &Expr::Call { callee, .. } => { 87 &Expr::Call { callee, .. } => {
88 if let Some(func) = infer[callee].as_fn_def(db) { 88 if let Some(func) = infer[callee].as_fn_def(db) {
89 if db.function_data(func).is_unsafe { 89 if db.function_data(func).qualifier.is_unsafe {
90 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); 90 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
91 } 91 }
92 } 92 }
@@ -103,7 +103,7 @@ fn walk_unsafe(
103 Expr::MethodCall { .. } => { 103 Expr::MethodCall { .. } => {
104 if infer 104 if infer
105 .method_resolution(current) 105 .method_resolution(current)
106 .map(|func| db.function_data(func).is_unsafe) 106 .map(|func| db.function_data(func).qualifier.is_unsafe)
107 .unwrap_or(false) 107 .unwrap_or(false)
108 { 108 {
109 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); 109 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index c1062387e..c572bb114 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -5,7 +5,13 @@ use std::{borrow::Cow, fmt};
5use arrayvec::ArrayVec; 5use arrayvec::ArrayVec;
6use chalk_ir::Mutability; 6use chalk_ir::Mutability;
7use hir_def::{ 7use hir_def::{
8 db::DefDatabase, find_path, generics::TypeParamProvenance, item_scope::ItemInNs, 8 db::DefDatabase,
9 find_path,
10 generics::TypeParamProvenance,
11 item_scope::ItemInNs,
12 path::{GenericArg, Path, PathKind},
13 type_ref::{TypeBound, TypeRef},
14 visibility::Visibility,
9 AssocContainerId, Lookup, ModuleId, TraitId, 15 AssocContainerId, Lookup, ModuleId, TraitId,
10}; 16};
11use hir_expand::name::Name; 17use hir_expand::name::Name;
@@ -232,7 +238,7 @@ where
232 238
233const TYPE_HINT_TRUNCATION: &str = "…"; 239const TYPE_HINT_TRUNCATION: &str = "…";
234 240
235impl HirDisplay for &Ty { 241impl<T: HirDisplay> HirDisplay for &'_ T {
236 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 242 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
237 HirDisplay::hir_fmt(*self, f) 243 HirDisplay::hir_fmt(*self, f)
238 } 244 }
@@ -761,12 +767,6 @@ impl HirDisplay for TraitRef {
761 } 767 }
762} 768}
763 769
764impl HirDisplay for &GenericPredicate {
765 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
766 HirDisplay::hir_fmt(*self, f)
767 }
768}
769
770impl HirDisplay for GenericPredicate { 770impl HirDisplay for GenericPredicate {
771 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 771 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
772 if f.should_truncate() { 772 if f.should_truncate() {
@@ -825,3 +825,190 @@ impl HirDisplay for Obligation {
825 } 825 }
826 } 826 }
827} 827}
828
829pub fn write_visibility(
830 module_id: ModuleId,
831 vis: Visibility,
832 f: &mut HirFormatter,
833) -> Result<(), HirDisplayError> {
834 match vis {
835 Visibility::Public => write!(f, "pub "),
836 Visibility::Module(vis_id) => {
837 let def_map = module_id.def_map(f.db.upcast());
838 let root_module_id = def_map.module_id(def_map.root());
839 if vis_id == module_id {
840 // pub(self) or omitted
841 Ok(())
842 } else if root_module_id == vis_id {
843 write!(f, "pub(crate) ")
844 } else if module_id.containing_module(f.db.upcast()) == Some(vis_id) {
845 write!(f, "pub(super) ")
846 } else {
847 write!(f, "pub(in ...) ")
848 }
849 }
850 }
851}
852
853impl HirDisplay for TypeRef {
854 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
855 match self {
856 TypeRef::Never => write!(f, "!")?,
857 TypeRef::Placeholder => write!(f, "_")?,
858 TypeRef::Tuple(elems) => {
859 write!(f, "(")?;
860 f.write_joined(elems, ", ")?;
861 if elems.len() == 1 {
862 write!(f, ",")?;
863 }
864 write!(f, ")")?;
865 }
866 TypeRef::Path(path) => path.hir_fmt(f)?,
867 TypeRef::RawPtr(inner, mutability) => {
868 let mutability = match mutability {
869 hir_def::type_ref::Mutability::Shared => "*const ",
870 hir_def::type_ref::Mutability::Mut => "*mut ",
871 };
872 write!(f, "{}", mutability)?;
873 inner.hir_fmt(f)?;
874 }
875 TypeRef::Reference(inner, lifetime, mutability) => {
876 let mutability = match mutability {
877 hir_def::type_ref::Mutability::Shared => "",
878 hir_def::type_ref::Mutability::Mut => "mut ",
879 };
880 write!(f, "&")?;
881 if let Some(lifetime) = lifetime {
882 write!(f, "{} ", lifetime.name)?;
883 }
884 write!(f, "{}", mutability)?;
885 inner.hir_fmt(f)?;
886 }
887 TypeRef::Array(inner) => {
888 write!(f, "[")?;
889 inner.hir_fmt(f)?;
890 // FIXME: Array length?
891 write!(f, "; _]")?;
892 }
893 TypeRef::Slice(inner) => {
894 write!(f, "[")?;
895 inner.hir_fmt(f)?;
896 write!(f, "]")?;
897 }
898 TypeRef::Fn(tys, is_varargs) => {
899 // FIXME: Function pointer qualifiers.
900 write!(f, "fn(")?;
901 f.write_joined(&tys[..tys.len() - 1], ", ")?;
902 if *is_varargs {
903 write!(f, "{}...", if tys.len() == 1 { "" } else { ", " })?;
904 }
905 write!(f, ")")?;
906 let ret_ty = tys.last().unwrap();
907 match ret_ty {
908 TypeRef::Tuple(tup) if tup.is_empty() => {}
909 _ => {
910 write!(f, " -> ")?;
911 ret_ty.hir_fmt(f)?;
912 }
913 }
914 }
915 TypeRef::ImplTrait(bounds) => {
916 write!(f, "impl ")?;
917 f.write_joined(bounds, " + ")?;
918 }
919 TypeRef::DynTrait(bounds) => {
920 write!(f, "dyn ")?;
921 f.write_joined(bounds, " + ")?;
922 }
923 TypeRef::Error => write!(f, "{{error}}")?,
924 }
925 Ok(())
926 }
927}
928
929impl HirDisplay for TypeBound {
930 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
931 match self {
932 TypeBound::Path(path) => path.hir_fmt(f),
933 TypeBound::Lifetime(lifetime) => write!(f, "{}", lifetime.name),
934 TypeBound::Error => write!(f, "{{error}}"),
935 }
936 }
937}
938
939impl HirDisplay for Path {
940 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
941 match (self.type_anchor(), self.kind()) {
942 (Some(anchor), _) => {
943 write!(f, "<")?;
944 anchor.hir_fmt(f)?;
945 write!(f, ">")?;
946 }
947 (_, PathKind::Plain) => {}
948 (_, PathKind::Abs) => write!(f, "::")?,
949 (_, PathKind::Crate) => write!(f, "crate")?,
950 (_, PathKind::Super(0)) => write!(f, "self")?,
951 (_, PathKind::Super(n)) => {
952 write!(f, "super")?;
953 for _ in 0..*n {
954 write!(f, "::super")?;
955 }
956 }
957 (_, PathKind::DollarCrate(_)) => write!(f, "{{extern_crate}}")?,
958 }
959
960 for (seg_idx, segment) in self.segments().iter().enumerate() {
961 if seg_idx != 0 {
962 write!(f, "::")?;
963 }
964 write!(f, "{}", segment.name)?;
965 if let Some(generic_args) = segment.args_and_bindings {
966 // We should be in type context, so format as `Foo<Bar>` instead of `Foo::<Bar>`.
967 // Do we actually format expressions?
968 write!(f, "<")?;
969 let mut first = true;
970 for arg in &generic_args.args {
971 if first {
972 first = false;
973 if generic_args.has_self_type {
974 // FIXME: Convert to `<Ty as Trait>` form.
975 write!(f, "Self = ")?;
976 }
977 } else {
978 write!(f, ", ")?;
979 }
980 arg.hir_fmt(f)?;
981 }
982 for binding in &generic_args.bindings {
983 if first {
984 first = false;
985 } else {
986 write!(f, ", ")?;
987 }
988 write!(f, "{}", binding.name)?;
989 match &binding.type_ref {
990 Some(ty) => {
991 write!(f, " = ")?;
992 ty.hir_fmt(f)?
993 }
994 None => {
995 write!(f, ": ")?;
996 f.write_joined(&binding.bounds, " + ")?;
997 }
998 }
999 }
1000 write!(f, ">")?;
1001 }
1002 }
1003 Ok(())
1004 }
1005}
1006
1007impl HirDisplay for GenericArg {
1008 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
1009 match self {
1010 GenericArg::Type(ty) => ty.hir_fmt(f),
1011 GenericArg::Lifetime(lifetime) => write!(f, "{}", lifetime.name),
1012 }
1013 }
1014}
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs
index 66f8fe8a3..7795f446f 100644
--- a/crates/hir_ty/src/infer/unify.rs
+++ b/crates/hir_ty/src/infer/unify.rs
@@ -300,7 +300,7 @@ impl InferenceTable {
300 | (TyKind::Raw(_, ty1), TyKind::Raw(_, ty2)) 300 | (TyKind::Raw(_, ty1), TyKind::Raw(_, ty2))
301 | (TyKind::Array(ty1), TyKind::Array(ty2)) 301 | (TyKind::Array(ty1), TyKind::Array(ty2))
302 | (TyKind::Slice(ty1), TyKind::Slice(ty2)) => self.unify_inner(ty1, ty2, depth + 1), 302 | (TyKind::Slice(ty1), TyKind::Slice(ty2)) => self.unify_inner(ty1, ty2, depth + 1),
303 _ => false, 303 _ => true, /* we checked equals_ctor already */
304 } 304 }
305 } else { 305 } else {
306 self.unify_inner_trivial(&ty1, &ty2, depth) 306 self.unify_inner_trivial(&ty1, &ty2, depth)
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index 503910dde..850385280 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -31,6 +31,7 @@ use hir_def::{
31 GenericDefId, HasModule, LifetimeParamId, Lookup, TraitId, TypeAliasId, TypeParamId, 31 GenericDefId, HasModule, LifetimeParamId, Lookup, TraitId, TypeAliasId, TypeParamId,
32}; 32};
33use itertools::Itertools; 33use itertools::Itertools;
34use smallvec::SmallVec;
34 35
35use crate::{ 36use crate::{
36 db::HirDatabase, 37 db::HirDatabase,
@@ -272,7 +273,7 @@ impl Ty {
272 273
273/// A list of substitutions for generic parameters. 274/// A list of substitutions for generic parameters.
274#[derive(Clone, PartialEq, Eq, Debug, Hash)] 275#[derive(Clone, PartialEq, Eq, Debug, Hash)]
275pub struct Substs(Arc<[Ty]>); 276pub struct Substs(SmallVec<[Ty; 2]>);
276 277
277impl TypeWalk for Substs { 278impl TypeWalk for Substs {
278 fn walk(&self, f: &mut impl FnMut(&Ty)) { 279 fn walk(&self, f: &mut impl FnMut(&Ty)) {
@@ -286,19 +287,27 @@ impl TypeWalk for Substs {
286 f: &mut impl FnMut(&mut Ty, DebruijnIndex), 287 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
287 binders: DebruijnIndex, 288 binders: DebruijnIndex,
288 ) { 289 ) {
289 for t in make_mut_slice(&mut self.0) { 290 for t in &mut self.0 {
290 t.walk_mut_binders(f, binders); 291 t.walk_mut_binders(f, binders);
291 } 292 }
292 } 293 }
293} 294}
294 295
295impl Substs { 296impl Substs {
297 pub fn interned(&self, _: &Interner) -> &[Ty] {
298 &self.0
299 }
300
296 pub fn empty() -> Substs { 301 pub fn empty() -> Substs {
297 Substs(Arc::new([])) 302 Substs(SmallVec::new())
298 } 303 }
299 304
300 pub fn single(ty: Ty) -> Substs { 305 pub fn single(ty: Ty) -> Substs {
301 Substs(Arc::new([ty])) 306 Substs({
307 let mut v = SmallVec::new();
308 v.push(ty);
309 v
310 })
302 } 311 }
303 312
304 pub fn prefix(&self, n: usize) -> Substs { 313 pub fn prefix(&self, n: usize) -> Substs {
@@ -316,6 +325,10 @@ impl Substs {
316 &self.0[0] 325 &self.0[0]
317 } 326 }
318 327
328 pub fn from_iter(_interner: &Interner, elements: impl IntoIterator<Item = Ty>) -> Self {
329 Substs(elements.into_iter().collect())
330 }
331
319 /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). 332 /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`).
320 pub(crate) fn type_params_for_generics( 333 pub(crate) fn type_params_for_generics(
321 db: &dyn HirDatabase, 334 db: &dyn HirDatabase,
@@ -600,13 +613,13 @@ impl CallableSig {
600 613
601 pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig { 614 pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig {
602 CallableSig { 615 CallableSig {
603 params_and_return: Arc::clone(&fn_ptr.substs.0), 616 params_and_return: fn_ptr.substs.interned(&Interner).iter().cloned().collect(),
604 is_varargs: fn_ptr.sig.variadic, 617 is_varargs: fn_ptr.sig.variadic,
605 } 618 }
606 } 619 }
607 620
608 pub fn from_substs(substs: &Substs) -> CallableSig { 621 pub fn from_substs(substs: &Substs) -> CallableSig {
609 CallableSig { params_and_return: Arc::clone(&substs.0), is_varargs: false } 622 CallableSig { params_and_return: substs.iter().cloned().collect(), is_varargs: false }
610 } 623 }
611 624
612 pub fn params(&self) -> &[Ty] { 625 pub fn params(&self) -> &[Ty] {
@@ -649,7 +662,7 @@ impl Ty {
649 TyKind::Function(FnPointer { 662 TyKind::Function(FnPointer {
650 num_args: sig.params().len(), 663 num_args: sig.params().len(),
651 sig: FnSig { abi: (), safety: Safety::Safe, variadic: sig.is_varargs }, 664 sig: FnSig { abi: (), safety: Safety::Safe, variadic: sig.is_varargs },
652 substs: Substs(sig.params_and_return), 665 substs: Substs::from_iter(&Interner, sig.params_and_return.iter().cloned()),
653 }) 666 })
654 .intern(&Interner) 667 .intern(&Interner)
655 } 668 }
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index b4c650fa1..6ab757bfc 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -31,7 +31,7 @@ use crate::{
31 traits::chalk::{Interner, ToChalk}, 31 traits::chalk::{Interner, ToChalk},
32 utils::{ 32 utils::{
33 all_super_trait_refs, associated_type_by_name_including_super_traits, generics, 33 all_super_trait_refs, associated_type_by_name_including_super_traits, generics,
34 make_mut_slice, variant_data, 34 variant_data,
35 }, 35 },
36 AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, FnPointer, FnSig, GenericPredicate, 36 AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, FnPointer, FnSig, GenericPredicate,
37 ImplTraitId, OpaqueTy, PolyFnSig, ProjectionPredicate, ProjectionTy, ReturnTypeImplTrait, 37 ImplTraitId, OpaqueTy, PolyFnSig, ProjectionPredicate, ProjectionTy, ReturnTypeImplTrait,
@@ -150,8 +150,9 @@ impl<'a> TyLoweringContext<'a> {
150 let ty = match type_ref { 150 let ty = match type_ref {
151 TypeRef::Never => TyKind::Never.intern(&Interner), 151 TypeRef::Never => TyKind::Never.intern(&Interner),
152 TypeRef::Tuple(inner) => { 152 TypeRef::Tuple(inner) => {
153 let inner_tys: Arc<[Ty]> = inner.iter().map(|tr| self.lower_ty(tr)).collect(); 153 let inner_tys = inner.iter().map(|tr| self.lower_ty(tr));
154 TyKind::Tuple(inner_tys.len(), Substs(inner_tys)).intern(&Interner) 154 TyKind::Tuple(inner_tys.len(), Substs::from_iter(&Interner, inner_tys))
155 .intern(&Interner)
155 } 156 }
156 TypeRef::Path(path) => { 157 TypeRef::Path(path) => {
157 let (ty, res_) = self.lower_path(path); 158 let (ty, res_) = self.lower_path(path);
@@ -638,7 +639,7 @@ impl<'a> TyLoweringContext<'a> {
638 ) -> TraitRef { 639 ) -> TraitRef {
639 let mut substs = self.trait_ref_substs_from_path(segment, resolved); 640 let mut substs = self.trait_ref_substs_from_path(segment, resolved);
640 if let Some(self_ty) = explicit_self_ty { 641 if let Some(self_ty) = explicit_self_ty {
641 make_mut_slice(&mut substs.0)[0] = self_ty; 642 substs.0[0] = self_ty;
642 } 643 }
643 TraitRef { trait_: resolved, substs } 644 TraitRef { trait_: resolved, substs }
644 } 645 }
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs
index fb3afaedc..af4f8bb11 100644
--- a/crates/hir_ty/src/tests/macros.rs
+++ b/crates/hir_ty/src/tests/macros.rs
@@ -216,6 +216,22 @@ fn expr_macro_expanded_in_various_places() {
216} 216}
217 217
218#[test] 218#[test]
219fn expr_macro_expanded_in_stmts() {
220 check_infer(
221 r#"
222 macro_rules! id { ($($es:tt)*) => { $($es)* } }
223 fn foo() {
224 id! { let a = (); }
225 }
226 "#,
227 expect![[r#"
228 !0..8 'leta=();': ()
229 57..84 '{ ...); } }': ()
230 "#]],
231 );
232}
233
234#[test]
219fn infer_type_value_macro_having_same_name() { 235fn infer_type_value_macro_having_same_name() {
220 check_infer( 236 check_infer(
221 r#" 237 r#"
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs
index e185b1c0a..93d3ad020 100644
--- a/crates/hir_ty/src/tests/traits.rs
+++ b/crates/hir_ty/src/tests/traits.rs
@@ -1699,7 +1699,7 @@ fn super_trait_assoc_type_bounds() {
1699 1699
1700#[test] 1700#[test]
1701fn fn_trait() { 1701fn fn_trait() {
1702 check_infer( 1702 check_infer_with_mismatches(
1703 r#" 1703 r#"
1704 trait FnOnce<Args> { 1704 trait FnOnce<Args> {
1705 type Output; 1705 type Output;
@@ -1727,7 +1727,7 @@ fn fn_trait() {
1727 1727
1728#[test] 1728#[test]
1729fn fn_ptr_and_item() { 1729fn fn_ptr_and_item() {
1730 check_infer( 1730 check_infer_with_mismatches(
1731 r#" 1731 r#"
1732 #[lang="fn_once"] 1732 #[lang="fn_once"]
1733 trait FnOnce<Args> { 1733 trait FnOnce<Args> {
@@ -1743,12 +1743,12 @@ fn fn_ptr_and_item() {
1743 struct Bar<T>(T); 1743 struct Bar<T>(T);
1744 1744
1745 impl<A1, R, F: FnOnce(A1) -> R> Foo<(A1, R)> for Bar<F> { 1745 impl<A1, R, F: FnOnce(A1) -> R> Foo<(A1, R)> for Bar<F> {
1746 fn foo(&self) -> (A1, R) {} 1746 fn foo(&self) -> (A1, R) { loop {} }
1747 } 1747 }
1748 1748
1749 enum Opt<T> { None, Some(T) } 1749 enum Opt<T> { None, Some(T) }
1750 impl<T> Opt<T> { 1750 impl<T> Opt<T> {
1751 fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Opt<U> {} 1751 fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Opt<U> { loop {} }
1752 } 1752 }
1753 1753
1754 fn test() { 1754 fn test() {
@@ -1765,19 +1765,23 @@ fn fn_ptr_and_item() {
1765 80..84 'args': Args 1765 80..84 'args': Args
1766 139..143 'self': &Self 1766 139..143 'self': &Self
1767 243..247 'self': &Bar<F> 1767 243..247 'self': &Bar<F>
1768 260..262 '{}': () 1768 260..271 '{ loop {} }': (A1, R)
1769 346..350 'self': Opt<T> 1769 262..269 'loop {}': !
1770 352..353 'f': F 1770 267..269 '{}': ()
1771 368..370 '{}': () 1771 355..359 'self': Opt<T>
1772 384..500 '{ ...(f); }': () 1772 361..362 'f': F
1773 394..397 'bar': Bar<fn(u8) -> u32> 1773 377..388 '{ loop {} }': Opt<U>
1774 423..426 'bar': Bar<fn(u8) -> u32> 1774 379..386 'loop {}': !
1775 423..432 'bar.foo()': (u8, u32) 1775 384..386 '{}': ()
1776 443..446 'opt': Opt<u8> 1776 402..518 '{ ...(f); }': ()
1777 465..466 'f': fn(u8) -> u32 1777 412..415 'bar': Bar<fn(u8) -> u32>
1778 487..490 'opt': Opt<u8> 1778 441..444 'bar': Bar<fn(u8) -> u32>
1779 487..497 'opt.map(f)': Opt<u32> 1779 441..450 'bar.foo()': (u8, u32)
1780 495..496 'f': fn(u8) -> u32 1780 461..464 'opt': Opt<u8>
1781 483..484 'f': fn(u8) -> u32
1782 505..508 'opt': Opt<u8>
1783 505..515 'opt.map(f)': Opt<u32>
1784 513..514 'f': fn(u8) -> u32
1781 "#]], 1785 "#]],
1782 ); 1786 );
1783} 1787}
@@ -1859,7 +1863,7 @@ fn fn_trait_deref_with_ty_default() {
1859 1863
1860#[test] 1864#[test]
1861fn closure_1() { 1865fn closure_1() {
1862 check_infer( 1866 check_infer_with_mismatches(
1863 r#" 1867 r#"
1864 #[lang = "fn_once"] 1868 #[lang = "fn_once"]
1865 trait FnOnce<Args> { 1869 trait FnOnce<Args> {
@@ -1868,7 +1872,7 @@ fn closure_1() {
1868 1872
1869 enum Option<T> { Some(T), None } 1873 enum Option<T> { Some(T), None }
1870 impl<T> Option<T> { 1874 impl<T> Option<T> {
1871 fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> {} 1875 fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> { loop {} }
1872 } 1876 }
1873 1877
1874 fn test() { 1878 fn test() {
@@ -1881,37 +1885,39 @@ fn closure_1() {
1881 expect![[r#" 1885 expect![[r#"
1882 147..151 'self': Option<T> 1886 147..151 'self': Option<T>
1883 153..154 'f': F 1887 153..154 'f': F
1884 172..174 '{}': () 1888 172..183 '{ loop {} }': Option<U>
1885 188..307 '{ ... 1); }': () 1889 174..181 'loop {}': !
1886 198..199 'x': Option<u32> 1890 179..181 '{}': ()
1887 202..214 'Option::Some': Some<u32>(u32) -> Option<u32> 1891 197..316 '{ ... 1); }': ()
1888 202..220 'Option...(1u32)': Option<u32> 1892 207..208 'x': Option<u32>
1889 215..219 '1u32': u32 1893 211..223 'Option::Some': Some<u32>(u32) -> Option<u32>
1890 226..227 'x': Option<u32> 1894 211..229 'Option...(1u32)': Option<u32>
1891 226..242 'x.map(...v + 1)': Option<u32> 1895 224..228 '1u32': u32
1892 232..241 '|v| v + 1': |u32| -> u32 1896 235..236 'x': Option<u32>
1893 233..234 'v': u32 1897 235..251 'x.map(...v + 1)': Option<u32>
1894 236..237 'v': u32 1898 241..250 '|v| v + 1': |u32| -> u32
1895 236..241 'v + 1': u32 1899 242..243 'v': u32
1896 240..241 '1': u32 1900 245..246 'v': u32
1897 248..249 'x': Option<u32> 1901 245..250 'v + 1': u32
1898 248..264 'x.map(... 1u64)': Option<u64> 1902 249..250 '1': u32
1899 254..263 '|_v| 1u64': |u32| -> u64 1903 257..258 'x': Option<u32>
1900 255..257 '_v': u32 1904 257..273 'x.map(... 1u64)': Option<u64>
1901 259..263 '1u64': u64 1905 263..272 '|_v| 1u64': |u32| -> u64
1902 274..275 'y': Option<i64> 1906 264..266 '_v': u32
1903 291..292 'x': Option<u32> 1907 268..272 '1u64': u64
1904 291..304 'x.map(|_v| 1)': Option<i64> 1908 283..284 'y': Option<i64>
1905 297..303 '|_v| 1': |u32| -> i64 1909 300..301 'x': Option<u32>
1906 298..300 '_v': u32 1910 300..313 'x.map(|_v| 1)': Option<i64>
1907 302..303 '1': i64 1911 306..312 '|_v| 1': |u32| -> i64
1912 307..309 '_v': u32
1913 311..312 '1': i64
1908 "#]], 1914 "#]],
1909 ); 1915 );
1910} 1916}
1911 1917
1912#[test] 1918#[test]
1913fn closure_2() { 1919fn closure_2() {
1914 check_infer( 1920 check_infer_with_mismatches(
1915 r#" 1921 r#"
1916 trait FnOnce<Args> { 1922 trait FnOnce<Args> {
1917 type Output; 1923 type Output;
@@ -1951,22 +1957,22 @@ fn closure_2() {
1951 1957
1952#[test] 1958#[test]
1953fn closure_as_argument_inference_order() { 1959fn closure_as_argument_inference_order() {
1954 check_infer( 1960 check_infer_with_mismatches(
1955 r#" 1961 r#"
1956 #[lang = "fn_once"] 1962 #[lang = "fn_once"]
1957 trait FnOnce<Args> { 1963 trait FnOnce<Args> {
1958 type Output; 1964 type Output;
1959 } 1965 }
1960 1966
1961 fn foo1<T, U, F: FnOnce(T) -> U>(x: T, f: F) -> U {} 1967 fn foo1<T, U, F: FnOnce(T) -> U>(x: T, f: F) -> U { loop {} }
1962 fn foo2<T, U, F: FnOnce(T) -> U>(f: F, x: T) -> U {} 1968 fn foo2<T, U, F: FnOnce(T) -> U>(f: F, x: T) -> U { loop {} }
1963 1969
1964 struct S; 1970 struct S;
1965 impl S { 1971 impl S {
1966 fn method(self) -> u64; 1972 fn method(self) -> u64;
1967 1973
1968 fn foo1<T, U, F: FnOnce(T) -> U>(self, x: T, f: F) -> U {} 1974 fn foo1<T, U, F: FnOnce(T) -> U>(self, x: T, f: F) -> U { loop {} }
1969 fn foo2<T, U, F: FnOnce(T) -> U>(self, f: F, x: T) -> U {} 1975 fn foo2<T, U, F: FnOnce(T) -> U>(self, f: F, x: T) -> U { loop {} }
1970 } 1976 }
1971 1977
1972 fn test() { 1978 fn test() {
@@ -1979,52 +1985,60 @@ fn closure_as_argument_inference_order() {
1979 expect![[r#" 1985 expect![[r#"
1980 94..95 'x': T 1986 94..95 'x': T
1981 100..101 'f': F 1987 100..101 'f': F
1982 111..113 '{}': () 1988 111..122 '{ loop {} }': U
1983 147..148 'f': F 1989 113..120 'loop {}': !
1984 153..154 'x': T 1990 118..120 '{}': ()
1985 164..166 '{}': () 1991 156..157 'f': F
1986 201..205 'self': S 1992 162..163 'x': T
1987 253..257 'self': S 1993 173..184 '{ loop {} }': U
1988 259..260 'x': T 1994 175..182 'loop {}': !
1989 265..266 'f': F 1995 180..182 '{}': ()
1990 276..278 '{}': () 1996 219..223 'self': S
1991 316..320 'self': S 1997 271..275 'self': S
1992 322..323 'f': F 1998 277..278 'x': T
1993 328..329 'x': T 1999 283..284 'f': F
1994 339..341 '{}': () 2000 294..305 '{ loop {} }': U
1995 355..514 '{ ... S); }': () 2001 296..303 'loop {}': !
1996 365..367 'x1': u64 2002 301..303 '{}': ()
1997 370..374 'foo1': fn foo1<S, u64, |S| -> u64>(S, |S| -> u64) -> u64 2003 343..347 'self': S
1998 370..393 'foo1(S...hod())': u64 2004 349..350 'f': F
1999 375..376 'S': S 2005 355..356 'x': T
2000 378..392 '|s| s.method()': |S| -> u64 2006 366..377 '{ loop {} }': U
2001 379..380 's': S 2007 368..375 'loop {}': !
2002 382..383 's': S 2008 373..375 '{}': ()
2003 382..392 's.method()': u64 2009 391..550 '{ ... S); }': ()
2004 403..405 'x2': u64 2010 401..403 'x1': u64
2005 408..412 'foo2': fn foo2<S, u64, |S| -> u64>(|S| -> u64, S) -> u64 2011 406..410 'foo1': fn foo1<S, u64, |S| -> u64>(S, |S| -> u64) -> u64
2006 408..431 'foo2(|...(), S)': u64 2012 406..429 'foo1(S...hod())': u64
2007 413..427 '|s| s.method()': |S| -> u64 2013 411..412 'S': S
2008 414..415 's': S 2014 414..428 '|s| s.method()': |S| -> u64
2009 417..418 's': S 2015 415..416 's': S
2010 417..427 's.method()': u64 2016 418..419 's': S
2011 429..430 'S': S 2017 418..428 's.method()': u64
2012 441..443 'x3': u64 2018 439..441 'x2': u64
2013 446..447 'S': S 2019 444..448 'foo2': fn foo2<S, u64, |S| -> u64>(|S| -> u64, S) -> u64
2014 446..471 'S.foo1...hod())': u64 2020 444..467 'foo2(|...(), S)': u64
2015 453..454 'S': S 2021 449..463 '|s| s.method()': |S| -> u64
2016 456..470 '|s| s.method()': |S| -> u64 2022 450..451 's': S
2017 457..458 's': S 2023 453..454 's': S
2018 460..461 's': S 2024 453..463 's.method()': u64
2019 460..470 's.method()': u64 2025 465..466 'S': S
2020 481..483 'x4': u64 2026 477..479 'x3': u64
2021 486..487 'S': S 2027 482..483 'S': S
2022 486..511 'S.foo2...(), S)': u64 2028 482..507 'S.foo1...hod())': u64
2023 493..507 '|s| s.method()': |S| -> u64 2029 489..490 'S': S
2024 494..495 's': S 2030 492..506 '|s| s.method()': |S| -> u64
2025 497..498 's': S 2031 493..494 's': S
2026 497..507 's.method()': u64 2032 496..497 's': S
2027 509..510 'S': S 2033 496..506 's.method()': u64
2034 517..519 'x4': u64
2035 522..523 'S': S
2036 522..547 'S.foo2...(), S)': u64
2037 529..543 '|s| s.method()': |S| -> u64
2038 530..531 's': S
2039 533..534 's': S
2040 533..543 's.method()': u64
2041 545..546 'S': S
2028 "#]], 2042 "#]],
2029 ); 2043 );
2030} 2044}
@@ -2536,7 +2550,7 @@ fn test() {
2536 2550
2537#[test] 2551#[test]
2538fn iterator_chain() { 2552fn iterator_chain() {
2539 check_infer( 2553 check_infer_with_mismatches(
2540 r#" 2554 r#"
2541 //- /main.rs 2555 //- /main.rs
2542 #[lang = "fn_once"] 2556 #[lang = "fn_once"]
@@ -2939,7 +2953,7 @@ fn infer_closure_arg() {
2939 2953
2940#[test] 2954#[test]
2941fn infer_fn_trait_arg() { 2955fn infer_fn_trait_arg() {
2942 check_infer( 2956 check_infer_with_mismatches(
2943 r#" 2957 r#"
2944 //- /lib.rs deps:std 2958 //- /lib.rs deps:std
2945 2959
@@ -2986,7 +3000,8 @@ fn infer_fn_trait_arg() {
2986 3000
2987#[test] 3001#[test]
2988fn infer_box_fn_arg() { 3002fn infer_box_fn_arg() {
2989 check_infer( 3003 // The type mismatch is a bug
3004 check_infer_with_mismatches(
2990 r#" 3005 r#"
2991 //- /lib.rs deps:std 3006 //- /lib.rs deps:std
2992 3007
@@ -3025,7 +3040,7 @@ fn infer_box_fn_arg() {
3025 fn foo() { 3040 fn foo() {
3026 let s = Option::None; 3041 let s = Option::None;
3027 let f: Box<dyn FnOnce(&Option<i32>)> = box (|ps| {}); 3042 let f: Box<dyn FnOnce(&Option<i32>)> = box (|ps| {});
3028 f(&s) 3043 f(&s);
3029 } 3044 }
3030 "#, 3045 "#,
3031 expect![[r#" 3046 expect![[r#"
@@ -3037,7 +3052,7 @@ fn infer_box_fn_arg() {
3037 406..417 '&self.inner': &*mut T 3052 406..417 '&self.inner': &*mut T
3038 407..411 'self': &Box<T> 3053 407..411 'self': &Box<T>
3039 407..417 'self.inner': *mut T 3054 407..417 'self.inner': *mut T
3040 478..575 '{ ...(&s) }': FnOnce::Output<dyn FnOnce(&Option<i32>), (&Option<i32>,)> 3055 478..576 '{ ...&s); }': ()
3041 488..489 's': Option<i32> 3056 488..489 's': Option<i32>
3042 492..504 'Option::None': Option<i32> 3057 492..504 'Option::None': Option<i32>
3043 514..515 'f': Box<dyn FnOnce(&Option<i32>)> 3058 514..515 'f': Box<dyn FnOnce(&Option<i32>)>
@@ -3049,6 +3064,7 @@ fn infer_box_fn_arg() {
3049 568..573 'f(&s)': FnOnce::Output<dyn FnOnce(&Option<i32>), (&Option<i32>,)> 3064 568..573 'f(&s)': FnOnce::Output<dyn FnOnce(&Option<i32>), (&Option<i32>,)>
3050 570..572 '&s': &Option<i32> 3065 570..572 '&s': &Option<i32>
3051 571..572 's': Option<i32> 3066 571..572 's': Option<i32>
3067 549..562: expected Box<dyn FnOnce(&Option<i32>)>, got Box<|_| -> ()>
3052 "#]], 3068 "#]],
3053 ); 3069 );
3054} 3070}
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs
index 232cf9cd0..4bd8ba303 100644
--- a/crates/hir_ty/src/traits/chalk.rs
+++ b/crates/hir_ty/src/traits/chalk.rs
@@ -429,7 +429,7 @@ pub(crate) fn trait_datum_query(
429 let generic_params = generics(db.upcast(), trait_.into()); 429 let generic_params = generics(db.upcast(), trait_.into());
430 let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST); 430 let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST);
431 let flags = rust_ir::TraitFlags { 431 let flags = rust_ir::TraitFlags {
432 auto: trait_data.auto, 432 auto: trait_data.is_auto,
433 upstream: trait_.lookup(db.upcast()).container.krate() != krate, 433 upstream: trait_.lookup(db.upcast()).container.krate() != krate,
434 non_enumerable: true, 434 non_enumerable: true,
435 coinductive: false, // only relevant for Chalk testing 435 coinductive: false, // only relevant for Chalk testing
diff --git a/crates/hir_ty/src/traits/chalk/interner.rs b/crates/hir_ty/src/traits/chalk/interner.rs
index 1dc3f497d..94e94a26d 100644
--- a/crates/hir_ty/src/traits/chalk/interner.rs
+++ b/crates/hir_ty/src/traits/chalk/interner.rs
@@ -5,6 +5,7 @@ use super::tls;
5use base_db::salsa::InternId; 5use base_db::salsa::InternId;
6use chalk_ir::{GenericArg, Goal, GoalData}; 6use chalk_ir::{GenericArg, Goal, GoalData};
7use hir_def::TypeAliasId; 7use hir_def::TypeAliasId;
8use smallvec::SmallVec;
8use std::{fmt, sync::Arc}; 9use std::{fmt, sync::Arc};
9 10
10#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] 11#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
@@ -33,7 +34,7 @@ impl chalk_ir::interner::Interner for Interner {
33 type InternedGenericArg = chalk_ir::GenericArgData<Self>; 34 type InternedGenericArg = chalk_ir::GenericArgData<Self>;
34 type InternedGoal = Arc<GoalData<Self>>; 35 type InternedGoal = Arc<GoalData<Self>>;
35 type InternedGoals = Vec<Goal<Self>>; 36 type InternedGoals = Vec<Goal<Self>>;
36 type InternedSubstitution = Vec<GenericArg<Self>>; 37 type InternedSubstitution = SmallVec<[GenericArg<Self>; 2]>;
37 type InternedProgramClause = Arc<chalk_ir::ProgramClauseData<Self>>; 38 type InternedProgramClause = Arc<chalk_ir::ProgramClauseData<Self>>;
38 type InternedProgramClauses = Arc<[chalk_ir::ProgramClause<Self>]>; 39 type InternedProgramClauses = Arc<[chalk_ir::ProgramClause<Self>]>;
39 type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>; 40 type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>;
@@ -265,13 +266,13 @@ impl chalk_ir::interner::Interner for Interner {
265 fn intern_substitution<E>( 266 fn intern_substitution<E>(
266 &self, 267 &self,
267 data: impl IntoIterator<Item = Result<GenericArg<Self>, E>>, 268 data: impl IntoIterator<Item = Result<GenericArg<Self>, E>>,
268 ) -> Result<Vec<GenericArg<Self>>, E> { 269 ) -> Result<Self::InternedSubstitution, E> {
269 data.into_iter().collect() 270 data.into_iter().collect()
270 } 271 }
271 272
272 fn substitution_data<'a>( 273 fn substitution_data<'a>(
273 &self, 274 &self,
274 substitution: &'a Vec<GenericArg<Self>>, 275 substitution: &'a Self::InternedSubstitution,
275 ) -> &'a [GenericArg<Self>] { 276 ) -> &'a [GenericArg<Self>] {
276 substitution 277 substitution
277 } 278 }
diff --git a/crates/ide/src/call_hierarchy.rs b/crates/ide/src/call_hierarchy.rs
index b848945d7..96021f677 100644
--- a/crates/ide/src/call_hierarchy.rs
+++ b/crates/ide/src/call_hierarchy.rs
@@ -53,10 +53,8 @@ pub(crate) fn incoming_calls(db: &RootDatabase, position: FilePosition) -> Optio
53 for (r_range, _) in references { 53 for (r_range, _) in references {
54 let token = file.token_at_offset(r_range.start()).next()?; 54 let token = file.token_at_offset(r_range.start()).next()?;
55 let token = sema.descend_into_macros(token); 55 let token = sema.descend_into_macros(token);
56 let syntax = token.parent();
57
58 // This target is the containing function 56 // This target is the containing function
59 if let Some(nav) = syntax.ancestors().find_map(|node| { 57 if let Some(nav) = token.ancestors().find_map(|node| {
60 let fn_ = ast::Fn::cast(node)?; 58 let fn_ = ast::Fn::cast(node)?;
61 let def = sema.to_def(&fn_)?; 59 let def = sema.to_def(&fn_)?;
62 def.try_to_nav(sema.db) 60 def.try_to_nav(sema.db)
@@ -77,12 +75,13 @@ pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Optio
77 let file = file.syntax(); 75 let file = file.syntax();
78 let token = file.token_at_offset(position.offset).next()?; 76 let token = file.token_at_offset(position.offset).next()?;
79 let token = sema.descend_into_macros(token); 77 let token = sema.descend_into_macros(token);
80 let syntax = token.parent();
81 78
82 let mut calls = CallLocations::default(); 79 let mut calls = CallLocations::default();
83 80
84 syntax 81 token
85 .descendants() 82 .parent()
83 .into_iter()
84 .flat_map(|it| it.descendants())
86 .filter_map(|node| FnCallNode::with_node_exact(&node)) 85 .filter_map(|node| FnCallNode::with_node_exact(&node))
87 .filter_map(|call_node| { 86 .filter_map(|call_node| {
88 let name_ref = call_node.name_ref()?; 87 let name_ref = call_node.name_ref()?;
diff --git a/crates/ide/src/display.rs b/crates/ide/src/display.rs
index bae9e40df..1f7b665c0 100644
--- a/crates/ide/src/display.rs
+++ b/crates/ide/src/display.rs
@@ -5,6 +5,5 @@ pub(crate) mod navigation_target;
5mod short_label; 5mod short_label;
6 6
7pub(crate) use navigation_target::{ToNav, TryToNav}; 7pub(crate) use navigation_target::{ToNav, TryToNav};
8pub(crate) use short_label::ShortLabel;
9 8
10pub(crate) use syntax::display::{function_declaration, macro_label}; 9pub(crate) use syntax::display::{function_declaration, macro_label};
diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs
index 198243466..69c3751a1 100644
--- a/crates/ide/src/display/navigation_target.rs
+++ b/crates/ide/src/display/navigation_target.rs
@@ -3,7 +3,9 @@
3use std::fmt; 3use std::fmt;
4 4
5use either::Either; 5use either::Either;
6use hir::{AssocItem, Documentation, FieldSource, HasAttrs, HasSource, InFile, ModuleSource}; 6use hir::{
7 AssocItem, Documentation, FieldSource, HasAttrs, HasSource, HirDisplay, InFile, ModuleSource,
8};
7use ide_db::{ 9use ide_db::{
8 base_db::{FileId, FileRange, SourceDatabase}, 10 base_db::{FileId, FileRange, SourceDatabase},
9 symbol_index::FileSymbolKind, 11 symbol_index::FileSymbolKind,
@@ -98,7 +100,7 @@ impl NavigationTarget {
98 SymbolKind::Module, 100 SymbolKind::Module,
99 ); 101 );
100 res.docs = module.attrs(db).docs(); 102 res.docs = module.attrs(db).docs();
101 res.description = src.value.short_label(); 103 res.description = Some(module.display(db).to_string());
102 return res; 104 return res;
103 } 105 }
104 module.to_nav(db) 106 module.to_nav(db)
@@ -251,8 +253,8 @@ impl ToNavFromAst for hir::Trait {
251 253
252impl<D> TryToNav for D 254impl<D> TryToNav for D
253where 255where
254 D: HasSource + ToNavFromAst + Copy + HasAttrs, 256 D: HasSource + ToNavFromAst + Copy + HasAttrs + HirDisplay,
255 D::Ast: ast::NameOwner + ShortLabel, 257 D::Ast: ast::NameOwner,
256{ 258{
257 fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { 259 fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
258 let src = self.source(db)?; 260 let src = self.source(db)?;
@@ -262,7 +264,7 @@ where
262 D::KIND, 264 D::KIND,
263 ); 265 );
264 res.docs = self.docs(db); 266 res.docs = self.docs(db);
265 res.description = src.value.short_label(); 267 res.description = Some(self.display(db).to_string());
266 Some(res) 268 Some(res)
267 } 269 }
268} 270}
@@ -317,7 +319,7 @@ impl TryToNav for hir::Field {
317 let mut res = 319 let mut res =
318 NavigationTarget::from_named(db, src.with_value(it), SymbolKind::Field); 320 NavigationTarget::from_named(db, src.with_value(it), SymbolKind::Field);
319 res.docs = self.docs(db); 321 res.docs = self.docs(db);
320 res.description = it.short_label(); 322 res.description = Some(self.display(db).to_string());
321 res 323 res
322 } 324 }
323 FieldSource::Pos(it) => { 325 FieldSource::Pos(it) => {
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs
index 7bdd3cca3..461e11060 100644
--- a/crates/ide/src/doc_links.rs
+++ b/crates/ide/src/doc_links.rs
@@ -279,7 +279,7 @@ pub(crate) fn external_docs(
279 let token = pick_best(file.token_at_offset(position.offset))?; 279 let token = pick_best(file.token_at_offset(position.offset))?;
280 let token = sema.descend_into_macros(token); 280 let token = sema.descend_into_macros(token);
281 281
282 let node = token.parent(); 282 let node = token.parent()?;
283 let definition = match_ast! { 283 let definition = match_ast! {
284 match node { 284 match node {
285 ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)), 285 ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)),
diff --git a/crates/ide/src/extend_selection.rs b/crates/ide/src/extend_selection.rs
index b540d04fe..e187243cb 100644
--- a/crates/ide/src/extend_selection.rs
+++ b/crates/ide/src/extend_selection.rs
@@ -88,7 +88,7 @@ fn try_extend_selection(
88 return Some(range); 88 return Some(range);
89 } 89 }
90 } 90 }
91 token.parent() 91 token.parent()?
92 } 92 }
93 NodeOrToken::Node(node) => node, 93 NodeOrToken::Node(node) => node,
94 }; 94 };
@@ -142,7 +142,8 @@ fn extend_tokens_from_range(
142 let extended = { 142 let extended = {
143 let fst_expanded = sema.descend_into_macros(first_token.clone()); 143 let fst_expanded = sema.descend_into_macros(first_token.clone());
144 let lst_expanded = sema.descend_into_macros(last_token.clone()); 144 let lst_expanded = sema.descend_into_macros(last_token.clone());
145 let mut lca = algo::least_common_ancestor(&fst_expanded.parent(), &lst_expanded.parent())?; 145 let mut lca =
146 algo::least_common_ancestor(&fst_expanded.parent()?, &lst_expanded.parent()?)?;
146 lca = shallowest_node(&lca); 147 lca = shallowest_node(&lca);
147 if lca.first_token() == Some(fst_expanded) && lca.last_token() == Some(lst_expanded) { 148 if lca.first_token() == Some(fst_expanded) && lca.last_token() == Some(lst_expanded) {
148 lca = lca.parent()?; 149 lca = lca.parent()?;
@@ -151,9 +152,13 @@ fn extend_tokens_from_range(
151 }; 152 };
152 153
153 // Compute parent node range 154 // Compute parent node range
154 let validate = |token: &SyntaxToken| { 155 let validate = |token: &SyntaxToken| -> bool {
155 let expanded = sema.descend_into_macros(token.clone()); 156 let expanded = sema.descend_into_macros(token.clone());
156 algo::least_common_ancestor(&extended, &expanded.parent()).as_ref() == Some(&extended) 157 let parent = match expanded.parent() {
158 Some(it) => it,
159 None => return false,
160 };
161 algo::least_common_ancestor(&extended, &parent).as_ref() == Some(&extended)
157 }; 162 };
158 163
159 // Find the first and last text range under expanded parent 164 // Find the first and last text range under expanded parent
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index e8f31e4b1..6986477a5 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -30,7 +30,7 @@ pub(crate) fn goto_definition(
30 let file = sema.parse(position.file_id).syntax().clone(); 30 let file = sema.parse(position.file_id).syntax().clone();
31 let original_token = pick_best(file.token_at_offset(position.offset))?; 31 let original_token = pick_best(file.token_at_offset(position.offset))?;
32 let token = sema.descend_into_macros(original_token.clone()); 32 let token = sema.descend_into_macros(original_token.clone());
33 let parent = token.parent(); 33 let parent = token.parent()?;
34 if let Some(comment) = ast::Comment::cast(token) { 34 if let Some(comment) = ast::Comment::cast(token) {
35 let nav = def_for_doc_comment(&sema, position, &comment)?.try_to_nav(db)?; 35 let nav = def_for_doc_comment(&sema, position, &comment)?.try_to_nav(db)?;
36 return Some(RangeInfo::new(original_token.text_range(), vec![nav])); 36 return Some(RangeInfo::new(original_token.text_range(), vec![nav]));
@@ -63,7 +63,7 @@ fn def_for_doc_comment(
63 position: FilePosition, 63 position: FilePosition,
64 doc_comment: &ast::Comment, 64 doc_comment: &ast::Comment,
65) -> Option<hir::ModuleDef> { 65) -> Option<hir::ModuleDef> {
66 let parent = doc_comment.syntax().parent(); 66 let parent = doc_comment.syntax().parent()?;
67 let (link, ns) = extract_positioned_link_from_comment(position, doc_comment)?; 67 let (link, ns) = extract_positioned_link_from_comment(position, doc_comment)?;
68 68
69 let def = doc_owner_to_def(sema, parent)?; 69 let def = doc_owner_to_def(sema, parent)?;
diff --git a/crates/ide/src/goto_type_definition.rs b/crates/ide/src/goto_type_definition.rs
index 369a59820..2d38cb112 100644
--- a/crates/ide/src/goto_type_definition.rs
+++ b/crates/ide/src/goto_type_definition.rs
@@ -22,7 +22,7 @@ pub(crate) fn goto_type_definition(
22 let token: SyntaxToken = pick_best(file.syntax().token_at_offset(position.offset))?; 22 let token: SyntaxToken = pick_best(file.syntax().token_at_offset(position.offset))?;
23 let token: SyntaxToken = sema.descend_into_macros(token); 23 let token: SyntaxToken = sema.descend_into_macros(token);
24 24
25 let (ty, node) = sema.ancestors_with_macros(token.parent()).find_map(|node| { 25 let (ty, node) = sema.token_ancestors_with_macros(token).find_map(|node| {
26 let ty = match_ast! { 26 let ty = match_ast! {
27 match node { 27 match node {
28 ast::Expr(it) => sema.type_of_expr(&it)?, 28 ast::Expr(it) => sema.type_of_expr(&it)?,
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index ea45086ce..8d45b4875 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -1,7 +1,7 @@
1use either::Either; 1use either::Either;
2use hir::{ 2use hir::{
3 Adt, AsAssocItem, AssocItemContainer, FieldSource, GenericParam, HasAttrs, HasSource, 3 Adt, AsAssocItem, AssocItemContainer, GenericParam, HasAttrs, HasSource, HirDisplay, Module,
4 HirDisplay, Module, ModuleDef, ModuleSource, Semantics, 4 ModuleDef, Semantics,
5}; 5};
6use ide_db::{ 6use ide_db::{
7 base_db::SourceDatabase, 7 base_db::SourceDatabase,
@@ -14,7 +14,7 @@ use stdx::format_to;
14use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T}; 14use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T};
15 15
16use crate::{ 16use crate::{
17 display::{macro_label, ShortLabel, TryToNav}, 17 display::{macro_label, TryToNav},
18 doc_links::{remove_links, rewrite_links}, 18 doc_links::{remove_links, rewrite_links},
19 markdown_remove::remove_markdown, 19 markdown_remove::remove_markdown,
20 markup::Markup, 20 markup::Markup,
@@ -92,7 +92,7 @@ pub(crate) fn hover(
92 92
93 let mut res = HoverResult::default(); 93 let mut res = HoverResult::default();
94 94
95 let node = token.parent(); 95 let node = token.parent()?;
96 let definition = match_ast! { 96 let definition = match_ast! {
97 match node { 97 match node {
98 // we don't use NameClass::referenced_or_defined here as we do not want to resolve 98 // we don't use NameClass::referenced_or_defined here as we do not want to resolve
@@ -335,34 +335,18 @@ fn hover_for_definition(
335 let label = macro_label(&it.source(db)?.value); 335 let label = macro_label(&it.source(db)?.value);
336 from_def_source_labeled(db, it, Some(label), mod_path) 336 from_def_source_labeled(db, it, Some(label), mod_path)
337 } 337 }
338 Definition::Field(def) => { 338 Definition::Field(def) => from_hir_fmt(db, def, mod_path),
339 let src = def.source(db)?.value;
340 if let FieldSource::Named(it) = src {
341 from_def_source_labeled(db, def, it.short_label(), mod_path)
342 } else {
343 None
344 }
345 }
346 Definition::ModuleDef(it) => match it { 339 Definition::ModuleDef(it) => match it {
347 ModuleDef::Module(it) => from_def_source_labeled( 340 ModuleDef::Module(it) => from_hir_fmt(db, it, mod_path),
348 db, 341 ModuleDef::Function(it) => from_hir_fmt(db, it, mod_path),
349 it, 342 ModuleDef::Adt(Adt::Struct(it)) => from_hir_fmt(db, it, mod_path),
350 match it.definition_source(db).value { 343 ModuleDef::Adt(Adt::Union(it)) => from_hir_fmt(db, it, mod_path),
351 ModuleSource::Module(it) => it.short_label(), 344 ModuleDef::Adt(Adt::Enum(it)) => from_hir_fmt(db, it, mod_path),
352 ModuleSource::SourceFile(it) => it.short_label(), 345 ModuleDef::Variant(it) => from_hir_fmt(db, it, mod_path),
353 ModuleSource::BlockExpr(it) => it.short_label(), 346 ModuleDef::Const(it) => from_hir_fmt(db, it, mod_path),
354 }, 347 ModuleDef::Static(it) => from_hir_fmt(db, it, mod_path),
355 mod_path, 348 ModuleDef::Trait(it) => from_hir_fmt(db, it, mod_path),
356 ), 349 ModuleDef::TypeAlias(it) => from_hir_fmt(db, it, mod_path),
357 ModuleDef::Function(it) => from_def_source(db, it, mod_path),
358 ModuleDef::Adt(Adt::Struct(it)) => from_def_source(db, it, mod_path),
359 ModuleDef::Adt(Adt::Union(it)) => from_def_source(db, it, mod_path),
360 ModuleDef::Adt(Adt::Enum(it)) => from_def_source(db, it, mod_path),
361 ModuleDef::Variant(it) => from_def_source(db, it, mod_path),
362 ModuleDef::Const(it) => from_def_source(db, it, mod_path),
363 ModuleDef::Static(it) => from_def_source(db, it, mod_path),
364 ModuleDef::Trait(it) => from_def_source(db, it, mod_path),
365 ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path),
366 ModuleDef::BuiltinType(it) => famous_defs 350 ModuleDef::BuiltinType(it) => famous_defs
367 .and_then(|fd| hover_for_builtin(fd, it)) 351 .and_then(|fd| hover_for_builtin(fd, it))
368 .or_else(|| Some(Markup::fenced_block(&it.name()))), 352 .or_else(|| Some(Markup::fenced_block(&it.name()))),
@@ -370,26 +354,25 @@ fn hover_for_definition(
370 Definition::Local(it) => hover_for_local(it, db), 354 Definition::Local(it) => hover_for_local(it, db),
371 Definition::SelfType(impl_def) => { 355 Definition::SelfType(impl_def) => {
372 impl_def.target_ty(db).as_adt().and_then(|adt| match adt { 356 impl_def.target_ty(db).as_adt().and_then(|adt| match adt {
373 Adt::Struct(it) => from_def_source(db, it, mod_path), 357 Adt::Struct(it) => from_hir_fmt(db, it, mod_path),
374 Adt::Union(it) => from_def_source(db, it, mod_path), 358 Adt::Union(it) => from_hir_fmt(db, it, mod_path),
375 Adt::Enum(it) => from_def_source(db, it, mod_path), 359 Adt::Enum(it) => from_hir_fmt(db, it, mod_path),
376 }) 360 })
377 } 361 }
378 Definition::Label(it) => Some(Markup::fenced_block(&it.name(db))), 362 Definition::Label(it) => Some(Markup::fenced_block(&it.name(db))),
379 Definition::GenericParam(it) => match it { 363 Definition::GenericParam(it) => match it {
380 GenericParam::TypeParam(it) => Some(Markup::fenced_block(&it.display(db))), 364 GenericParam::TypeParam(it) => Some(Markup::fenced_block(&it.display(db))),
381 GenericParam::LifetimeParam(it) => Some(Markup::fenced_block(&it.name(db))), 365 GenericParam::LifetimeParam(it) => Some(Markup::fenced_block(&it.name(db))),
382 GenericParam::ConstParam(it) => from_def_source(db, it, None), 366 GenericParam::ConstParam(it) => Some(Markup::fenced_block(&it.display(db))),
383 }, 367 },
384 }; 368 };
385 369
386 fn from_def_source<A, D>(db: &RootDatabase, def: D, mod_path: Option<String>) -> Option<Markup> 370 fn from_hir_fmt<D>(db: &RootDatabase, def: D, mod_path: Option<String>) -> Option<Markup>
387 where 371 where
388 D: HasSource<Ast = A> + HasAttrs + Copy, 372 D: HasAttrs + HirDisplay,
389 A: ShortLabel,
390 { 373 {
391 let short_label = def.source(db)?.value.short_label(); 374 let label = def.display(db).to_string();
392 from_def_source_labeled(db, def, short_label, mod_path) 375 from_def_source_labeled(db, def, Some(label), mod_path)
393 } 376 }
394 377
395 fn from_def_source_labeled<D>( 378 fn from_def_source_labeled<D>(
@@ -438,7 +421,7 @@ fn hover_for_keyword(
438 if !token.kind().is_keyword() { 421 if !token.kind().is_keyword() {
439 return None; 422 return None;
440 } 423 }
441 let famous_defs = FamousDefs(&sema, sema.scope(&token.parent()).krate()); 424 let famous_defs = FamousDefs(&sema, sema.scope(&token.parent()?).krate());
442 // std exposes {}_keyword modules with docstrings on the root to document keywords 425 // std exposes {}_keyword modules with docstrings on the root to document keywords
443 let keyword_mod = format!("{}_keyword", token.text()); 426 let keyword_mod = format!("{}_keyword", token.text());
444 let doc_owner = find_std_module(&famous_defs, &keyword_mod)?; 427 let doc_owner = find_std_module(&famous_defs, &keyword_mod)?;
@@ -670,7 +653,9 @@ fn main() { let foo_test = fo$0o(); }
670 ``` 653 ```
671 654
672 ```rust 655 ```rust
673 pub fn foo<'a, T: AsRef<str>>(b: &'a T) -> &'a str 656 pub fn foo<'a, T>(b: &'a T) -> &'a str
657 where
658 T: AsRef<str>,
674 ``` 659 ```
675 "#]], 660 "#]],
676 ); 661 );
@@ -878,7 +863,7 @@ fn main() { So$0me(12); }
878 ``` 863 ```
879 864
880 ```rust 865 ```rust
881 Some 866 Some(T)
882 ``` 867 ```
883 "#]], 868 "#]],
884 ); 869 );
@@ -944,7 +929,7 @@ fn main() {
944 ``` 929 ```
945 930
946 ```rust 931 ```rust
947 Some 932 Some(T)
948 ``` 933 ```
949 934
950 --- 935 ---
@@ -1441,13 +1426,14 @@ fn bar() { fo$0o(); }
1441 ``` 1426 ```
1442 "#]], 1427 "#]],
1443 ); 1428 );
1429 // Top level `pub(crate)` will be displayed as no visibility.
1444 check( 1430 check(
1445 r#"pub(crate) async unsafe extern "C" fn foo$0() {}"#, 1431 r#"mod m { pub(crate) async unsafe extern "C" fn foo$0() {} }"#,
1446 expect![[r#" 1432 expect![[r#"
1447 *foo* 1433 *foo*
1448 1434
1449 ```rust 1435 ```rust
1450 test 1436 test::m
1451 ``` 1437 ```
1452 1438
1453 ```rust 1439 ```rust
@@ -1489,11 +1475,18 @@ extern crate st$0d;
1489//! abc123 1475//! abc123
1490 "#, 1476 "#,
1491 expect![[r#" 1477 expect![[r#"
1492 *std* 1478 *std*
1493 Standard library for this test 1479
1480 ```rust
1481 extern crate std
1482 ```
1494 1483
1495 Printed? 1484 ---
1496 abc123 1485
1486 Standard library for this test
1487
1488 Printed?
1489 abc123
1497 "#]], 1490 "#]],
1498 ); 1491 );
1499 check( 1492 check(
@@ -1507,11 +1500,18 @@ extern crate std as ab$0c;
1507//! abc123 1500//! abc123
1508 "#, 1501 "#,
1509 expect![[r#" 1502 expect![[r#"
1510 *abc* 1503 *abc*
1511 Standard library for this test 1504
1505 ```rust
1506 extern crate std
1507 ```
1508
1509 ---
1512 1510
1513 Printed? 1511 Standard library for this test
1514 abc123 1512
1513 Printed?
1514 abc123
1515 "#]], 1515 "#]],
1516 ); 1516 );
1517 } 1517 }
@@ -2021,7 +2021,7 @@ enum E {
2021 ``` 2021 ```
2022 2022
2023 ```rust 2023 ```rust
2024 V 2024 V { field: i32 }
2025 ``` 2025 ```
2026 2026
2027 --- 2027 ---
@@ -2417,7 +2417,7 @@ fn main() { let s$0t = S{ f1:Arg(0) }; }
2417 focus_range: 24..25, 2417 focus_range: 24..25,
2418 name: "S", 2418 name: "S",
2419 kind: Struct, 2419 kind: Struct,
2420 description: "struct S", 2420 description: "struct S<T>",
2421 }, 2421 },
2422 }, 2422 },
2423 HoverGotoTypeData { 2423 HoverGotoTypeData {
@@ -2463,7 +2463,7 @@ fn main() { let s$0t = S{ f1: S{ f1: Arg(0) } }; }
2463 focus_range: 24..25, 2463 focus_range: 24..25,
2464 name: "S", 2464 name: "S",
2465 kind: Struct, 2465 kind: Struct,
2466 description: "struct S", 2466 description: "struct S<T>",
2467 }, 2467 },
2468 }, 2468 },
2469 HoverGotoTypeData { 2469 HoverGotoTypeData {
@@ -2605,7 +2605,7 @@ fn main() { let s$0t = foo(); }
2605 focus_range: 6..9, 2605 focus_range: 6..9,
2606 name: "Foo", 2606 name: "Foo",
2607 kind: Trait, 2607 kind: Trait,
2608 description: "trait Foo", 2608 description: "trait Foo<T>",
2609 }, 2609 },
2610 }, 2610 },
2611 HoverGotoTypeData { 2611 HoverGotoTypeData {
@@ -2702,7 +2702,7 @@ fn main() { let s$0t = foo(); }
2702 focus_range: 6..9, 2702 focus_range: 6..9,
2703 name: "Foo", 2703 name: "Foo",
2704 kind: Trait, 2704 kind: Trait,
2705 description: "trait Foo", 2705 description: "trait Foo<T>",
2706 }, 2706 },
2707 }, 2707 },
2708 HoverGotoTypeData { 2708 HoverGotoTypeData {
@@ -2715,7 +2715,7 @@ fn main() { let s$0t = foo(); }
2715 focus_range: 22..25, 2715 focus_range: 22..25,
2716 name: "Bar", 2716 name: "Bar",
2717 kind: Trait, 2717 kind: Trait,
2718 description: "trait Bar", 2718 description: "trait Bar<T>",
2719 }, 2719 },
2720 }, 2720 },
2721 HoverGotoTypeData { 2721 HoverGotoTypeData {
@@ -2819,7 +2819,7 @@ fn foo(ar$0g: &impl Foo + Bar<S>) {}
2819 focus_range: 19..22, 2819 focus_range: 19..22,
2820 name: "Bar", 2820 name: "Bar",
2821 kind: Trait, 2821 kind: Trait,
2822 description: "trait Bar", 2822 description: "trait Bar<T>",
2823 }, 2823 },
2824 }, 2824 },
2825 HoverGotoTypeData { 2825 HoverGotoTypeData {
@@ -2916,7 +2916,7 @@ fn foo(ar$0g: &impl Foo<S>) {}
2916 focus_range: 6..9, 2916 focus_range: 6..9,
2917 name: "Foo", 2917 name: "Foo",
2918 kind: Trait, 2918 kind: Trait,
2919 description: "trait Foo", 2919 description: "trait Foo<T>",
2920 }, 2920 },
2921 }, 2921 },
2922 HoverGotoTypeData { 2922 HoverGotoTypeData {
@@ -2966,7 +2966,7 @@ fn main() { let s$0t = foo(); }
2966 focus_range: 49..50, 2966 focus_range: 49..50,
2967 name: "B", 2967 name: "B",
2968 kind: Struct, 2968 kind: Struct,
2969 description: "struct B", 2969 description: "struct B<T>",
2970 }, 2970 },
2971 }, 2971 },
2972 HoverGotoTypeData { 2972 HoverGotoTypeData {
@@ -3042,7 +3042,7 @@ fn foo(ar$0g: &dyn Foo<S>) {}
3042 focus_range: 6..9, 3042 focus_range: 6..9,
3043 name: "Foo", 3043 name: "Foo",
3044 kind: Trait, 3044 kind: Trait,
3045 description: "trait Foo", 3045 description: "trait Foo<T>",
3046 }, 3046 },
3047 }, 3047 },
3048 HoverGotoTypeData { 3048 HoverGotoTypeData {
@@ -3090,7 +3090,7 @@ fn foo(a$0rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
3090 focus_range: 6..15, 3090 focus_range: 6..15,
3091 name: "ImplTrait", 3091 name: "ImplTrait",
3092 kind: Trait, 3092 kind: Trait,
3093 description: "trait ImplTrait", 3093 description: "trait ImplTrait<T>",
3094 }, 3094 },
3095 }, 3095 },
3096 HoverGotoTypeData { 3096 HoverGotoTypeData {
@@ -3103,7 +3103,7 @@ fn foo(a$0rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
3103 focus_range: 50..51, 3103 focus_range: 50..51,
3104 name: "B", 3104 name: "B",
3105 kind: Struct, 3105 kind: Struct,
3106 description: "struct B", 3106 description: "struct B<T>",
3107 }, 3107 },
3108 }, 3108 },
3109 HoverGotoTypeData { 3109 HoverGotoTypeData {
@@ -3116,7 +3116,7 @@ fn foo(a$0rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
3116 focus_range: 28..36, 3116 focus_range: 28..36,
3117 name: "DynTrait", 3117 name: "DynTrait",
3118 kind: Trait, 3118 kind: Trait,
3119 description: "trait DynTrait", 3119 description: "trait DynTrait<T>",
3120 }, 3120 },
3121 }, 3121 },
3122 HoverGotoTypeData { 3122 HoverGotoTypeData {
@@ -3582,6 +3582,17 @@ mod foo$0;
3582"#, 3582"#,
3583 expect![[r#" 3583 expect![[r#"
3584 *foo* 3584 *foo*
3585
3586 ```rust
3587 test
3588 ```
3589
3590 ```rust
3591 mod foo
3592 ```
3593
3594 ---
3595
3585 For the horde! 3596 For the horde!
3586 "#]], 3597 "#]],
3587 ); 3598 );
@@ -3606,7 +3617,7 @@ use foo::bar::{self$0};
3606 ``` 3617 ```
3607 3618
3608 ```rust 3619 ```rust
3609 pub mod bar 3620 mod bar
3610 ``` 3621 ```
3611 3622
3612 --- 3623 ---
@@ -3657,4 +3668,43 @@ cosnt _: &str$0 = ""; }"#;