diff options
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 | ||
17 | jobs: | 18 | jobs: |
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. |
3 | version = 3 | ||
4 | |||
5 | [[package]] | 3 | [[package]] |
6 | name = "addr2line" | 4 | name = "addr2line" |
7 | version = "0.14.1" | 5 | version = "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]] |
1327 | name = "rowan" | 1326 | name = "rowan" |
1328 | version = "0.12.6" | 1327 | version = "0.13.0-pre.2" |
1329 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1328 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1330 | checksum = "a1b36e449f3702f3b0c821411db1cbdf30fb451726a9456dce5dabcd44420043" | 1329 | checksum = "8f300be7fa17c3fa563d2bc6ab5b1a8d5163162f9111599eda4f86a563714724" |
1331 | dependencies = [ | 1330 | dependencies = [ |
1332 | "countme", | 1331 | "countme", |
1333 | "hashbrown", | 1332 | "hashbrown", |
@@ -1810,9 +1809,9 @@ checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" | |||
1810 | 1809 | ||
1811 | [[package]] | 1810 | [[package]] |
1812 | name = "ungrammar" | 1811 | name = "ungrammar" |
1813 | version = "1.11.0" | 1812 | version = "1.12.2" |
1814 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1813 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1815 | checksum = "84c629795d377049f2a1dc5f42cf505dc5ba8b28a5df0a03f4183a24480e4a6a" | 1814 | checksum = "df6586a7c530704efe803d49a0b4132dcbdb4063163df39110548e6b5f2373ba" |
1816 | 1815 | ||
1817 | [[package]] | 1816 | [[package]] |
1818 | name = "unicase" | 1817 | name = "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" | |||
15 | either = "1.5.3" | 15 | either = "1.5.3" |
16 | arrayvec = "0.5.1" | 16 | arrayvec = "0.5.1" |
17 | itertools = "0.10.0" | 17 | itertools = "0.10.0" |
18 | smallvec = "1.4.0" | ||
18 | 19 | ||
19 | stdx = { path = "../stdx", version = "0.0.0" } | 20 | stdx = { path = "../stdx", version = "0.0.0" } |
20 | syntax = { path = "../syntax", version = "0.0.0" } | 21 | syntax = { 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. | ||
2 | use hir_def::{ | ||
3 | adt::VariantData, | ||
4 | generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget}, | ||
5 | type_ref::{TypeBound, TypeRef}, | ||
6 | AdtId, GenericDefId, | ||
7 | }; | ||
8 | use hir_ty::display::{ | ||
9 | write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError, | ||
10 | HirFormatter, | ||
11 | }; | ||
12 | use syntax::ast::{self, NameOwner}; | ||
13 | |||
14 | use crate::{ | ||
15 | Const, ConstParam, Enum, Field, Function, HasVisibility, Module, Static, Struct, Substs, Trait, | ||
16 | Type, TypeAlias, TypeParam, Union, Variant, | ||
17 | }; | ||
18 | |||
19 | impl 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 | |||
123 | impl 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 | |||
135 | impl 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 | |||
147 | impl 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 | |||
159 | impl 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 | |||
167 | impl 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 | |||
208 | impl HirDisplay for Type { | ||
209 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
210 | self.ty.value.hir_fmt(f) | ||
211 | } | ||
212 | } | ||
213 | |||
214 | impl 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 | |||
227 | impl 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 | |||
234 | fn 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 | |||
283 | fn 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 ¶ms.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(¶ms.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 | |||
359 | impl 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 | |||
373 | impl 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 | |||
390 | impl 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 | |||
412 | impl 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 | |||
429 | impl 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; | |||
29 | pub mod diagnostics; | 29 | pub mod diagnostics; |
30 | pub mod db; | 30 | pub mod db; |
31 | 31 | ||
32 | mod display; | ||
33 | |||
32 | use std::{iter, sync::Arc}; | 34 | use std::{iter, sync::Arc}; |
33 | 35 | ||
34 | use arrayvec::ArrayVec; | 36 | use arrayvec::ArrayVec; |
@@ -50,8 +52,8 @@ use hir_def::{ | |||
50 | use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind}; | 52 | use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind}; |
51 | use hir_ty::{ | 53 | use 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 | ||
584 | impl 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)] |
583 | pub struct Union { | 591 | pub struct Union { |
584 | pub(crate) id: UnionId, | 592 | pub(crate) id: UnionId, |
@@ -611,6 +619,12 @@ impl Union { | |||
611 | } | 619 | } |
612 | } | 620 | } |
613 | 621 | ||
622 | impl 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)] |
615 | pub struct Enum { | 629 | pub struct Enum { |
616 | pub(crate) id: EnumId, | 630 | pub(crate) id: EnumId, |
@@ -638,6 +652,12 @@ impl Enum { | |||
638 | } | 652 | } |
639 | } | 653 | } |
640 | 654 | ||
655 | impl 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)] |
642 | pub struct Variant { | 662 | pub 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)] |
902 | pub struct Param { | 923 | pub 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 | ||
934 | impl HasVisibility for Function { | 975 | impl 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 | ||
961 | impl HasVisibility for Const { | 1006 | impl HasVisibility for Const { |
@@ -989,6 +1034,12 @@ impl Static { | |||
989 | } | 1034 | } |
990 | } | 1035 | } |
991 | 1036 | ||
1037 | impl 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)] |
993 | pub struct Trait { | 1044 | pub 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 | |||
1066 | impl 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 | ||
1423 | impl 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)] |
1437 | pub struct LifetimeParam { | 1481 | pub 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 | ||
2072 | impl 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)] |
2080 | pub struct Callable { | 2122 | pub 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 | }; |
13 | use hir_expand::{name::AsName, AstId, MacroDefKind}; | 13 | use hir_expand::{name::AsName, AstId, MacroDefKind}; |
14 | use rustc_hash::FxHashMap; | 14 | use rustc_hash::FxHashMap; |
15 | use smallvec::SmallVec; | ||
15 | use stdx::impl_from; | 16 | use stdx::impl_from; |
16 | use syntax::{ | 17 | use syntax::{ |
17 | ast::{self, NameOwner}, | 18 | ast::{self, NameOwner}, |
@@ -28,14 +29,19 @@ pub(super) struct SourceToDefCtx<'a, 'b> { | |||
28 | } | 29 | } |
29 | 30 | ||
30 | impl SourceToDefCtx<'_, '_> { | 31 | impl 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)] |
37 | pub struct EnumData { | 38 | pub 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 { | |||
87 | pub struct TraitData { | 87 | pub 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 | ||
93 | impl TraitData { | 96 | impl 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)] |
103 | pub struct UnresolvedMacroCall { | 103 | pub 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}; | |||
24 | use profile::Count; | 24 | use profile::Count; |
25 | use rustc_hash::FxHashMap; | 25 | use rustc_hash::FxHashMap; |
26 | use smallvec::SmallVec; | 26 | use smallvec::SmallVec; |
27 | use syntax::{ast, match_ast, SyntaxKind}; | 27 | use syntax::{ast, match_ast, SmolStr, SyntaxKind}; |
28 | 28 | ||
29 | use crate::{ | 29 | use 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)] | ||
570 | pub 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)] |
565 | pub struct Struct { | 579 | pub 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 | }; |
18 | use hir_expand::{InFile, MacroCallLoc}; | 18 | use hir_expand::{InFile, MacroCallLoc}; |
19 | use rustc_hash::{FxHashMap, FxHashSet}; | 19 | use 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] | ||
160 | fn 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] | ||
174 | fn 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] | ||
191 | fn 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 | ||
10 | use crate::{body::LowerCtx, type_ref::LifetimeRef}; | 10 | use crate::{body::LowerCtx, type_ref::LifetimeRef}; |
11 | use base_db::CrateId; | 11 | use base_db::CrateId; |
12 | use hir_expand::{hygiene::Hygiene, name::Name}; | 12 | use hir_expand::{ |
13 | hygiene::Hygiene, | ||
14 | name::{name, Name}, | ||
15 | }; | ||
13 | use syntax::ast; | 16 | use syntax::ast; |
14 | 17 | ||
15 | use crate::{ | 18 | use 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}; | |||
5 | use arrayvec::ArrayVec; | 5 | use arrayvec::ArrayVec; |
6 | use chalk_ir::Mutability; | 6 | use chalk_ir::Mutability; |
7 | use hir_def::{ | 7 | use 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 | }; |
11 | use hir_expand::name::Name; | 17 | use hir_expand::name::Name; |
@@ -232,7 +238,7 @@ where | |||
232 | 238 | ||
233 | const TYPE_HINT_TRUNCATION: &str = "…"; | 239 | const TYPE_HINT_TRUNCATION: &str = "…"; |
234 | 240 | ||
235 | impl HirDisplay for &Ty { | 241 | impl<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 | ||
764 | impl HirDisplay for &GenericPredicate { | ||
765 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
766 | HirDisplay::hir_fmt(*self, f) | ||
767 | } | ||
768 | } | ||
769 | |||
770 | impl HirDisplay for GenericPredicate { | 770 | impl 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 | |||
829 | pub 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 | |||
853 | impl 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 | |||
929 | impl 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 | |||
939 | impl 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 | |||
1007 | impl 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 | }; |
33 | use itertools::Itertools; | 33 | use itertools::Itertools; |
34 | use smallvec::SmallVec; | ||
34 | 35 | ||
35 | use crate::{ | 36 | use 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)] |
275 | pub struct Substs(Arc<[Ty]>); | 276 | pub struct Substs(SmallVec<[Ty; 2]>); |
276 | 277 | ||
277 | impl TypeWalk for Substs { | 278 | impl 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 | ||
295 | impl Substs { | 296 | impl 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] |
219 | fn 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] | ||
219 | fn infer_type_value_macro_having_same_name() { | 235 | fn 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] |
1701 | fn fn_trait() { | 1701 | fn 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] |
1729 | fn fn_ptr_and_item() { | 1729 | fn 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] |
1861 | fn closure_1() { | 1865 | fn 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] |
1913 | fn closure_2() { | 1919 | fn 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] |
1953 | fn closure_as_argument_inference_order() { | 1959 | fn 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] |
2538 | fn iterator_chain() { | 2552 | fn 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] |
2941 | fn infer_fn_trait_arg() { | 2955 | fn 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] |
2988 | fn infer_box_fn_arg() { | 3002 | fn 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; | |||
5 | use base_db::salsa::InternId; | 5 | use base_db::salsa::InternId; |
6 | use chalk_ir::{GenericArg, Goal, GoalData}; | 6 | use chalk_ir::{GenericArg, Goal, GoalData}; |
7 | use hir_def::TypeAliasId; | 7 | use hir_def::TypeAliasId; |
8 | use smallvec::SmallVec; | ||
8 | use std::{fmt, sync::Arc}; | 9 | use 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; | |||
5 | mod short_label; | 5 | mod short_label; |
6 | 6 | ||
7 | pub(crate) use navigation_target::{ToNav, TryToNav}; | 7 | pub(crate) use navigation_target::{ToNav, TryToNav}; |
8 | pub(crate) use short_label::ShortLabel; | ||
9 | 8 | ||
10 | pub(crate) use syntax::display::{function_declaration, macro_label}; | 9 | pub(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 @@ | |||
3 | use std::fmt; | 3 | use std::fmt; |
4 | 4 | ||
5 | use either::Either; | 5 | use either::Either; |
6 | use hir::{AssocItem, Documentation, FieldSource, HasAttrs, HasSource, InFile, ModuleSource}; | 6 | use hir::{ |
7 | AssocItem, Documentation, FieldSource, HasAttrs, HasSource, HirDisplay, InFile, ModuleSource, | ||
8 | }; | ||
7 | use ide_db::{ | 9 | use 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 | ||
252 | impl<D> TryToNav for D | 254 | impl<D> TryToNav for D |
253 | where | 255 | where |
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 @@ | |||
1 | use either::Either; | 1 | use either::Either; |
2 | use hir::{ | 2 | use 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 | }; |
6 | use ide_db::{ | 6 | use ide_db::{ |
7 | base_db::SourceDatabase, | 7 | base_db::SourceDatabase, |
@@ -14,7 +14,7 @@ use stdx::format_to; | |||
14 | use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T}; | 14 | use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T}; |
15 | 15 | ||
16 | use crate::{ | 16 | use 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 = ""; }"#; | |||