aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r--crates/ra_hir_ty/Cargo.toml7
-rw-r--r--crates/ra_hir_ty/src/_match.rs1411
-rw-r--r--crates/ra_hir_ty/src/autoderef.rs19
-rw-r--r--crates/ra_hir_ty/src/diagnostics.rs21
-rw-r--r--crates/ra_hir_ty/src/display.rs22
-rw-r--r--crates/ra_hir_ty/src/expr.rs205
-rw-r--r--crates/ra_hir_ty/src/infer/pat.rs17
-rw-r--r--crates/ra_hir_ty/src/infer/path.rs12
-rw-r--r--crates/ra_hir_ty/src/infer/unify.rs28
-rw-r--r--crates/ra_hir_ty/src/lib.rs108
-rw-r--r--crates/ra_hir_ty/src/lower.rs28
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs16
-rw-r--r--crates/ra_hir_ty/src/test_db.rs6
-rw-r--r--crates/ra_hir_ty/src/tests.rs3
-rw-r--r--crates/ra_hir_ty/src/tests/coercion.rs14
-rw-r--r--crates/ra_hir_ty/src/tests/macros.rs31
-rw-r--r--crates/ra_hir_ty/src/tests/patterns.rs85
-rw-r--r--crates/ra_hir_ty/src/tests/regression.rs5
-rw-r--r--crates/ra_hir_ty/src/tests/simple.rs30
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs37
-rw-r--r--crates/ra_hir_ty/src/traits.rs16
-rw-r--r--crates/ra_hir_ty/src/traits/builtin.rs53
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs160
-rw-r--r--crates/ra_hir_ty/src/utils.rs6
24 files changed, 2126 insertions, 214 deletions
diff --git a/crates/ra_hir_ty/Cargo.toml b/crates/ra_hir_ty/Cargo.toml
index 5a58d70cf..9a4a7aa6f 100644
--- a/crates/ra_hir_ty/Cargo.toml
+++ b/crates/ra_hir_ty/Cargo.toml
@@ -9,6 +9,7 @@ doctest = false
9 9
10[dependencies] 10[dependencies]
11arrayvec = "0.5.1" 11arrayvec = "0.5.1"
12smallvec = "1.2.0"
12ena = "0.13.1" 13ena = "0.13.1"
13log = "0.4.8" 14log = "0.4.8"
14rustc-hash = "1.1.0" 15rustc-hash = "1.1.0"
@@ -23,9 +24,9 @@ ra_prof = { path = "../ra_prof" }
23ra_syntax = { path = "../ra_syntax" } 24ra_syntax = { path = "../ra_syntax" }
24test_utils = { path = "../test_utils" } 25test_utils = { path = "../test_utils" }
25 26
26chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "177d71340acc7a7204a33115fc63075d86452179" } 27chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" }
27chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "177d71340acc7a7204a33115fc63075d86452179" } 28chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" }
28chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "177d71340acc7a7204a33115fc63075d86452179" } 29chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" }
29 30
30[dev-dependencies] 31[dev-dependencies]
31insta = "0.15.0" 32insta = "0.15.0"
diff --git a/crates/ra_hir_ty/src/_match.rs b/crates/ra_hir_ty/src/_match.rs
new file mode 100644
index 000000000..f29a25505
--- /dev/null
+++ b/crates/ra_hir_ty/src/_match.rs
@@ -0,0 +1,1411 @@
1//! This module implements match statement exhaustiveness checking and usefulness checking
2//! for match arms.
3//!
4//! It is modeled on the rustc module `librustc_mir_build::hair::pattern::_match`, which
5//! contains very detailed documentation about the algorithms used here. I've duplicated
6//! most of that documentation below.
7//!
8//! This file includes the logic for exhaustiveness and usefulness checking for
9//! pattern-matching. Specifically, given a list of patterns for a type, we can
10//! tell whether:
11//! (a) the patterns cover every possible constructor for the type [exhaustiveness]
12//! (b) each pattern is necessary [usefulness]
13//!
14//! The algorithm implemented here is a modified version of the one described in:
15//! http://moscova.inria.fr/~maranget/papers/warn/index.html
16//! However, to save future implementors from reading the original paper, we
17//! summarise the algorithm here to hopefully save time and be a little clearer
18//! (without being so rigorous).
19//!
20//! The core of the algorithm revolves about a "usefulness" check. In particular, we
21//! are trying to compute a predicate `U(P, p)` where `P` is a list of patterns (we refer to this as
22//! a matrix). `U(P, p)` represents whether, given an existing list of patterns
23//! `P_1 ..= P_m`, adding a new pattern `p` will be "useful" (that is, cover previously-
24//! uncovered values of the type).
25//!
26//! If we have this predicate, then we can easily compute both exhaustiveness of an
27//! entire set of patterns and the individual usefulness of each one.
28//! (a) the set of patterns is exhaustive iff `U(P, _)` is false (i.e., adding a wildcard
29//! match doesn't increase the number of values we're matching)
30//! (b) a pattern `P_i` is not useful if `U(P[0..=(i-1), P_i)` is false (i.e., adding a
31//! pattern to those that have come before it doesn't increase the number of values
32//! we're matching).
33//!
34//! During the course of the algorithm, the rows of the matrix won't just be individual patterns,
35//! but rather partially-deconstructed patterns in the form of a list of patterns. The paper
36//! calls those pattern-vectors, and we will call them pattern-stacks. The same holds for the
37//! new pattern `p`.
38//!
39//! For example, say we have the following:
40//! ```
41//! // x: (Option<bool>, Result<()>)
42//! match x {
43//! (Some(true), _) => {}
44//! (None, Err(())) => {}
45//! (None, Err(_)) => {}
46//! }
47//! ```
48//! Here, the matrix `P` starts as:
49//! [
50//! [(Some(true), _)],
51//! [(None, Err(()))],
52//! [(None, Err(_))],
53//! ]
54//! We can tell it's not exhaustive, because `U(P, _)` is true (we're not covering
55//! `[(Some(false), _)]`, for instance). In addition, row 3 is not useful, because
56//! all the values it covers are already covered by row 2.
57//!
58//! A list of patterns can be thought of as a stack, because we are mainly interested in the top of
59//! the stack at any given point, and we can pop or apply constructors to get new pattern-stacks.
60//! To match the paper, the top of the stack is at the beginning / on the left.
61//!
62//! There are two important operations on pattern-stacks necessary to understand the algorithm:
63//! 1. We can pop a given constructor off the top of a stack. This operation is called
64//! `specialize`, and is denoted `S(c, p)` where `c` is a constructor (like `Some` or
65//! `None`) and `p` a pattern-stack.
66//! If the pattern on top of the stack can cover `c`, this removes the constructor and
67//! pushes its arguments onto the stack. It also expands OR-patterns into distinct patterns.
68//! Otherwise the pattern-stack is discarded.
69//! This essentially filters those pattern-stacks whose top covers the constructor `c` and
70//! discards the others.
71//!
72//! For example, the first pattern above initially gives a stack `[(Some(true), _)]`. If we
73//! pop the tuple constructor, we are left with `[Some(true), _]`, and if we then pop the
74//! `Some` constructor we get `[true, _]`. If we had popped `None` instead, we would get
75//! nothing back.
76//!
77//! This returns zero or more new pattern-stacks, as follows. We look at the pattern `p_1`
78//! on top of the stack, and we have four cases:
79//! 1.1. `p_1 = c(r_1, .., r_a)`, i.e. the top of the stack has constructor `c`. We
80//! push onto the stack the arguments of this constructor, and return the result:
81//! r_1, .., r_a, p_2, .., p_n
82//! 1.2. `p_1 = c'(r_1, .., r_a')` where `c ≠ c'`. We discard the current stack and
83//! return nothing.
84//! 1.3. `p_1 = _`. We push onto the stack as many wildcards as the constructor `c` has
85//! arguments (its arity), and return the resulting stack:
86//! _, .., _, p_2, .., p_n
87//! 1.4. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting
88//! stack:
89//! S(c, (r_1, p_2, .., p_n))
90//! S(c, (r_2, p_2, .., p_n))
91//!
92//! 2. We can pop a wildcard off the top of the stack. This is called `D(p)`, where `p` is
93//! a pattern-stack.
94//! This is used when we know there are missing constructor cases, but there might be
95//! existing wildcard patterns, so to check the usefulness of the matrix, we have to check
96//! all its *other* components.
97//!
98//! It is computed as follows. We look at the pattern `p_1` on top of the stack,
99//! and we have three cases:
100//! 1.1. `p_1 = c(r_1, .., r_a)`. We discard the current stack and return nothing.
101//! 1.2. `p_1 = _`. We return the rest of the stack:
102//! p_2, .., p_n
103//! 1.3. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting
104//! stack.
105//! D((r_1, p_2, .., p_n))
106//! D((r_2, p_2, .., p_n))
107//!
108//! Note that the OR-patterns are not always used directly in Rust, but are used to derive the
109//! exhaustive integer matching rules, so they're written here for posterity.
110//!
111//! Both those operations extend straightforwardly to a list or pattern-stacks, i.e. a matrix, by
112//! working row-by-row. Popping a constructor ends up keeping only the matrix rows that start with
113//! the given constructor, and popping a wildcard keeps those rows that start with a wildcard.
114//!
115//!
116//! The algorithm for computing `U`
117//! -------------------------------
118//! The algorithm is inductive (on the number of columns: i.e., components of tuple patterns).
119//! That means we're going to check the components from left-to-right, so the algorithm
120//! operates principally on the first component of the matrix and new pattern-stack `p`.
121//! This algorithm is realised in the `is_useful` function.
122//!
123//! Base case. (`n = 0`, i.e., an empty tuple pattern)
124//! - If `P` already contains an empty pattern (i.e., if the number of patterns `m > 0`),
125//! then `U(P, p)` is false.
126//! - Otherwise, `P` must be empty, so `U(P, p)` is true.
127//!
128//! Inductive step. (`n > 0`, i.e., whether there's at least one column
129//! [which may then be expanded into further columns later])
130//! We're going to match on the top of the new pattern-stack, `p_1`.
131//! - If `p_1 == c(r_1, .., r_a)`, i.e. we have a constructor pattern.
132//! Then, the usefulness of `p_1` can be reduced to whether it is useful when
133//! we ignore all the patterns in the first column of `P` that involve other constructors.
134//! This is where `S(c, P)` comes in:
135//! `U(P, p) := U(S(c, P), S(c, p))`
136//! This special case is handled in `is_useful_specialized`.
137//!
138//! For example, if `P` is:
139//! [
140//! [Some(true), _],
141//! [None, 0],
142//! ]
143//! and `p` is [Some(false), 0], then we don't care about row 2 since we know `p` only
144//! matches values that row 2 doesn't. For row 1 however, we need to dig into the
145//! arguments of `Some` to know whether some new value is covered. So we compute
146//! `U([[true, _]], [false, 0])`.
147//!
148//! - If `p_1 == _`, then we look at the list of constructors that appear in the first
149//! component of the rows of `P`:
150//! + If there are some constructors that aren't present, then we might think that the
151//! wildcard `_` is useful, since it covers those constructors that weren't covered
152//! before.
153//! That's almost correct, but only works if there were no wildcards in those first
154//! components. So we need to check that `p` is useful with respect to the rows that
155//! start with a wildcard, if there are any. This is where `D` comes in:
156//! `U(P, p) := U(D(P), D(p))`
157//!
158//! For example, if `P` is:
159//! [
160//! [_, true, _],
161//! [None, false, 1],
162//! ]
163//! and `p` is [_, false, _], the `Some` constructor doesn't appear in `P`. So if we
164//! only had row 2, we'd know that `p` is useful. However row 1 starts with a
165//! wildcard, so we need to check whether `U([[true, _]], [false, 1])`.
166//!
167//! + Otherwise, all possible constructors (for the relevant type) are present. In this
168//! case we must check whether the wildcard pattern covers any unmatched value. For
169//! that, we can think of the `_` pattern as a big OR-pattern that covers all
170//! possible constructors. For `Option`, that would mean `_ = None | Some(_)` for
171//! example. The wildcard pattern is useful in this case if it is useful when
172//! specialized to one of the possible constructors. So we compute:
173//! `U(P, p) := ∃(k ϵ constructors) U(S(k, P), S(k, p))`
174//!
175//! For example, if `P` is:
176//! [
177//! [Some(true), _],
178//! [None, false],
179//! ]
180//! and `p` is [_, false], both `None` and `Some` constructors appear in the first
181//! components of `P`. We will therefore try popping both constructors in turn: we
182//! compute U([[true, _]], [_, false]) for the `Some` constructor, and U([[false]],
183//! [false]) for the `None` constructor. The first case returns true, so we know that
184//! `p` is useful for `P`. Indeed, it matches `[Some(false), _]` that wasn't matched
185//! before.
186//!
187//! - If `p_1 == r_1 | r_2`, then the usefulness depends on each `r_i` separately:
188//! `U(P, p) := U(P, (r_1, p_2, .., p_n))
189//! || U(P, (r_2, p_2, .., p_n))`
190use std::sync::Arc;
191
192use smallvec::{smallvec, SmallVec};
193
194use crate::{
195 db::HirDatabase,
196 expr::{Body, Expr, Literal, Pat, PatId},
197 InferenceResult,
198};
199use hir_def::{adt::VariantData, EnumVariantId, VariantId};
200
201#[derive(Debug, Clone, Copy)]
202/// Either a pattern from the source code being analyzed, represented as
203/// as `PatId`, or a `Wild` pattern which is created as an intermediate
204/// step in the match checking algorithm and thus is not backed by a
205/// real `PatId`.
206///
207/// Note that it is totally valid for the `PatId` variant to contain
208/// a `PatId` which resolves to a `Wild` pattern, if that wild pattern
209/// exists in the source code being analyzed.
210enum PatIdOrWild {
211 PatId(PatId),
212 Wild,
213}
214
215impl PatIdOrWild {
216 fn as_pat(self, cx: &MatchCheckCtx) -> Pat {
217 match self {
218 PatIdOrWild::PatId(id) => cx.body.pats[id].clone(),
219 PatIdOrWild::Wild => Pat::Wild,
220 }
221 }
222
223 fn as_id(self) -> Option<PatId> {
224 match self {
225 PatIdOrWild::PatId(id) => Some(id),
226 PatIdOrWild::Wild => None,
227 }
228 }
229}
230
231impl From<PatId> for PatIdOrWild {
232 fn from(pat_id: PatId) -> Self {
233 Self::PatId(pat_id)
234 }
235}
236
237#[derive(Debug, Clone, Copy, PartialEq)]
238pub struct MatchCheckNotImplemented;
239
240/// The return type of `is_useful` is either an indication of usefulness
241/// of the match arm, or an error in the case the match statement
242/// is made up of types for which exhaustiveness checking is currently
243/// not completely implemented.
244///
245/// The `std::result::Result` type is used here rather than a custom enum
246/// to allow the use of `?`.
247pub type MatchCheckResult<T> = Result<T, MatchCheckNotImplemented>;
248
249#[derive(Debug)]
250/// A row in a Matrix.
251///
252/// This type is modeled from the struct of the same name in `rustc`.
253pub(crate) struct PatStack(PatStackInner);
254type PatStackInner = SmallVec<[PatIdOrWild; 2]>;
255
256impl PatStack {
257 pub(crate) fn from_pattern(pat_id: PatId) -> PatStack {
258 Self(smallvec!(pat_id.into()))
259 }
260
261 pub(crate) fn from_wild() -> PatStack {
262 Self(smallvec!(PatIdOrWild::Wild))
263 }
264
265 fn from_slice(slice: &[PatIdOrWild]) -> PatStack {
266 Self(SmallVec::from_slice(slice))
267 }
268
269 fn from_vec(v: PatStackInner) -> PatStack {
270 Self(v)
271 }
272
273 fn is_empty(&self) -> bool {
274 self.0.is_empty()
275 }
276
277 fn head(&self) -> PatIdOrWild {
278 self.0[0]
279 }
280
281 fn get_head(&self) -> Option<PatIdOrWild> {
282 self.0.first().copied()
283 }
284
285 fn to_tail(&self) -> PatStack {
286 Self::from_slice(&self.0[1..])
287 }
288
289 fn replace_head_with(&self, pat_ids: &[PatId]) -> PatStack {
290 let mut patterns: PatStackInner = smallvec![];
291 for pat in pat_ids {
292 patterns.push((*pat).into());
293 }
294 for pat in &self.0[1..] {
295 patterns.push(*pat);
296 }
297 PatStack::from_vec(patterns)
298 }
299
300 /// Computes `D(self)`.
301 ///
302 /// See the module docs and the associated documentation in rustc for details.
303 fn specialize_wildcard(&self, cx: &MatchCheckCtx) -> Option<PatStack> {
304 if matches!(self.head().as_pat(cx), Pat::Wild) {
305 Some(self.to_tail())
306 } else {
307 None
308 }
309 }
310
311 /// Computes `S(constructor, self)`.
312 ///
313 /// See the module docs and the associated documentation in rustc for details.
314 fn specialize_constructor(
315 &self,
316 cx: &MatchCheckCtx,
317 constructor: &Constructor,
318 ) -> MatchCheckResult<Option<PatStack>> {
319 let result = match (self.head().as_pat(cx), constructor) {
320 (Pat::Tuple(ref pat_ids), Constructor::Tuple { arity }) => {
321 debug_assert_eq!(
322 pat_ids.len(),
323 *arity,
324 "we type check before calling this code, so we should never hit this case",
325 );
326
327 Some(self.replace_head_with(pat_ids))
328 }
329 (Pat::Lit(lit_expr), Constructor::Bool(constructor_val)) => {
330 match cx.body.exprs[lit_expr] {
331 Expr::Literal(Literal::Bool(pat_val)) if *constructor_val == pat_val => {
332 Some(self.to_tail())
333 }
334 // it was a bool but the value doesn't match
335 Expr::Literal(Literal::Bool(_)) => None,
336 // perhaps this is actually unreachable given we have
337 // already checked that these match arms have the appropriate type?
338 _ => return Err(MatchCheckNotImplemented),
339 }
340 }
341 (Pat::Wild, constructor) => Some(self.expand_wildcard(cx, constructor)?),
342 (Pat::Path(_), Constructor::Enum(constructor)) => {
343 // enums with no associated data become `Pat::Path`
344 let pat_id = self.head().as_id().expect("we know this isn't a wild");
345 if !enum_variant_matches(cx, pat_id, *constructor) {
346 None
347 } else {
348 Some(self.to_tail())
349 }
350 }
351 (Pat::TupleStruct { args: ref pat_ids, .. }, Constructor::Enum(constructor)) => {
352 let pat_id = self.head().as_id().expect("we know this isn't a wild");
353 if !enum_variant_matches(cx, pat_id, *constructor) {
354 None
355 } else {
356 Some(self.replace_head_with(pat_ids))
357 }
358 }
359 (Pat::Or(_), _) => return Err(MatchCheckNotImplemented),
360 (_, _) => return Err(MatchCheckNotImplemented),
361 };
362
363 Ok(result)
364 }
365
366 /// A special case of `specialize_constructor` where the head of the pattern stack
367 /// is a Wild pattern.
368 ///
369 /// Replaces the Wild pattern at the head of the pattern stack with N Wild patterns
370 /// (N >= 0), where N is the arity of the given constructor.
371 fn expand_wildcard(
372 &self,
373 cx: &MatchCheckCtx,
374 constructor: &Constructor,
375 ) -> MatchCheckResult<PatStack> {
376 assert_eq!(
377 Pat::Wild,
378 self.head().as_pat(cx),
379 "expand_wildcard must only be called on PatStack with wild at head",
380 );
381
382 let mut patterns: PatStackInner = smallvec![];
383
384 for _ in 0..constructor.arity(cx)? {
385 patterns.push(PatIdOrWild::Wild);
386 }
387
388 for pat in &self.0[1..] {
389 patterns.push(*pat);
390 }
391
392 Ok(PatStack::from_vec(patterns))
393 }
394}
395
396#[derive(Debug)]
397/// A collection of PatStack.
398///
399/// This type is modeled from the struct of the same name in `rustc`.
400pub(crate) struct Matrix(Vec<PatStack>);
401
402impl Matrix {
403 pub(crate) fn empty() -> Self {
404 Self(vec![])
405 }
406
407 pub(crate) fn push(&mut self, cx: &MatchCheckCtx, row: PatStack) {
408 if let Some(Pat::Or(pat_ids)) = row.get_head().map(|pat_id| pat_id.as_pat(cx)) {
409 // Or patterns are expanded here
410 for pat_id in pat_ids {
411 self.0.push(PatStack::from_pattern(pat_id));
412 }
413 } else {
414 self.0.push(row);
415 }
416 }
417
418 fn is_empty(&self) -> bool {
419 self.0.is_empty()
420 }
421
422 fn heads(&self) -> Vec<PatIdOrWild> {
423 self.0.iter().map(|p| p.head()).collect()
424 }
425
426 /// Computes `D(self)` for each contained PatStack.
427 ///
428 /// See the module docs and the associated documentation in rustc for details.
429 fn specialize_wildcard(&self, cx: &MatchCheckCtx) -> Self {
430 Self::collect(cx, self.0.iter().filter_map(|r| r.specialize_wildcard(cx)))
431 }
432
433 /// Computes `S(constructor, self)` for each contained PatStack.
434 ///
435 /// See the module docs and the associated documentation in rustc for details.
436 fn specialize_constructor(
437 &self,
438 cx: &MatchCheckCtx,
439 constructor: &Constructor,
440 ) -> MatchCheckResult<Self> {
441 let mut new_matrix = Matrix::empty();
442 for pat in &self.0 {
443 if let Some(pat) = pat.specialize_constructor(cx, constructor)? {
444 new_matrix.push(cx, pat);
445 }
446 }
447
448 Ok(new_matrix)
449 }
450
451 fn collect<T: IntoIterator<Item = PatStack>>(cx: &MatchCheckCtx, iter: T) -> Self {
452 let mut matrix = Matrix::empty();
453
454 for pat in iter {
455 // using push ensures we expand or-patterns
456 matrix.push(cx, pat);
457 }
458
459 matrix
460 }
461}
462
463#[derive(Clone, Debug, PartialEq)]
464/// An indication of the usefulness of a given match arm, where
465/// usefulness is defined as matching some patterns which were
466/// not matched by an prior match arms.
467///
468/// We may eventually need an `Unknown` variant here.
469pub enum Usefulness {
470 Useful,
471 NotUseful,
472}
473
474pub struct MatchCheckCtx<'a> {
475 pub body: Arc<Body>,
476 pub infer: Arc<InferenceResult>,
477 pub db: &'a dyn HirDatabase,
478}
479
480/// Given a set of patterns `matrix`, and pattern to consider `v`, determines
481/// whether `v` is useful. A pattern is useful if it covers cases which were
482/// not previously covered.
483///
484/// When calling this function externally (that is, not the recursive calls) it
485/// expected that you have already type checked the match arms. All patterns in
486/// matrix should be the same type as v, as well as they should all be the same
487/// type as the match expression.
488pub(crate) fn is_useful(
489 cx: &MatchCheckCtx,
490 matrix: &Matrix,
491 v: &PatStack,
492) -> MatchCheckResult<Usefulness> {
493 if v.is_empty() {
494 let result = if matrix.is_empty() { Usefulness::Useful } else { Usefulness::NotUseful };
495
496 return Ok(result);
497 }
498
499 if let Pat::Or(pat_ids) = v.head().as_pat(cx) {
500 let mut found_unimplemented = false;
501 let any_useful = pat_ids.iter().any(|&pat_id| {
502 let v = PatStack::from_pattern(pat_id);
503
504 match is_useful(cx, matrix, &v) {
505 Ok(Usefulness::Useful) => true,
506 Ok(Usefulness::NotUseful) => false,
507 _ => {
508 found_unimplemented = true;
509 false
510 }
511 }
512 });
513
514 return if any_useful {
515 Ok(Usefulness::Useful)
516 } else if found_unimplemented {
517 Err(MatchCheckNotImplemented)
518 } else {
519 Ok(Usefulness::NotUseful)
520 };
521 }
522
523 if let Some(constructor) = pat_constructor(cx, v.head())? {
524 let matrix = matrix.specialize_constructor(&cx, &constructor)?;
525 let v = v
526 .specialize_constructor(&cx, &constructor)?
527 .expect("we know this can't fail because we get the constructor from `v.head()` above");
528
529 is_useful(&cx, &matrix, &v)
530 } else {
531 // expanding wildcard
532 let mut used_constructors: Vec<Constructor> = vec![];
533 for pat in matrix.heads() {
534 if let Some(constructor) = pat_constructor(cx, pat)? {
535 used_constructors.push(constructor);
536 }
537 }
538
539 // We assume here that the first constructor is the "correct" type. Since we
540 // only care about the "type" of the constructor (i.e. if it is a bool we
541 // don't care about the value), this assumption should be valid as long as
542 // the match statement is well formed. We currently uphold this invariant by
543 // filtering match arms before calling `is_useful`, only passing in match arms
544 // whose type matches the type of the match expression.
545 match &used_constructors.first() {
546 Some(constructor) if all_constructors_covered(&cx, constructor, &used_constructors) => {
547 // If all constructors are covered, then we need to consider whether
548 // any values are covered by this wildcard.
549 //
550 // For example, with matrix '[[Some(true)], [None]]', all
551 // constructors are covered (`Some`/`None`), so we need
552 // to perform specialization to see that our wildcard will cover
553 // the `Some(false)` case.
554 //
555 // Here we create a constructor for each variant and then check
556 // usefulness after specializing for that constructor.
557 let mut found_unimplemented = false;
558 for constructor in constructor.all_constructors(cx) {
559 let matrix = matrix.specialize_constructor(&cx, &constructor)?;
560 let v = v.expand_wildcard(&cx, &constructor)?;
561
562 match is_useful(&cx, &matrix, &v) {
563 Ok(Usefulness::Useful) => return Ok(Usefulness::Useful),
564 Ok(Usefulness::NotUseful) => continue,
565 _ => found_unimplemented = true,
566 };
567 }
568
569 if found_unimplemented {
570 Err(MatchCheckNotImplemented)
571 } else {
572 Ok(Usefulness::NotUseful)
573 }
574 }
575 _ => {
576 // Either not all constructors are covered, or the only other arms
577 // are wildcards. Either way, this pattern is useful if it is useful
578 // when compared to those arms with wildcards.
579 let matrix = matrix.specialize_wildcard(&cx);
580 let v = v.to_tail();
581
582 is_useful(&cx, &matrix, &v)
583 }
584 }
585 }
586}
587
588#[derive(Debug, Clone, Copy)]
589/// Similar to TypeCtor, but includes additional information about the specific
590/// value being instantiated. For example, TypeCtor::Bool doesn't contain the
591/// boolean value.
592enum Constructor {
593 Bool(bool),
594 Tuple { arity: usize },
595 Enum(EnumVariantId),
596}
597
598impl Constructor {
599 fn arity(&self, cx: &MatchCheckCtx) -> MatchCheckResult<usize> {
600 let arity = match self {
601 Constructor::Bool(_) => 0,
602 Constructor::Tuple { arity } => *arity,
603 Constructor::Enum(e) => {
604 match cx.db.enum_data(e.parent).variants[e.local_id].variant_data.as_ref() {
605 VariantData::Tuple(struct_field_data) => struct_field_data.len(),
606 VariantData::Unit => 0,
607 _ => return Err(MatchCheckNotImplemented),
608 }
609 }
610 };
611
612 Ok(arity)
613 }
614
615 fn all_constructors(&self, cx: &MatchCheckCtx) -> Vec<Constructor> {
616 match self {
617 Constructor::Bool(_) => vec![Constructor::Bool(true), Constructor::Bool(false)],
618 Constructor::Tuple { .. } => vec![*self],
619 Constructor::Enum(e) => cx
620 .db
621 .enum_data(e.parent)
622 .variants
623 .iter()
624 .map(|(local_id, _)| {
625 Constructor::Enum(EnumVariantId { parent: e.parent, local_id })
626 })
627 .collect(),
628 }
629 }
630}
631
632/// Returns the constructor for the given pattern. Should only return None
633/// in the case of a Wild pattern.
634fn pat_constructor(cx: &MatchCheckCtx, pat: PatIdOrWild) -> MatchCheckResult<Option<Constructor>> {
635 let res = match pat.as_pat(cx) {
636 Pat::Wild => None,
637 Pat::Tuple(pats) => Some(Constructor::Tuple { arity: pats.len() }),
638 Pat::Lit(lit_expr) => match cx.body.exprs[lit_expr] {
639 Expr::Literal(Literal::Bool(val)) => Some(Constructor::Bool(val)),
640 _ => return Err(MatchCheckNotImplemented),
641 },
642 Pat::TupleStruct { .. } | Pat::Path(_) => {
643 let pat_id = pat.as_id().expect("we already know this pattern is not a wild");
644 let variant_id =
645 cx.infer.variant_resolution_for_pat(pat_id).ok_or(MatchCheckNotImplemented)?;
646 match variant_id {
647 VariantId::EnumVariantId(enum_variant_id) => {
648 Some(Constructor::Enum(enum_variant_id))
649 }
650 _ => return Err(MatchCheckNotImplemented),
651 }
652 }
653 _ => return Err(MatchCheckNotImplemented),
654 };
655
656 Ok(res)
657}
658
659fn all_constructors_covered(
660 cx: &MatchCheckCtx,
661 constructor: &Constructor,
662 used_constructors: &[Constructor],
663) -> bool {
664 match constructor {
665 Constructor::Tuple { arity } => {
666 used_constructors.iter().any(|constructor| match constructor {
667 Constructor::Tuple { arity: used_arity } => arity == used_arity,
668 _ => false,
669 })
670 }
671 Constructor::Bool(_) => {
672 if used_constructors.is_empty() {
673 return false;
674 }
675
676 let covers_true =
677 used_constructors.iter().any(|c| matches!(c, Constructor::Bool(true)));
678 let covers_false =
679 used_constructors.iter().any(|c| matches!(c, Constructor::Bool(false)));
680
681 covers_true && covers_false
682 }
683 Constructor::Enum(e) => cx.db.enum_data(e.parent).variants.iter().all(|(id, _)| {
684 for constructor in used_constructors {
685 if let Constructor::Enum(e) = constructor {
686 if id == e.local_id {
687 return true;
688 }
689 }
690 }
691
692 false
693 }),
694 }
695}
696
697fn enum_variant_matches(cx: &MatchCheckCtx, pat_id: PatId, enum_variant_id: EnumVariantId) -> bool {
698 Some(enum_variant_id.into()) == cx.infer.variant_resolution_for_pat(pat_id)
699}
700
701#[cfg(test)]
702mod tests {
703 pub(super) use insta::assert_snapshot;
704 pub(super) use ra_db::fixture::WithFixture;
705
706 pub(super) use crate::test_db::TestDB;
707
708 pub(super) fn check_diagnostic_message(content: &str) -> String {
709 TestDB::with_single_file(content).0.diagnostics().0
710 }
711
712 pub(super) fn check_diagnostic(content: &str) {
713 let diagnostic_count = TestDB::with_single_file(content).0.diagnostics().1;
714
715 assert_eq!(1, diagnostic_count, "no diagnostic reported");
716 }
717
718 pub(super) fn check_no_diagnostic(content: &str) {
719 let diagnostic_count = TestDB::with_single_file(content).0.diagnostics().1;
720
721 assert_eq!(0, diagnostic_count, "expected no diagnostic, found one");
722 }
723
724 #[test]
725 fn empty_tuple_no_arms_diagnostic_message() {
726 let content = r"
727 fn test_fn() {
728 match () {
729 }
730 }
731 ";
732
733 assert_snapshot!(
734 check_diagnostic_message(content),
735 @"\"()\": Missing match arm\n"
736 );
737 }
738
739 #[test]
740 fn empty_tuple_no_arms() {
741 let content = r"
742 fn test_fn() {
743 match () {
744 }
745 }
746 ";
747
748 check_diagnostic(content);
749 }
750
751 #[test]
752 fn empty_tuple_wild() {
753 let content = r"
754 fn test_fn() {
755 match () {
756 _ => {}
757 }
758 }
759 ";
760
761 check_no_diagnostic(content);
762 }
763
764 #[test]
765 fn empty_tuple_no_diagnostic() {
766 let content = r"
767 fn test_fn() {
768 match () {
769 () => {}
770 }
771 }
772 ";
773
774 check_no_diagnostic(content);
775 }
776
777 #[test]
778 fn tuple_of_empty_tuple_no_arms() {
779 let content = r"
780 fn test_fn() {
781 match (()) {
782 }
783 }
784 ";
785
786 check_diagnostic(content);
787 }
788
789 #[test]
790 fn tuple_of_empty_tuple_no_diagnostic() {
791 let content = r"
792 fn test_fn() {
793 match (()) {
794 (()) => {}
795 }
796 }
797 ";
798
799 check_no_diagnostic(content);
800 }
801
802 #[test]
803 fn tuple_of_two_empty_tuple_no_arms() {
804 let content = r"
805 fn test_fn() {
806 match ((), ()) {
807 }
808 }
809 ";
810
811 check_diagnostic(content);
812 }
813
814 #[test]
815 fn tuple_of_two_empty_tuple_no_diagnostic() {
816 let content = r"
817 fn test_fn() {
818 match ((), ()) {
819 ((), ()) => {}
820 }
821 }
822 ";
823
824 check_no_diagnostic(content);
825 }
826
827 #[test]
828 fn bool_no_arms() {
829 let content = r"
830 fn test_fn() {
831 match false {
832 }
833 }
834 ";
835
836 check_diagnostic(content);
837 }
838
839 #[test]
840 fn bool_missing_arm() {
841 let content = r"
842 fn test_fn() {
843 match false {
844 true => {}
845 }
846 }
847 ";
848
849 check_diagnostic(content);
850 }
851
852 #[test]
853 fn bool_no_diagnostic() {
854 let content = r"
855 fn test_fn() {
856 match false {
857 true => {}
858 false => {}
859 }
860 }
861 ";
862
863 check_no_diagnostic(content);
864 }
865
866 #[test]
867 fn tuple_of_bools_no_arms() {
868 let content = r"
869 fn test_fn() {
870 match (false, true) {
871 }
872 }
873 ";
874
875 check_diagnostic(content);
876 }
877
878 #[test]
879 fn tuple_of_bools_missing_arms() {
880 let content = r"
881 fn test_fn() {
882 match (false, true) {
883 (true, true) => {},
884 }
885 }
886 ";
887
888 check_diagnostic(content);
889 }
890
891 #[test]
892 fn tuple_of_bools_missing_arm() {
893 let content = r"
894 fn test_fn() {
895 match (false, true) {
896 (false, true) => {},
897 (false, false) => {},
898 (true, false) => {},
899 }
900 }
901 ";
902
903 check_diagnostic(content);
904 }
905
906 #[test]
907 fn tuple_of_bools_with_wilds() {
908 let content = r"
909 fn test_fn() {
910 match (false, true) {
911 (false, _) => {},
912 (true, false) => {},
913 (_, true) => {},
914 }
915 }
916 ";
917
918 check_no_diagnostic(content);
919 }
920
921 #[test]
922 fn tuple_of_bools_no_diagnostic() {
923 let content = r"
924 fn test_fn() {
925 match (false, true) {
926 (true, true) => {},
927 (true, false) => {},
928 (false, true) => {},
929 (false, false) => {},
930 }
931 }
932 ";
933
934 check_no_diagnostic(content);
935 }
936
937 #[test]
938 fn tuple_of_bools_binding_missing_arms() {
939 let content = r"
940 fn test_fn() {
941 match (false, true) {
942 (true, _x) => {},
943 }
944 }
945 ";
946
947 check_diagnostic(content);
948 }
949
950 #[test]
951 fn tuple_of_bools_binding_no_diagnostic() {
952 let content = r"
953 fn test_fn() {
954 match (false, true) {
955 (true, _x) => {},
956 (false, true) => {},
957 (false, false) => {},
958 }
959 }
960 ";
961
962 check_no_diagnostic(content);
963 }
964
965 #[test]
966 fn tuple_of_tuple_and_bools_no_arms() {
967 let content = r"
968 fn test_fn() {
969 match (false, ((), false)) {
970 }
971 }
972 ";
973
974 check_diagnostic(content);
975 }
976
977 #[test]
978 fn tuple_of_tuple_and_bools_missing_arms() {
979 let content = r"
980 fn test_fn() {
981 match (false, ((), false)) {
982 (true, ((), true)) => {},
983 }
984 }
985 ";
986
987 check_diagnostic(content);
988 }
989
990 #[test]
991 fn tuple_of_tuple_and_bools_no_diagnostic() {
992 let content = r"
993 fn test_fn() {
994 match (false, ((), false)) {
995 (true, ((), true)) => {},
996 (true, ((), false)) => {},
997 (false, ((), true)) => {},
998 (false, ((), false)) => {},
999 }
1000 }
1001 ";
1002
1003 check_no_diagnostic(content);
1004 }
1005
1006 #[test]
1007 fn tuple_of_tuple_and_bools_wildcard_missing_arms() {
1008 let content = r"
1009 fn test_fn() {
1010 match (false, ((), false)) {
1011 (true, _) => {},
1012 }
1013 }
1014 ";
1015
1016 check_diagnostic(content);
1017 }
1018
1019 #[test]
1020 fn tuple_of_tuple_and_bools_wildcard_no_diagnostic() {
1021 let content = r"
1022 fn test_fn() {
1023 match (false, ((), false)) {
1024 (true, ((), true)) => {},
1025 (true, ((), false)) => {},
1026 (false, _) => {},
1027 }
1028 }
1029 ";
1030
1031 check_no_diagnostic(content);
1032 }
1033
1034 #[test]
1035 fn enum_no_arms() {
1036 let content = r"
1037 enum Either {
1038 A,
1039 B,
1040 }
1041 fn test_fn() {
1042 match Either::A {
1043 }
1044 }
1045 ";
1046
1047 check_diagnostic(content);
1048 }
1049
1050 #[test]
1051 fn enum_missing_arms() {
1052 let content = r"
1053 enum Either {
1054 A,
1055 B,
1056 }
1057 fn test_fn() {
1058 match Either::B {
1059 Either::A => {},
1060 }
1061 }
1062 ";
1063
1064 check_diagnostic(content);
1065 }
1066
1067 #[test]
1068 fn enum_no_diagnostic() {
1069 let content = r"
1070 enum Either {
1071 A,
1072 B,
1073 }
1074 fn test_fn() {
1075 match Either::B {
1076 Either::A => {},
1077 Either::B => {},
1078 }
1079 }
1080 ";
1081
1082 check_no_diagnostic(content);
1083 }
1084
1085 #[test]
1086 fn enum_ref_missing_arms() {
1087 let content = r"
1088 enum Either {
1089 A,
1090 B,
1091 }
1092 fn test_fn() {
1093 match &Either::B {
1094 Either::A => {},
1095 }
1096 }
1097 ";
1098
1099 check_diagnostic(content);
1100 }
1101
1102 #[test]
1103 fn enum_ref_no_diagnostic() {
1104 let content = r"
1105 enum Either {
1106 A,
1107 B,
1108 }
1109 fn test_fn() {
1110 match &Either::B {
1111 Either::A => {},
1112 Either::B => {},
1113 }
1114 }
1115 ";
1116
1117 check_no_diagnostic(content);
1118 }
1119
1120 #[test]
1121 fn enum_containing_bool_no_arms() {
1122 let content = r"
1123 enum Either {
1124 A(bool),
1125 B,
1126 }
1127 fn test_fn() {
1128 match Either::B {
1129 }
1130 }
1131 ";
1132
1133 check_diagnostic(content);
1134 }
1135
1136 #[test]
1137 fn enum_containing_bool_missing_arms() {
1138 let content = r"
1139 enum Either {
1140 A(bool),
1141 B,
1142 }
1143 fn test_fn() {
1144 match Either::B {
1145 Either::A(true) => (),
1146 Either::B => (),
1147 }
1148 }
1149 ";
1150
1151 check_diagnostic(content);
1152 }
1153
1154 #[test]
1155 fn enum_containing_bool_no_diagnostic() {
1156 let content = r"
1157 enum Either {
1158 A(bool),
1159 B,
1160 }
1161 fn test_fn() {
1162 match Either::B {
1163 Either::A(true) => (),
1164 Either::A(false) => (),
1165 Either::B => (),
1166 }
1167 }
1168 ";
1169
1170 check_no_diagnostic(content);
1171 }
1172
1173 #[test]
1174 fn enum_containing_bool_with_wild_no_diagnostic() {
1175 let content = r"
1176 enum Either {
1177 A(bool),
1178 B,
1179 }
1180 fn test_fn() {
1181 match Either::B {
1182 Either::B => (),
1183 _ => (),
1184 }
1185 }
1186 ";
1187
1188 check_no_diagnostic(content);
1189 }
1190
1191 #[test]
1192 fn enum_containing_bool_with_wild_2_no_diagnostic() {
1193 let content = r"
1194 enum Either {
1195 A(bool),
1196 B,
1197 }
1198 fn test_fn() {
1199 match Either::B {
1200 Either::A(_) => (),
1201 Either::B => (),
1202 }
1203 }
1204 ";
1205
1206 check_no_diagnostic(content);
1207 }
1208
1209 #[test]
1210 fn enum_different_sizes_missing_arms() {
1211 let content = r"
1212 enum Either {
1213 A(bool),
1214 B(bool, bool),
1215 }
1216 fn test_fn() {
1217 match Either::A(false) {
1218 Either::A(_) => (),
1219 Either::B(false, _) => (),
1220 }
1221 }
1222 ";
1223
1224 check_diagnostic(content);
1225 }
1226
1227 #[test]
1228 fn enum_different_sizes_no_diagnostic() {
1229 let content = r"
1230 enum Either {
1231 A(bool),
1232 B(bool, bool),
1233 }
1234 fn test_fn() {
1235 match Either::A(false) {
1236 Either::A(_) => (),
1237 Either::B(true, _) => (),
1238 Either::B(false, _) => (),
1239 }
1240 }
1241 ";
1242
1243 check_no_diagnostic(content);
1244 }
1245
1246 #[test]
1247 fn or_no_diagnostic() {
1248 let content = r"
1249 enum Either {
1250 A(bool),
1251 B(bool, bool),
1252 }
1253 fn test_fn() {
1254 match Either::A(false) {
1255 Either::A(true) | Either::A(false) => (),
1256 Either::B(true, _) => (),
1257 Either::B(false, _) => (),
1258 }
1259 }
1260 ";
1261
1262 check_no_diagnostic(content);
1263 }
1264
1265 #[test]
1266 fn tuple_of_enum_no_diagnostic() {
1267 let content = r"
1268 enum Either {
1269 A(bool),
1270 B(bool, bool),
1271 }
1272 enum Either2 {
1273 C,
1274 D,
1275 }
1276 fn test_fn() {
1277 match (Either::A(false), Either2::C) {
1278 (Either::A(true), _) | (Either::A(false), _) => (),
1279 (Either::B(true, _), Either2::C) => (),
1280 (Either::B(false, _), Either2::C) => (),
1281 (Either::B(_, _), Either2::D) => (),
1282 }
1283 }
1284 ";
1285
1286 check_no_diagnostic(content);
1287 }
1288
1289 #[test]
1290 fn mismatched_types() {
1291 let content = r"
1292 enum Either {
1293 A,
1294 B,
1295 }
1296 enum Either2 {
1297 C,
1298 D,
1299 }
1300 fn test_fn() {
1301 match Either::A {
1302 Either2::C => (),
1303 Either2::D => (),
1304 }
1305 }
1306 ";
1307
1308 // Match arms with the incorrect type are filtered out.
1309 check_diagnostic(content);
1310 }
1311
1312 #[test]
1313 fn mismatched_types_with_different_arity() {
1314 let content = r"
1315 fn test_fn() {
1316 match (true, false) {
1317 (true, false, true) => (),
1318 (true) => (),
1319 }
1320 }
1321 ";
1322
1323 // Match arms with the incorrect type are filtered out.
1324 check_diagnostic(content);
1325 }
1326
1327 #[test]
1328 fn enum_not_in_scope() {
1329 let content = r"
1330 fn test_fn() {
1331 match Foo::Bar {
1332 Foo::Baz => (),
1333 }
1334 }
1335 ";
1336
1337 // The enum is not in scope so we don't perform exhaustiveness
1338 // checking, but we want to be sure we don't panic here (and
1339 // we don't create a diagnostic).
1340 check_no_diagnostic(content);
1341 }
1342}
1343
1344#[cfg(test)]
1345mod false_negatives {
1346 //! The implementation of match checking here is a work in progress. As we roll this out, we
1347 //! prefer false negatives to false positives (ideally there would be no false positives). This
1348 //! test module should document known false negatives. Eventually we will have a complete
1349 //! implementation of match checking and this module will be empty.
1350 //!
1351 //! The reasons for documenting known false negatives:
1352 //!
1353 //! 1. It acts as a backlog of work that can be done to improve the behavior of the system.
1354 //! 2. It ensures the code doesn't panic when handling these cases.
1355
1356 use super::tests::*;
1357
1358 #[test]
1359 fn integers() {
1360 let content = r"
1361 fn test_fn() {
1362 match 5 {
1363 10 => (),
1364 11..20 => (),
1365 }
1366 }
1367 ";
1368
1369 // This is a false negative.
1370 // We don't currently check integer exhaustiveness.
1371 check_no_diagnostic(content);
1372 }
1373
1374 #[test]
1375 fn enum_record() {
1376 let content = r"
1377 enum Either {
1378 A { foo: u32 },
1379 B,
1380 }
1381 fn test_fn() {
1382 match Either::B {
1383 Either::A { foo: 5 } => (),
1384 }
1385 }
1386 ";
1387
1388 // This is a false negative.
1389 // We don't currently handle enum record types.
1390 check_no_diagnostic(content);
1391 }
1392
1393 #[test]
1394 fn internal_or() {
1395 let content = r"
1396 fn test_fn() {
1397 enum Either {
1398 A(bool),
1399 B,
1400 }
1401 match Either::B {
1402 Either::A(true | false) => (),
1403 }
1404 }
1405 ";
1406
1407 // This is a false negative.
1408 // We do not currently handle patterns with internal `or`s.
1409 check_no_diagnostic(content);
1410 }
1411}
diff --git a/crates/ra_hir_ty/src/autoderef.rs b/crates/ra_hir_ty/src/autoderef.rs
index 53e81e85d..d91c21e24 100644
--- a/crates/ra_hir_ty/src/autoderef.rs
+++ b/crates/ra_hir_ty/src/autoderef.rs
@@ -14,7 +14,7 @@ use crate::{
14 db::HirDatabase, 14 db::HirDatabase,
15 traits::{InEnvironment, Solution}, 15 traits::{InEnvironment, Solution},
16 utils::generics, 16 utils::generics,
17 Canonical, Substs, Ty, TypeWalk, 17 BoundVar, Canonical, DebruijnIndex, Substs, Ty,
18}; 18};
19 19
20const AUTODEREF_RECURSION_LIMIT: usize = 10; 20const AUTODEREF_RECURSION_LIMIT: usize = 10;
@@ -61,14 +61,13 @@ fn deref_by_trait(
61 return None; 61 return None;
62 } 62 }
63 63
64 // FIXME make the Canonical handling nicer 64 // FIXME make the Canonical / bound var handling nicer
65 65
66 let parameters = Substs::build_for_generics(&generic_params) 66 let parameters =
67 .push(ty.value.value.clone().shift_bound_vars(1)) 67 Substs::build_for_generics(&generic_params).push(ty.value.value.clone()).build();
68 .build();
69 68
70 let projection = super::traits::ProjectionPredicate { 69 let projection = super::traits::ProjectionPredicate {
71 ty: Ty::Bound(0), 70 ty: Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.num_vars)),
72 projection_ty: super::ProjectionTy { associated_ty: target, parameters }, 71 projection_ty: super::ProjectionTy { associated_ty: target, parameters },
73 }; 72 };
74 73
@@ -93,12 +92,16 @@ fn deref_by_trait(
93 // we have `impl<T> Deref for Foo<T> { Target = T }`, that should be 92 // we have `impl<T> Deref for Foo<T> { Target = T }`, that should be
94 // the case. 93 // the case.
95 for i in 1..vars.0.num_vars { 94 for i in 1..vars.0.num_vars {
96 if vars.0.value[i] != Ty::Bound((i - 1) as u32) { 95 if vars.0.value[i - 1] != Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, i - 1))
96 {
97 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution); 97 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution);
98 return None; 98 return None;
99 } 99 }
100 } 100 }
101 Some(Canonical { value: vars.0.value[0].clone(), num_vars: vars.0.num_vars }) 101 Some(Canonical {
102 value: vars.0.value[vars.0.value.len() - 1].clone(),
103 num_vars: vars.0.num_vars,
104 })
102 } 105 }
103 Solution::Ambig(_) => { 106 Solution::Ambig(_) => {
104 info!("Ambiguous solution for derefing {:?}: {:?}", ty.value, solution); 107 info!("Ambiguous solution for derefing {:?}: {:?}", ty.value, solution);
diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs
index 0f8522021..8cbce1168 100644
--- a/crates/ra_hir_ty/src/diagnostics.rs
+++ b/crates/ra_hir_ty/src/diagnostics.rs
@@ -6,7 +6,7 @@ use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile};
6use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr}; 6use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr};
7use stdx::format_to; 7use stdx::format_to;
8 8
9pub use hir_def::diagnostics::UnresolvedModule; 9pub use hir_def::{diagnostics::UnresolvedModule, expr::MatchArm};
10pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; 10pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink};
11 11
12#[derive(Debug)] 12#[derive(Debug)]
@@ -63,6 +63,25 @@ impl AstDiagnostic for MissingFields {
63} 63}
64 64
65#[derive(Debug)] 65#[derive(Debug)]
66pub struct MissingMatchArms {
67 pub file: HirFileId,
68 pub match_expr: AstPtr<ast::Expr>,
69 pub arms: AstPtr<ast::MatchArmList>,
70}
71
72impl Diagnostic for MissingMatchArms {
73 fn message(&self) -> String {
74 String::from("Missing match arm")
75 }
76 fn source(&self) -> InFile<SyntaxNodePtr> {
77 InFile { file_id: self.file, value: self.match_expr.into() }
78 }
79 fn as_any(&self) -> &(dyn Any + Send + 'static) {
80 self
81 }
82}
83
84#[derive(Debug)]
66pub struct MissingOkInTailExpr { 85pub struct MissingOkInTailExpr {
67 pub file: HirFileId, 86 pub file: HirFileId,
68 pub expr: AstPtr<ast::Expr>, 87 pub expr: AstPtr<ast::Expr>,
diff --git a/crates/ra_hir_ty/src/display.rs b/crates/ra_hir_ty/src/display.rs
index 13ecd537a..0e9313aa1 100644
--- a/crates/ra_hir_ty/src/display.rs
+++ b/crates/ra_hir_ty/src/display.rs
@@ -155,7 +155,11 @@ impl HirDisplay for ApplicationTy {
155 let sig = FnSig::from_fn_ptr_substs(&self.parameters); 155 let sig = FnSig::from_fn_ptr_substs(&self.parameters);
156 write!(f, "fn(")?; 156 write!(f, "fn(")?;
157 f.write_joined(sig.params(), ", ")?; 157 f.write_joined(sig.params(), ", ")?;
158 write!(f, ") -> {}", sig.ret().display(f.db))?; 158 write!(f, ")")?;
159 let ret = sig.ret();
160 if *ret != Ty::unit() {
161 write!(f, " -> {}", ret.display(f.db))?;
162 }
159 } 163 }
160 TypeCtor::FnDef(def) => { 164 TypeCtor::FnDef(def) => {
161 let sig = f.db.callable_item_signature(def).subst(&self.parameters); 165 let sig = f.db.callable_item_signature(def).subst(&self.parameters);
@@ -180,7 +184,11 @@ impl HirDisplay for ApplicationTy {
180 } 184 }
181 write!(f, "(")?; 185 write!(f, "(")?;
182 f.write_joined(sig.params(), ", ")?; 186 f.write_joined(sig.params(), ", ")?;
183 write!(f, ") -> {}", sig.ret().display(f.db))?; 187 write!(f, ")")?;
188 let ret = sig.ret();
189 if *ret != Ty::unit() {
190 write!(f, " -> {}", ret.display(f.db))?;
191 }
184 } 192 }
185 TypeCtor::Adt(def_id) => { 193 TypeCtor::Adt(def_id) => {
186 let name = match def_id { 194 let name = match def_id {
@@ -242,16 +250,16 @@ impl HirDisplay for ApplicationTy {
242 let sig = self.parameters[0] 250 let sig = self.parameters[0]
243 .callable_sig(f.db) 251 .callable_sig(f.db)
244 .expect("first closure parameter should contain signature"); 252 .expect("first closure parameter should contain signature");
245 let return_type_hint = sig.ret().display(f.db);
246 if sig.params().is_empty() { 253 if sig.params().is_empty() {
247 write!(f, "|| -> {}", return_type_hint)?; 254 write!(f, "||")?;
248 } else if f.omit_verbose_types() { 255 } else if f.omit_verbose_types() {
249 write!(f, "|{}| -> {}", TYPE_HINT_TRUNCATION, return_type_hint)?; 256 write!(f, "|{}|", TYPE_HINT_TRUNCATION)?;
250 } else { 257 } else {
251 write!(f, "|")?; 258 write!(f, "|")?;
252 f.write_joined(sig.params(), ", ")?; 259 f.write_joined(sig.params(), ", ")?;
253 write!(f, "| -> {}", return_type_hint)?; 260 write!(f, "|")?;
254 }; 261 };
262 write!(f, " -> {}", sig.ret().display(f.db))?;
255 } 263 }
256 } 264 }
257 Ok(()) 265 Ok(())
@@ -303,7 +311,7 @@ impl HirDisplay for Ty {
303 } 311 }
304 } 312 }
305 } 313 }
306 Ty::Bound(idx) => write!(f, "?{}", idx)?, 314 Ty::Bound(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?,
307 Ty::Dyn(predicates) | Ty::Opaque(predicates) => { 315 Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
308 match self { 316 match self {
309 Ty::Dyn(_) => write!(f, "dyn ")?, 317 Ty::Dyn(_) => write!(f, "dyn ")?,
diff --git a/crates/ra_hir_ty/src/expr.rs b/crates/ra_hir_ty/src/expr.rs
index b7b476b4c..b4592fbf5 100644
--- a/crates/ra_hir_ty/src/expr.rs
+++ b/crates/ra_hir_ty/src/expr.rs
@@ -2,21 +2,18 @@
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::{ 5use hir_def::{path::path, resolver::HasResolver, AdtId, FunctionId};
6 path::{path, Path}, 6use hir_expand::diagnostics::DiagnosticSink;
7 resolver::HasResolver,
8 AdtId, FunctionId,
9};
10use hir_expand::{diagnostics::DiagnosticSink, name::Name};
11use ra_syntax::ast; 7use ra_syntax::ast;
12use ra_syntax::AstPtr; 8use ra_syntax::AstPtr;
13use rustc_hash::FxHashSet; 9use rustc_hash::FxHashSet;
14 10
15use crate::{ 11use crate::{
16 db::HirDatabase, 12 db::HirDatabase,
17 diagnostics::{MissingFields, MissingOkInTailExpr}, 13 diagnostics::{MissingFields, MissingMatchArms, MissingOkInTailExpr},
18 utils::variant_data, 14 utils::variant_data,
19 ApplicationTy, InferenceResult, Ty, TypeCtor, 15 ApplicationTy, InferenceResult, Ty, TypeCtor,
16 _match::{is_useful, MatchCheckCtx, Matrix, PatStack, Usefulness},
20}; 17};
21 18
22pub use hir_def::{ 19pub use hir_def::{
@@ -28,7 +25,7 @@ pub use hir_def::{
28 ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, LogicOp, 25 ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, LogicOp,
29 MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, UnaryOp, 26 MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, UnaryOp,
30 }, 27 },
31 VariantId, 28 LocalStructFieldId, VariantId,
32}; 29};
33 30
34pub struct ExprValidator<'a, 'b: 'a> { 31pub struct ExprValidator<'a, 'b: 'a> {
@@ -49,66 +46,118 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
49 pub fn validate_body(&mut self, db: &dyn HirDatabase) { 46 pub fn validate_body(&mut self, db: &dyn HirDatabase) {
50 let body = db.body(self.func.into()); 47 let body = db.body(self.func.into());
51 48
52 for e in body.exprs.iter() { 49 for (id, expr) in body.exprs.iter() {
53 if let (id, Expr::RecordLit { path, fields, spread }) = e { 50 if let Some((variant_def, missed_fields, true)) =
54 self.validate_record_literal(id, path, fields, *spread, db); 51 record_literal_missing_fields(db, &self.infer, id, expr)
52 {
53 // XXX: only look at source_map if we do have missing fields
54 let (_, source_map) = db.body_with_source_map(self.func.into());
55
56 if let Ok(source_ptr) = source_map.expr_syntax(id) {
57 if let Some(expr) = source_ptr.value.left() {
58 let root = source_ptr.file_syntax(db.upcast());
59 if let ast::Expr::RecordLit(record_lit) = expr.to_node(&root) {
60 if let Some(field_list) = record_lit.record_field_list() {
61 let variant_data = variant_data(db.upcast(), variant_def);
62 let missed_fields = missed_fields
63 .into_iter()
64 .map(|idx| variant_data.fields()[idx].name.clone())
65 .collect();
66 self.sink.push(MissingFields {
67 file: source_ptr.file_id,
68 field_list: AstPtr::new(&field_list),
69 missed_fields,
70 })
71 }
72 }
73 }
74 }
75 }
76 if let Expr::Match { expr, arms } = expr {
77 self.validate_match(id, *expr, arms, db, self.infer.clone());
55 } 78 }
56 } 79 }
57
58 let body_expr = &body[body.body_expr]; 80 let body_expr = &body[body.body_expr];
59 if let Expr::Block { statements: _, tail: Some(t) } = body_expr { 81 if let Expr::Block { tail: Some(t), .. } = body_expr {
60 self.validate_results_in_tail_expr(body.body_expr, *t, db); 82 self.validate_results_in_tail_expr(body.body_expr, *t, db);
61 } 83 }
62 } 84 }
63 85
64 fn validate_record_literal( 86 fn validate_match(
65 &mut self, 87 &mut self,
66 id: ExprId, 88 id: ExprId,
67 _path: &Option<Path>, 89 match_expr: ExprId,
68 fields: &[RecordLitField], 90 arms: &[MatchArm],
69 spread: Option<ExprId>,
70 db: &dyn HirDatabase, 91 db: &dyn HirDatabase,
92 infer: Arc<InferenceResult>,
71 ) { 93 ) {
72 if spread.is_some() { 94 let (body, source_map): (Arc<Body>, Arc<BodySourceMap>) =
73 return; 95 db.body_with_source_map(self.func.into());
74 }; 96
75 let variant_def: VariantId = match self.infer.variant_resolution_for_expr(id) { 97 let match_expr_ty = match infer.type_of_expr.get(match_expr) {
76 Some(VariantId::UnionId(_)) | None => return, 98 Some(ty) => ty,
77 Some(it) => it, 99 // If we can't resolve the type of the match expression
100 // we cannot perform exhaustiveness checks.
101 None => return,
78 }; 102 };
79 if let VariantId::UnionId(_) = variant_def {
80 return;
81 }
82 103
83 let variant_data = variant_data(db.upcast(), variant_def); 104 let cx = MatchCheckCtx { body, infer: infer.clone(), db };
84 105 let pats = arms.iter().map(|arm| arm.pat);
85 let lit_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect(); 106
86 let missed_fields: Vec<Name> = variant_data 107 let mut seen = Matrix::empty();
87 .fields() 108 for pat in pats {
88 .iter() 109 // We skip any patterns whose type we cannot resolve.
89 .filter_map(|(_f, d)| { 110 //
90 let name = d.name.clone(); 111 // This could lead to false positives in this diagnostic, so
91 if lit_fields.contains(&name) { 112 // it might be better to skip the entire diagnostic if we either
92 None 113 // cannot resolve a match arm or determine that the match arm has
93 } else { 114 // the wrong type.
94 Some(name) 115 if let Some(pat_ty) = infer.type_of_pat.get(pat) {
116 // We only include patterns whose type matches the type
117 // of the match expression. If we had a InvalidMatchArmPattern
118 // diagnostic or similar we could raise that in an else
119 // block here.
120 //
121 // When comparing the types, we also have to consider that rustc
122 // will automatically de-reference the match expression type if
123 // necessary.
124 //
125 // FIXME we should use the type checker for this.
126 if pat_ty == match_expr_ty
127 || match_expr_ty
128 .as_reference()
129 .map(|(match_expr_ty, _)| match_expr_ty == pat_ty)
130 .unwrap_or(false)
131 {
132 // If we had a NotUsefulMatchArm diagnostic, we could
133 // check the usefulness of each pattern as we added it
134 // to the matrix here.
135 let v = PatStack::from_pattern(pat);
136 seen.push(&cx, v);
95 } 137 }
96 }) 138 }
97 .collect(); 139 }
98 if missed_fields.is_empty() { 140
99 return; 141 match is_useful(&cx, &seen, &PatStack::from_wild()) {
142 Ok(Usefulness::Useful) => (),
143 // if a wildcard pattern is not useful, then all patterns are covered
144 Ok(Usefulness::NotUseful) => return,
145 // this path is for unimplemented checks, so we err on the side of not
146 // reporting any errors
147 _ => return,
100 } 148 }
101 let (_, source_map) = db.body_with_source_map(self.func.into());
102 149
103 if let Ok(source_ptr) = source_map.expr_syntax(id) { 150 if let Ok(source_ptr) = source_map.expr_syntax(id) {
104 if let Some(expr) = source_ptr.value.left() { 151 if let Some(expr) = source_ptr.value.left() {
105 let root = source_ptr.file_syntax(db.upcast()); 152 let root = source_ptr.file_syntax(db.upcast());
106 if let ast::Expr::RecordLit(record_lit) = expr.to_node(&root) { 153 if let ast::Expr::MatchExpr(match_expr) = expr.to_node(&root) {
107 if let Some(field_list) = record_lit.record_field_list() { 154 if let (Some(match_expr), Some(arms)) =
108 self.sink.push(MissingFields { 155 (match_expr.expr(), match_expr.match_arm_list())
156 {
157 self.sink.push(MissingMatchArms {
109 file: source_ptr.file_id, 158 file: source_ptr.file_id,
110 field_list: AstPtr::new(&field_list), 159 match_expr: AstPtr::new(&match_expr),
111 missed_fields, 160 arms: AstPtr::new(&arms),
112 }) 161 })
113 } 162 }
114 } 163 }
@@ -148,3 +197,63 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
148 } 197 }
149 } 198 }
150} 199}
200
201pub fn record_literal_missing_fields(
202 db: &dyn HirDatabase,
203 infer: &InferenceResult,
204 id: ExprId,
205 expr: &Expr,
206) -> Option<(VariantId, Vec<LocalStructFieldId>, /*exhaustive*/ bool)> {
207 let (fields, exhausitve) = match expr {
208 Expr::RecordLit { path: _, fields, spread } => (fields, spread.is_none()),
209 _ => return None,
210 };
211
212 let variant_def = infer.variant_resolution_for_expr(id)?;
213 if let VariantId::UnionId(_) = variant_def {
214 return None;
215 }
216
217 let variant_data = variant_data(db.upcast(), variant_def);
218
219 let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
220 let missed_fields: Vec<LocalStructFieldId> = variant_data
221 .fields()
222 .iter()
223 .filter_map(|(f, d)| if specified_fields.contains(&d.name) { None } else { Some(f) })
224 .collect();
225 if missed_fields.is_empty() {
226 return None;
227 }
228 Some((variant_def, missed_fields, exhausitve))
229}
230
231pub fn record_pattern_missing_fields(
232 db: &dyn HirDatabase,
233 infer: &InferenceResult,
234 id: PatId,
235 pat: &Pat,
236) -> Option<(VariantId, Vec<LocalStructFieldId>)> {
237 let fields = match pat {
238 Pat::Record { path: _, args } => args,
239 _ => return None,
240 };
241
242 let variant_def = infer.variant_resolution_for_pat(id)?;
243 if let VariantId::UnionId(_) = variant_def {
244 return None;
245 }
246
247 let variant_data = variant_data(db.upcast(), variant_def);
248
249 let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
250 let missed_fields: Vec<LocalStructFieldId> = variant_data
251 .fields()
252 .iter()
253 .filter_map(|(f, d)| if specified_fields.contains(&d.name) { None } else { Some(f) })
254 .collect();
255 if missed_fields.is_empty() {
256 return None;
257 }
258 Some((variant_def, missed_fields))
259}
diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs
index baed6225b..69bbb4307 100644
--- a/crates/ra_hir_ty/src/infer/pat.rs
+++ b/crates/ra_hir_ty/src/infer/pat.rs
@@ -11,7 +11,7 @@ use hir_def::{
11use hir_expand::name::Name; 11use hir_expand::name::Name;
12use test_utils::tested_by; 12use test_utils::tested_by;
13 13
14use super::{BindingMode, InferenceContext}; 14use super::{BindingMode, Expectation, InferenceContext};
15use crate::{utils::variant_data, Substs, Ty, TypeCtor}; 15use crate::{utils::variant_data, Substs, Ty, TypeCtor};
16 16
17impl<'a> InferenceContext<'a> { 17impl<'a> InferenceContext<'a> {
@@ -21,9 +21,13 @@ impl<'a> InferenceContext<'a> {
21 subpats: &[PatId], 21 subpats: &[PatId],
22 expected: &Ty, 22 expected: &Ty,
23 default_bm: BindingMode, 23 default_bm: BindingMode,
24 id: PatId,
24 ) -> Ty { 25 ) -> Ty {
25 let (ty, def) = self.resolve_variant(path); 26 let (ty, def) = self.resolve_variant(path);
26 let var_data = def.map(|it| variant_data(self.db.upcast(), it)); 27 let var_data = def.map(|it| variant_data(self.db.upcast(), it));
28 if let Some(variant) = def {
29 self.write_variant_resolution(id.into(), variant);
30 }
27 self.unify(&ty, expected); 31 self.unify(&ty, expected);
28 32
29 let substs = ty.substs().unwrap_or_else(Substs::empty); 33 let substs = ty.substs().unwrap_or_else(Substs::empty);
@@ -152,7 +156,7 @@ impl<'a> InferenceContext<'a> {
152 Ty::apply_one(TypeCtor::Ref(*mutability), subty) 156 Ty::apply_one(TypeCtor::Ref(*mutability), subty)
153 } 157 }
154 Pat::TupleStruct { path: p, args: subpats } => { 158 Pat::TupleStruct { path: p, args: subpats } => {
155 self.infer_tuple_struct_pat(p.as_ref(), subpats, expected, default_bm) 159 self.infer_tuple_struct_pat(p.as_ref(), subpats, expected, default_bm, pat)
156 } 160 }
157 Pat::Record { path: p, args: fields } => { 161 Pat::Record { path: p, args: fields } => {
158 self.infer_record_pat(p.as_ref(), fields, expected, default_bm, pat) 162 self.infer_record_pat(p.as_ref(), fields, expected, default_bm, pat)
@@ -198,7 +202,14 @@ impl<'a> InferenceContext<'a> {
198 202
199 Ty::apply_one(container_ty, elem_ty) 203 Ty::apply_one(container_ty, elem_ty)
200 } 204 }
201 _ => Ty::Unknown, 205 Pat::Wild => expected.clone(),
206 Pat::Range { start, end } => {
207 let start_ty = self.infer_expr(*start, &Expectation::has_type(expected.clone()));
208 let end_ty = self.infer_expr(*end, &Expectation::has_type(start_ty));
209 end_ty
210 }
211 Pat::Lit(expr) => self.infer_expr(*expr, &Expectation::has_type(expected.clone())),
212 Pat::Missing => Ty::Unknown,
202 }; 213 };
203 // use a new type variable if we got Ty::Unknown here 214 // use a new type variable if we got Ty::Unknown here
204 let ty = self.insert_type_vars_shallow(ty); 215 let ty = self.insert_type_vars_shallow(ty);
diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs
index 318652c61..2b6bc0f79 100644
--- a/crates/ra_hir_ty/src/infer/path.rs
+++ b/crates/ra_hir_ty/src/infer/path.rs
@@ -67,8 +67,16 @@ impl<'a> InferenceContext<'a> {
67 ValueNs::FunctionId(it) => it.into(), 67 ValueNs::FunctionId(it) => it.into(),
68 ValueNs::ConstId(it) => it.into(), 68 ValueNs::ConstId(it) => it.into(),
69 ValueNs::StaticId(it) => it.into(), 69 ValueNs::StaticId(it) => it.into(),
70 ValueNs::StructId(it) => it.into(), 70 ValueNs::StructId(it) => {
71 ValueNs::EnumVariantId(it) => it.into(), 71 self.write_variant_resolution(id, it.into());
72
73 it.into()
74 }
75 ValueNs::EnumVariantId(it) => {
76 self.write_variant_resolution(id, it.into());
77
78 it.into()
79 }
72 }; 80 };
73 81
74 let ty = self.db.value_ty(typable); 82 let ty = self.db.value_ty(typable);
diff --git a/crates/ra_hir_ty/src/infer/unify.rs b/crates/ra_hir_ty/src/infer/unify.rs
index 0bf8fbd63..ac25f8a80 100644
--- a/crates/ra_hir_ty/src/infer/unify.rs
+++ b/crates/ra_hir_ty/src/infer/unify.rs
@@ -7,7 +7,9 @@ use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
7use test_utils::tested_by; 7use test_utils::tested_by;
8 8
9use super::{InferenceContext, Obligation}; 9use super::{InferenceContext, Obligation};
10use crate::{Canonical, InEnvironment, InferTy, Substs, Ty, TypeCtor, TypeWalk}; 10use crate::{
11 BoundVar, Canonical, DebruijnIndex, InEnvironment, InferTy, Substs, Ty, TypeCtor, TypeWalk,
12};
11 13
12impl<'a> InferenceContext<'a> { 14impl<'a> InferenceContext<'a> {
13 pub(super) fn canonicalizer<'b>(&'b mut self) -> Canonicalizer<'a, 'b> 15 pub(super) fn canonicalizer<'b>(&'b mut self) -> Canonicalizer<'a, 'b>
@@ -47,7 +49,7 @@ where
47 }) 49 })
48 } 50 }
49 51
50 fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: usize) -> T { 52 fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: DebruijnIndex) -> T {
51 t.fold_binders( 53 t.fold_binders(
52 &mut |ty, binders| match ty { 54 &mut |ty, binders| match ty {
53 Ty::Infer(tv) => { 55 Ty::Infer(tv) => {
@@ -72,7 +74,7 @@ where
72 InferTy::MaybeNeverTypeVar(_) => InferTy::MaybeNeverTypeVar(root), 74 InferTy::MaybeNeverTypeVar(_) => InferTy::MaybeNeverTypeVar(root),
73 }; 75 };
74 let position = self.add(free_var); 76 let position = self.add(free_var);
75 Ty::Bound((position + binders) as u32) 77 Ty::Bound(BoundVar::new(binders, position))
76 } 78 }
77 } 79 }
78 _ => ty, 80 _ => ty,
@@ -89,7 +91,7 @@ where
89 } 91 }
90 92
91 pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> { 93 pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> {
92 let result = self.do_canonicalize(ty, 0); 94 let result = self.do_canonicalize(ty, DebruijnIndex::INNERMOST);
93 self.into_canonicalized(result) 95 self.into_canonicalized(result)
94 } 96 }
95 97
@@ -98,8 +100,12 @@ where
98 obligation: InEnvironment<Obligation>, 100 obligation: InEnvironment<Obligation>,
99 ) -> Canonicalized<InEnvironment<Obligation>> { 101 ) -> Canonicalized<InEnvironment<Obligation>> {
100 let result = match obligation.value { 102 let result = match obligation.value {
101 Obligation::Trait(tr) => Obligation::Trait(self.do_canonicalize(tr, 0)), 103 Obligation::Trait(tr) => {
102 Obligation::Projection(pr) => Obligation::Projection(self.do_canonicalize(pr, 0)), 104 Obligation::Trait(self.do_canonicalize(tr, DebruijnIndex::INNERMOST))
105 }
106 Obligation::Projection(pr) => {
107 Obligation::Projection(self.do_canonicalize(pr, DebruijnIndex::INNERMOST))
108 }
103 }; 109 };
104 self.into_canonicalized(InEnvironment { 110 self.into_canonicalized(InEnvironment {
105 value: result, 111 value: result,
@@ -112,13 +118,13 @@ impl<T> Canonicalized<T> {
112 pub fn decanonicalize_ty(&self, mut ty: Ty) -> Ty { 118 pub fn decanonicalize_ty(&self, mut ty: Ty) -> Ty {
113 ty.walk_mut_binders( 119 ty.walk_mut_binders(
114 &mut |ty, binders| { 120 &mut |ty, binders| {
115 if let &mut Ty::Bound(idx) = ty { 121 if let &mut Ty::Bound(bound) = ty {
116 if idx as usize >= binders && (idx as usize - binders) < self.free_vars.len() { 122 if bound.debruijn >= binders {
117 *ty = Ty::Infer(self.free_vars[idx as usize - binders]); 123 *ty = Ty::Infer(self.free_vars[bound.index]);
118 } 124 }
119 } 125 }
120 }, 126 },
121 0, 127 DebruijnIndex::INNERMOST,
122 ); 128 );
123 ty 129 ty
124 } 130 }
@@ -150,7 +156,7 @@ pub fn unify(ty1: &Canonical<Ty>, ty2: &Canonical<Ty>) -> Option<Substs> {
150 // (kind of hacky) 156 // (kind of hacky)
151 for (i, var) in vars.iter().enumerate() { 157 for (i, var) in vars.iter().enumerate() {
152 if &*table.resolve_ty_shallow(var) == var { 158 if &*table.resolve_ty_shallow(var) == var {
153 table.unify(var, &Ty::Bound(i as u32)); 159 table.unify(var, &Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, i)));
154 } 160 }
155 } 161 }
156 Some( 162 Some(
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index 6c5469ecd..18f74d3b1 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -1,6 +1,11 @@
1//! The type system. We currently use this to infer types for completion, hover 1//! The type system. We currently use this to infer types for completion, hover
2//! information and various assists. 2//! information and various assists.
3 3
4#[allow(unused)]
5macro_rules! eprintln {
6 ($($tt:tt)*) => { stdx::eprintln!($($tt)*) };
7}
8
4macro_rules! impl_froms { 9macro_rules! impl_froms {
5 ($e:ident: $($v:ident $(($($sv:ident),*))?),*) => { 10 ($e:ident: $($v:ident $(($($sv:ident),*))?),*) => {
6 $( 11 $(
@@ -38,6 +43,7 @@ mod tests;
38#[cfg(test)] 43#[cfg(test)]
39mod test_db; 44mod test_db;
40mod marks; 45mod marks;
46mod _match;
41 47
42use std::ops::Deref; 48use std::ops::Deref;
43use std::sync::Arc; 49use std::sync::Arc;
@@ -64,6 +70,8 @@ pub use lower::{
64}; 70};
65pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; 71pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment};
66 72
73pub use chalk_ir::{BoundVar, DebruijnIndex};
74
67/// A type constructor or type name: this might be something like the primitive 75/// A type constructor or type name: this might be something like the primitive
68/// type `bool`, a struct like `Vec`, or things like function pointers or 76/// type `bool`, a struct like `Vec`, or things like function pointers or
69/// tuples. 77/// tuples.
@@ -265,7 +273,11 @@ impl TypeWalk for ProjectionTy {
265 self.parameters.walk(f); 273 self.parameters.walk(f);
266 } 274 }
267 275
268 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { 276 fn walk_mut_binders(
277 &mut self,
278 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
279 binders: DebruijnIndex,
280 ) {
269 self.parameters.walk_mut_binders(f, binders); 281 self.parameters.walk_mut_binders(f, binders);
270 } 282 }
271} 283}
@@ -299,7 +311,7 @@ pub enum Ty {
299 /// parameters get turned into variables; during trait resolution, inference 311 /// parameters get turned into variables; during trait resolution, inference
300 /// variables get turned into bound variables and back; and in `Dyn` the 312 /// variables get turned into bound variables and back; and in `Dyn` the
301 /// `Self` type is represented with a bound variable as well. 313 /// `Self` type is represented with a bound variable as well.
302 Bound(u32), 314 Bound(BoundVar),
303 315
304 /// A type variable used during type checking. 316 /// A type variable used during type checking.
305 Infer(InferTy), 317 Infer(InferTy),
@@ -337,7 +349,11 @@ impl TypeWalk for Substs {
337 } 349 }
338 } 350 }
339 351
340 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { 352 fn walk_mut_binders(
353 &mut self,
354 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
355 binders: DebruijnIndex,
356 ) {
341 for t in make_mut_slice(&mut self.0) { 357 for t in make_mut_slice(&mut self.0) {
342 t.walk_mut_binders(f, binders); 358 t.walk_mut_binders(f, binders);
343 } 359 }
@@ -381,7 +397,13 @@ impl Substs {
381 397
382 /// Return Substs that replace each parameter by a bound variable. 398 /// Return Substs that replace each parameter by a bound variable.
383 pub(crate) fn bound_vars(generic_params: &Generics) -> Substs { 399 pub(crate) fn bound_vars(generic_params: &Generics) -> Substs {
384 Substs(generic_params.iter().enumerate().map(|(idx, _)| Ty::Bound(idx as u32)).collect()) 400 Substs(
401 generic_params
402 .iter()
403 .enumerate()
404 .map(|(idx, _)| Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, idx)))
405 .collect(),
406 )
385 } 407 }
386 408
387 pub fn build_for_def(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> SubstsBuilder { 409 pub fn build_for_def(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> SubstsBuilder {
@@ -425,8 +447,8 @@ impl SubstsBuilder {
425 self.param_count - self.vec.len() 447 self.param_count - self.vec.len()
426 } 448 }
427 449
428 pub fn fill_with_bound_vars(self, starting_from: u32) -> Self { 450 pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self {
429 self.fill((starting_from..).map(Ty::Bound)) 451 self.fill((starting_from..).map(|idx| Ty::Bound(BoundVar::new(debruijn, idx))))
430 } 452 }
431 453
432 pub fn fill_with_unknown(self) -> Self { 454 pub fn fill_with_unknown(self) -> Self {
@@ -507,7 +529,11 @@ impl TypeWalk for TraitRef {
507 self.substs.walk(f); 529 self.substs.walk(f);
508 } 530 }
509 531
510 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { 532 fn walk_mut_binders(
533 &mut self,
534 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
535 binders: DebruijnIndex,
536 ) {
511 self.substs.walk_mut_binders(f, binders); 537 self.substs.walk_mut_binders(f, binders);
512 } 538 }
513} 539}
@@ -558,7 +584,11 @@ impl TypeWalk for GenericPredicate {
558 } 584 }
559 } 585 }
560 586
561 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { 587 fn walk_mut_binders(
588 &mut self,
589 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
590 binders: DebruijnIndex,
591 ) {
562 match self { 592 match self {
563 GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders), 593 GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders),
564 GenericPredicate::Projection(projection_pred) => { 594 GenericPredicate::Projection(projection_pred) => {
@@ -616,7 +646,11 @@ impl TypeWalk for FnSig {
616 } 646 }
617 } 647 }
618 648
619 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { 649 fn walk_mut_binders(
650 &mut self,
651 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
652 binders: DebruijnIndex,
653 ) {
620 for t in make_mut_slice(&mut self.params_and_return) { 654 for t in make_mut_slice(&mut self.params_and_return) {
621 t.walk_mut_binders(f, binders); 655 t.walk_mut_binders(f, binders);
622 } 656 }
@@ -755,7 +789,7 @@ impl Ty {
755pub trait TypeWalk { 789pub trait TypeWalk {
756 fn walk(&self, f: &mut impl FnMut(&Ty)); 790 fn walk(&self, f: &mut impl FnMut(&Ty));
757 fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { 791 fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
758 self.walk_mut_binders(&mut |ty, _binders| f(ty), 0); 792 self.walk_mut_binders(&mut |ty, _binders| f(ty), DebruijnIndex::INNERMOST);
759 } 793 }
760 /// Walk the type, counting entered binders. 794 /// Walk the type, counting entered binders.
761 /// 795 ///
@@ -767,9 +801,17 @@ pub trait TypeWalk {
767 /// that. Currently, the only thing that introduces bound variables on our 801 /// that. Currently, the only thing that introduces bound variables on our
768 /// side are `Ty::Dyn` and `Ty::Opaque`, which each introduce a bound 802 /// side are `Ty::Dyn` and `Ty::Opaque`, which each introduce a bound
769 /// variable for the self type. 803 /// variable for the self type.
770 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize); 804 fn walk_mut_binders(
771 805 &mut self,
772 fn fold_binders(mut self, f: &mut impl FnMut(Ty, usize) -> Ty, binders: usize) -> Self 806 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
807 binders: DebruijnIndex,
808 );
809
810 fn fold_binders(
811 mut self,
812 f: &mut impl FnMut(Ty, DebruijnIndex) -> Ty,
813 binders: DebruijnIndex,
814 ) -> Self
773 where 815 where
774 Self: Sized, 816 Self: Sized,
775 { 817 {
@@ -795,40 +837,44 @@ pub trait TypeWalk {
795 } 837 }
796 838
797 /// Substitutes `Ty::Bound` vars with the given substitution. 839 /// Substitutes `Ty::Bound` vars with the given substitution.
798 fn subst_bound_vars(mut self, substs: &Substs) -> Self 840 fn subst_bound_vars(self, substs: &Substs) -> Self
841 where
842 Self: Sized,
843 {
844 self.subst_bound_vars_at_depth(substs, DebruijnIndex::INNERMOST)
845 }
846
847 /// Substitutes `Ty::Bound` vars with the given substitution.
848 fn subst_bound_vars_at_depth(mut self, substs: &Substs, depth: DebruijnIndex) -> Self
799 where 849 where
800 Self: Sized, 850 Self: Sized,
801 { 851 {
802 self.walk_mut_binders( 852 self.walk_mut_binders(
803 &mut |ty, binders| { 853 &mut |ty, binders| {
804 if let &mut Ty::Bound(idx) = ty { 854 if let &mut Ty::Bound(bound) = ty {
805 if idx as usize >= binders && (idx as usize - binders) < substs.len() { 855 if bound.debruijn >= binders {
806 *ty = substs.0[idx as usize - binders].clone(); 856 *ty = substs.0[bound.index].clone();
807 } else if idx as usize >= binders + substs.len() {
808 // shift free binders
809 *ty = Ty::Bound(idx - substs.len() as u32);
810 } 857 }
811 } 858 }
812 }, 859 },
813 0, 860 depth,
814 ); 861 );
815 self 862 self
816 } 863 }
817 864
818 /// Shifts up `Ty::Bound` vars by `n`. 865 /// Shifts up debruijn indices of `Ty::Bound` vars by `n`.
819 fn shift_bound_vars(self, n: i32) -> Self 866 fn shift_bound_vars(self, n: DebruijnIndex) -> Self
820 where 867 where
821 Self: Sized, 868 Self: Sized,
822 { 869 {
823 self.fold_binders( 870 self.fold_binders(
824 &mut |ty, binders| match ty { 871 &mut |ty, binders| match ty {
825 Ty::Bound(idx) if idx as usize >= binders => { 872 Ty::Bound(bound) if bound.debruijn >= binders => {
826 assert!(idx as i32 >= -n); 873 Ty::Bound(bound.shifted_in_from(n))
827 Ty::Bound((idx as i32 + n) as u32)
828 } 874 }
829 ty => ty, 875 ty => ty,
830 }, 876 },
831 0, 877 DebruijnIndex::INNERMOST,
832 ) 878 )
833 } 879 }
834} 880}
@@ -856,7 +902,11 @@ impl TypeWalk for Ty {
856 f(self); 902 f(self);
857 } 903 }
858 904
859 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { 905 fn walk_mut_binders(
906 &mut self,
907 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
908 binders: DebruijnIndex,
909 ) {
860 match self { 910 match self {
861 Ty::Apply(a_ty) => { 911 Ty::Apply(a_ty) => {
862 a_ty.parameters.walk_mut_binders(f, binders); 912 a_ty.parameters.walk_mut_binders(f, binders);
@@ -866,7 +916,7 @@ impl TypeWalk for Ty {
866 } 916 }
867 Ty::Dyn(predicates) | Ty::Opaque(predicates) => { 917 Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
868 for p in make_mut_slice(predicates) { 918 for p in make_mut_slice(predicates) {
869 p.walk_mut_binders(f, binders + 1); 919 p.walk_mut_binders(f, binders.shifted_in());
870 } 920 }
871 } 921 }
872 Ty::Placeholder { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} 922 Ty::Placeholder { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index d7f250783..6c7bbc448 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -29,8 +29,8 @@ use crate::{
29 all_super_traits, associated_type_by_name_including_super_traits, generics, make_mut_slice, 29 all_super_traits, associated_type_by_name_including_super_traits, generics, make_mut_slice,
30 variant_data, 30 variant_data,
31 }, 31 },
32 Binders, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, ProjectionTy, Substs, 32 Binders, BoundVar, DebruijnIndex, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate,
33 TraitEnvironment, TraitRef, Ty, TypeCtor, 33 ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor,
34}; 34};
35 35
36#[derive(Debug)] 36#[derive(Debug)]
@@ -131,7 +131,7 @@ impl Ty {
131 Ty::apply(TypeCtor::FnPtr { num_args: sig.len() as u16 - 1 }, sig) 131 Ty::apply(TypeCtor::FnPtr { num_args: sig.len() as u16 - 1 }, sig)
132 } 132 }
133 TypeRef::DynTrait(bounds) => { 133 TypeRef::DynTrait(bounds) => {
134 let self_ty = Ty::Bound(0); 134 let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0));
135 let predicates = bounds 135 let predicates = bounds
136 .iter() 136 .iter()
137 .flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone())) 137 .flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone()))
@@ -141,7 +141,7 @@ impl Ty {
141 TypeRef::ImplTrait(bounds) => { 141 TypeRef::ImplTrait(bounds) => {
142 match ctx.impl_trait_mode { 142 match ctx.impl_trait_mode {
143 ImplTraitLoweringMode::Opaque => { 143 ImplTraitLoweringMode::Opaque => {
144 let self_ty = Ty::Bound(0); 144 let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0));
145 let predicates = bounds 145 let predicates = bounds
146 .iter() 146 .iter()
147 .flat_map(|b| { 147 .flat_map(|b| {
@@ -177,12 +177,10 @@ impl Ty {
177 } else { 177 } else {
178 (0, 0, 0, 0) 178 (0, 0, 0, 0)
179 }; 179 };
180 Ty::Bound( 180 Ty::Bound(BoundVar::new(
181 idx as u32 181 DebruijnIndex::INNERMOST,
182 + parent_params as u32 182 idx as usize + parent_params + self_params + list_params,
183 + self_params as u32 183 ))
184 + list_params as u32,
185 )
186 } 184 }
187 ImplTraitLoweringMode::Disallowed => { 185 ImplTraitLoweringMode::Disallowed => {
188 // FIXME: report error 186 // FIXME: report error
@@ -249,7 +247,11 @@ impl Ty {
249 let ty = match resolution { 247 let ty = match resolution {
250 TypeNs::TraitId(trait_) => { 248 TypeNs::TraitId(trait_) => {
251 // if this is a bare dyn Trait, we'll directly put the required ^0 for the self type in there 249 // if this is a bare dyn Trait, we'll directly put the required ^0 for the self type in there
252 let self_ty = if remaining_segments.len() == 0 { Some(Ty::Bound(0)) } else { None }; 250 let self_ty = if remaining_segments.len() == 0 {
251 Some(Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)))
252 } else {
253 None
254 };
253 let trait_ref = 255 let trait_ref =
254 TraitRef::from_resolved_path(ctx, trait_, resolved_segment, self_ty); 256 TraitRef::from_resolved_path(ctx, trait_, resolved_segment, self_ty);
255 let ty = if remaining_segments.len() == 1 { 257 let ty = if remaining_segments.len() == 1 {
@@ -289,7 +291,7 @@ impl Ty {
289 TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id), 291 TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id),
290 TypeParamLoweringMode::Variable => { 292 TypeParamLoweringMode::Variable => {
291 let idx = generics.param_idx(param_id).expect("matching generics"); 293 let idx = generics.param_idx(param_id).expect("matching generics");
292 Ty::Bound(idx) 294 Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, idx))
293 } 295 }
294 } 296 }
295 } 297 }
@@ -558,7 +560,7 @@ impl GenericPredicate {
558 TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id), 560 TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id),
559 TypeParamLoweringMode::Variable => { 561 TypeParamLoweringMode::Variable => {
560 let idx = generics.param_idx(param_id).expect("matching generics"); 562 let idx = generics.param_idx(param_id).expect("matching generics");
561 Ty::Bound(idx) 563 Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, idx))
562 } 564 }
563 } 565 }
564 } 566 }
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index 533c6ccfb..74a0bc7db 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -20,7 +20,8 @@ use crate::{
20 db::HirDatabase, 20 db::HirDatabase,
21 primitive::{FloatBitness, Uncertain}, 21 primitive::{FloatBitness, Uncertain},
22 utils::all_super_traits, 22 utils::all_super_traits,
23 ApplicationTy, Canonical, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, 23 ApplicationTy, Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty,
24 TypeCtor, TypeWalk,
24}; 25};
25 26
26/// This is used as a key for indexing impls. 27/// This is used as a key for indexing impls.
@@ -507,8 +508,9 @@ pub(crate) fn inherent_impl_substs(
507) -> Option<Substs> { 508) -> Option<Substs> {
508 // we create a var for each type parameter of the impl; we need to keep in 509 // we create a var for each type parameter of the impl; we need to keep in
509 // mind here that `self_ty` might have vars of its own 510 // mind here that `self_ty` might have vars of its own
510 let vars = 511 let vars = Substs::build_for_def(db, impl_id)
511 Substs::build_for_def(db, impl_id).fill_with_bound_vars(self_ty.num_vars as u32).build(); 512 .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.num_vars)
513 .build();
512 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); 514 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars);
513 let self_ty_with_vars = 515 let self_ty_with_vars =
514 Canonical { num_vars: vars.len() + self_ty.num_vars, value: self_ty_with_vars }; 516 Canonical { num_vars: vars.len() + self_ty.num_vars, value: self_ty_with_vars };
@@ -526,8 +528,8 @@ pub(crate) fn inherent_impl_substs(
526fn fallback_bound_vars(s: Substs, num_vars_to_keep: usize) -> Substs { 528fn fallback_bound_vars(s: Substs, num_vars_to_keep: usize) -> Substs {
527 s.fold_binders( 529 s.fold_binders(
528 &mut |ty, binders| { 530 &mut |ty, binders| {
529 if let Ty::Bound(idx) = &ty { 531 if let Ty::Bound(bound) = &ty {
530 if *idx >= binders as u32 { 532 if bound.index >= num_vars_to_keep && bound.debruijn >= binders {
531 Ty::Unknown 533 Ty::Unknown
532 } else { 534 } else {
533 ty 535 ty
@@ -536,7 +538,7 @@ fn fallback_bound_vars(s: Substs, num_vars_to_keep: usize) -> Substs {
536 ty 538 ty
537 } 539 }
538 }, 540 },
539 num_vars_to_keep, 541 DebruijnIndex::INNERMOST,
540 ) 542 )
541} 543}
542 544
@@ -586,7 +588,7 @@ fn generic_implements_goal(
586 let num_vars = self_ty.num_vars; 588 let num_vars = self_ty.num_vars;
587 let substs = super::Substs::build_for_def(db, trait_) 589 let substs = super::Substs::build_for_def(db, trait_)
588 .push(self_ty.value) 590 .push(self_ty.value)
589 .fill_with_bound_vars(num_vars as u32) 591 .fill_with_bound_vars(DebruijnIndex::INNERMOST, num_vars)
590 .build(); 592 .build();
591 let num_vars = substs.len() - 1 + self_ty.num_vars; 593 let num_vars = substs.len() - 1 + self_ty.num_vars;
592 let trait_ref = TraitRef { trait_, substs }; 594 let trait_ref = TraitRef { trait_, substs };
diff --git a/crates/ra_hir_ty/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs
index 208096aab..3a4d58bf9 100644
--- a/crates/ra_hir_ty/src/test_db.rs
+++ b/crates/ra_hir_ty/src/test_db.rs
@@ -105,8 +105,9 @@ impl TestDB {
105 } 105 }
106 106
107 // FIXME: don't duplicate this 107 // FIXME: don't duplicate this
108 pub fn diagnostics(&self) -> String { 108 pub fn diagnostics(&self) -> (String, u32) {
109 let mut buf = String::new(); 109 let mut buf = String::new();
110 let mut count = 0;
110 let crate_graph = self.crate_graph(); 111 let crate_graph = self.crate_graph();
111 for krate in crate_graph.iter() { 112 for krate in crate_graph.iter() {
112 let crate_def_map = self.crate_def_map(krate); 113 let crate_def_map = self.crate_def_map(krate);
@@ -133,13 +134,14 @@ impl TestDB {
133 let infer = self.infer(f.into()); 134 let infer = self.infer(f.into());
134 let mut sink = DiagnosticSink::new(|d| { 135 let mut sink = DiagnosticSink::new(|d| {
135 format_to!(buf, "{:?}: {}\n", d.syntax_node(self).text(), d.message()); 136 format_to!(buf, "{:?}: {}\n", d.syntax_node(self).text(), d.message());
137 count += 1;
136 }); 138 });
137 infer.add_diagnostics(self, f, &mut sink); 139 infer.add_diagnostics(self, f, &mut sink);
138 let mut validator = ExprValidator::new(f, infer, &mut sink); 140 let mut validator = ExprValidator::new(f, infer, &mut sink);
139 validator.validate_body(self); 141 validator.validate_body(self);
140 } 142 }
141 } 143 }
142 buf 144 (buf, count)
143 } 145 }
144} 146}
145 147
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs
index 027e5a8f8..e4a103d1b 100644
--- a/crates/ra_hir_ty/src/tests.rs
+++ b/crates/ra_hir_ty/src/tests.rs
@@ -309,7 +309,8 @@ fn no_such_field_diagnostics() {
309 } 309 }
310 ", 310 ",
311 ) 311 )
312 .diagnostics(); 312 .diagnostics()
313 .0;
313 314
314 assert_snapshot!(diagnostics, @r###" 315 assert_snapshot!(diagnostics, @r###"
315 "baz: 62": no such field 316 "baz: 62": no such field
diff --git a/crates/ra_hir_ty/src/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs
index 1e303f5ce..b2c971f02 100644
--- a/crates/ra_hir_ty/src/tests/coercion.rs
+++ b/crates/ra_hir_ty/src/tests/coercion.rs
@@ -275,12 +275,14 @@ fn test(i: i32) {
275 [70; 147) 'match ... }': &[i32] 275 [70; 147) 'match ... }': &[i32]
276 [76; 77) 'i': i32 276 [76; 77) 'i': i32
277 [88; 89) '2': i32 277 [88; 89) '2': i32
278 [88; 89) '2': i32
278 [93; 96) 'foo': fn foo<i32>(&[i32]) -> &[i32] 279 [93; 96) 'foo': fn foo<i32>(&[i32]) -> &[i32]
279 [93; 102) 'foo(&[2])': &[i32] 280 [93; 102) 'foo(&[2])': &[i32]
280 [97; 101) '&[2]': &[i32; _] 281 [97; 101) '&[2]': &[i32; _]
281 [98; 101) '[2]': [i32; _] 282 [98; 101) '[2]': [i32; _]
282 [99; 100) '2': i32 283 [99; 100) '2': i32
283 [112; 113) '1': i32 284 [112; 113) '1': i32
285 [112; 113) '1': i32
284 [117; 121) '&[1]': &[i32; _] 286 [117; 121) '&[1]': &[i32; _]
285 [118; 121) '[1]': [i32; _] 287 [118; 121) '[1]': [i32; _]
286 [119; 120) '1': i32 288 [119; 120) '1': i32
@@ -316,10 +318,12 @@ fn test(i: i32) {
316 [70; 147) 'match ... }': &[i32] 318 [70; 147) 'match ... }': &[i32]
317 [76; 77) 'i': i32 319 [76; 77) 'i': i32
318 [88; 89) '1': i32 320 [88; 89) '1': i32
321 [88; 89) '1': i32
319 [93; 97) '&[1]': &[i32; _] 322 [93; 97) '&[1]': &[i32; _]
320 [94; 97) '[1]': [i32; _] 323 [94; 97) '[1]': [i32; _]
321 [95; 96) '1': i32 324 [95; 96) '1': i32
322 [107; 108) '2': i32 325 [107; 108) '2': i32
326 [107; 108) '2': i32
323 [112; 115) 'foo': fn foo<i32>(&[i32]) -> &[i32] 327 [112; 115) 'foo': fn foo<i32>(&[i32]) -> &[i32]
324 [112; 121) 'foo(&[2])': &[i32] 328 [112; 121) 'foo(&[2])': &[i32]
325 [116; 120) '&[2]': &[i32; _] 329 [116; 120) '&[2]': &[i32; _]
@@ -357,9 +361,11 @@ fn test() {
357 [45; 142) 'match ... }': *const i32 361 [45; 142) 'match ... }': *const i32
358 [51; 52) '1': i32 362 [51; 52) '1': i32
359 [63; 64) '1': i32 363 [63; 64) '1': i32
364 [63; 64) '1': i32
360 [68; 69) 't': &mut i32 365 [68; 69) 't': &mut i32
361 [68; 81) 't as *mut i32': *mut i32 366 [68; 81) 't as *mut i32': *mut i32
362 [91; 92) '2': i32 367 [91; 92) '2': i32
368 [91; 92) '2': i32
363 [96; 97) 't': &mut i32 369 [96; 97) 't': &mut i32
364 [96; 105) 't as &i32': &i32 370 [96; 105) 't as &i32': &i32
365 [115; 116) '_': i32 371 [115; 116) '_': i32
@@ -401,16 +407,16 @@ fn test() {
401 [30; 31) 'x': &Foo 407 [30; 31) 'x': &Foo
402 [39; 41) '{}': () 408 [39; 41) '{}': ()
403 [52; 133) '{ ...oo); }': () 409 [52; 133) '{ ...oo); }': ()
404 [58; 71) 'takes_ref_foo': fn takes_ref_foo(&Foo) -> () 410 [58; 71) 'takes_ref_foo': fn takes_ref_foo(&Foo)
405 [58; 77) 'takes_...(&Foo)': () 411 [58; 77) 'takes_...(&Foo)': ()
406 [72; 76) '&Foo': &Foo 412 [72; 76) '&Foo': &Foo
407 [73; 76) 'Foo': Foo 413 [73; 76) 'Foo': Foo
408 [83; 96) 'takes_ref_foo': fn takes_ref_foo(&Foo) -> () 414 [83; 96) 'takes_ref_foo': fn takes_ref_foo(&Foo)
409 [83; 103) 'takes_...&&Foo)': () 415 [83; 103) 'takes_...&&Foo)': ()
410 [97; 102) '&&Foo': &&Foo 416 [97; 102) '&&Foo': &&Foo
411 [98; 102) '&Foo': &Foo 417 [98; 102) '&Foo': &Foo
412 [99; 102) 'Foo': Foo 418 [99; 102) 'Foo': Foo
413 [109; 122) 'takes_ref_foo': fn takes_ref_foo(&Foo) -> () 419 [109; 122) 'takes_ref_foo': fn takes_ref_foo(&Foo)
414 [109; 130) 'takes_...&&Foo)': () 420 [109; 130) 'takes_...&&Foo)': ()
415 [123; 129) '&&&Foo': &&&Foo 421 [123; 129) '&&&Foo': &&&Foo
416 [124; 129) '&&Foo': &&Foo 422 [124; 129) '&&Foo': &&Foo
@@ -478,7 +484,7 @@ fn test() {
478 [171; 178) 'loop {}': ! 484 [171; 178) 'loop {}': !
479 [176; 178) '{}': () 485 [176; 178) '{}': ()
480 [191; 236) '{ ... }); }': () 486 [191; 236) '{ ... }); }': ()
481 [197; 210) 'takes_ref_str': fn takes_ref_str(&str) -> () 487 [197; 210) 'takes_ref_str': fn takes_ref_str(&str)
482 [197; 233) 'takes_...g() })': () 488 [197; 233) 'takes_...g() })': ()
483 [211; 232) '&{ ret...ng() }': &String 489 [211; 232) '&{ ret...ng() }': &String
484 [212; 232) '{ retu...ng() }': String 490 [212; 232) '{ retu...ng() }': String
diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs
index eb97288f1..ff4599b71 100644
--- a/crates/ra_hir_ty/src/tests/macros.rs
+++ b/crates/ra_hir_ty/src/tests/macros.rs
@@ -1,8 +1,10 @@
1use super::{infer, type_at, type_at_pos};
2use crate::test_db::TestDB;
3use insta::assert_snapshot; 1use insta::assert_snapshot;
4use ra_db::fixture::WithFixture; 2use ra_db::fixture::WithFixture;
5 3
4use super::{infer, type_at, type_at_pos};
5
6use crate::test_db::TestDB;
7
6#[test] 8#[test]
7fn cfg_impl_def() { 9fn cfg_impl_def() {
8 let (db, pos) = TestDB::with_position( 10 let (db, pos) = TestDB::with_position(
@@ -658,3 +660,28 @@ fn test() {
658 ); 660 );
659 assert_eq!("S", type_at_pos(&db, pos)); 661 assert_eq!("S", type_at_pos(&db, pos));
660} 662}
663
664#[test]
665fn macro_in_arm() {
666 assert_snapshot!(
667 infer(r#"
668macro_rules! unit {
669 () => { () };
670}
671
672fn main() {
673 let x = match () {
674 unit!() => 92u32,
675 };
676}
677"#),
678 @r###"
679 [52; 111) '{ ... }; }': ()
680 [62; 63) 'x': u32
681 [66; 108) 'match ... }': u32
682 [72; 74) '()': ()
683 [85; 92) 'unit!()': ()
684 [96; 101) '92u32': u32
685 "###
686 );
687}
diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs
index 76aa32024..6e5d2247c 100644
--- a/crates/ra_hir_ty/src/tests/patterns.rs
+++ b/crates/ra_hir_ty/src/tests/patterns.rs
@@ -82,6 +82,90 @@ fn test(x: &i32) {
82} 82}
83 83
84#[test] 84#[test]
85fn infer_literal_pattern() {
86 assert_snapshot!(
87 infer_with_mismatches(r#"
88fn any<T>() -> T { loop {} }
89fn test(x: &i32) {
90 if let "foo" = any() {}
91 if let 1 = any() {}
92 if let 1u32 = any() {}
93 if let 1f32 = any() {}
94 if let 1.0 = any() {}
95 if let true = any() {}
96}
97"#, true),
98 @r###"
99 [18; 29) '{ loop {} }': T
100 [20; 27) 'loop {}': !
101 [25; 27) '{}': ()
102 [38; 39) 'x': &i32
103 [47; 209) '{ ...) {} }': ()
104 [53; 76) 'if let...y() {}': ()
105 [60; 65) '"foo"': &str
106 [60; 65) '"foo"': &str
107 [68; 71) 'any': fn any<&str>() -> &str
108 [68; 73) 'any()': &str
109 [74; 76) '{}': ()
110 [81; 100) 'if let...y() {}': ()
111 [88; 89) '1': i32
112 [88; 89) '1': i32
113 [92; 95) 'any': fn any<i32>() -> i32
114 [92; 97) 'any()': i32
115 [98; 100) '{}': ()
116 [105; 127) 'if let...y() {}': ()
117 [112; 116) '1u32': u32
118 [112; 116) '1u32': u32
119 [119; 122) 'any': fn any<u32>() -> u32
120 [119; 124) 'any()': u32
121 [125; 127) '{}': ()
122 [132; 154) 'if let...y() {}': ()
123 [139; 143) '1f32': f32
124 [139; 143) '1f32': f32
125 [146; 149) 'any': fn any<f32>() -> f32
126 [146; 151) 'any()': f32
127 [152; 154) '{}': ()
128 [159; 180) 'if let...y() {}': ()
129 [166; 169) '1.0': f64
130 [166; 169) '1.0': f64
131 [172; 175) 'any': fn any<f64>() -> f64
132 [172; 177) 'any()': f64
133 [178; 180) '{}': ()
134 [185; 207) 'if let...y() {}': ()
135 [192; 196) 'true': bool
136 [192; 196) 'true': bool
137 [199; 202) 'any': fn any<bool>() -> bool
138 [199; 204) 'any()': bool
139 [205; 207) '{}': ()
140 "###
141 );
142}
143
144#[test]
145fn infer_range_pattern() {
146 assert_snapshot!(
147 infer_with_mismatches(r#"
148fn test(x: &i32) {
149 if let 1..76 = 2u32 {}
150 if let 1..=76 = 2u32 {}
151}
152"#, true),
153 @r###"
154 [9; 10) 'x': &i32
155 [18; 76) '{ ...2 {} }': ()
156 [24; 46) 'if let...u32 {}': ()
157 [31; 36) '1..76': u32
158 [39; 43) '2u32': u32
159 [44; 46) '{}': ()
160 [51; 74) 'if let...u32 {}': ()
161 [58; 64) '1..=76': u32
162 [67; 71) '2u32': u32
163 [72; 74) '{}': ()
164 "###
165 );
166}
167
168#[test]
85fn infer_pattern_match_ergonomics() { 169fn infer_pattern_match_ergonomics() {
86 assert_snapshot!( 170 assert_snapshot!(
87 infer(r#" 171 infer(r#"
@@ -212,6 +296,7 @@ fn test() {
212 [59; 62) 'arr': [f64; _] 296 [59; 62) 'arr': [f64; _]
213 [73; 81) '[1.0, a]': [f64; _] 297 [73; 81) '[1.0, a]': [f64; _]
214 [74; 77) '1.0': f64 298 [74; 77) '1.0': f64
299 [74; 77) '1.0': f64
215 [79; 80) 'a': f64 300 [79; 80) 'a': f64
216 [85; 111) '{ ... }': () 301 [85; 111) '{ ... }': ()
217 [99; 100) 'a': f64 302 [99; 100) 'a': f64
diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs
index a02e3ee05..3402e0cb5 100644
--- a/crates/ra_hir_ty/src/tests/regression.rs
+++ b/crates/ra_hir_ty/src/tests/regression.rs
@@ -206,7 +206,8 @@ pub fn compute() {
206 [24; 106) 'match ... }': () 206 [24; 106) 'match ... }': ()
207 [30; 37) 'nope!()': {unknown} 207 [30; 37) 'nope!()': {unknown}
208 [48; 94) 'SizeSk...tail }': {unknown} 208 [48; 94) 'SizeSk...tail }': {unknown}
209 [82; 86) 'true': {unknown} 209 [82; 86) 'true': bool
210 [82; 86) 'true': bool
210 [88; 92) 'tail': {unknown} 211 [88; 92) 'tail': {unknown}
211 [98; 100) '{}': () 212 [98; 100) '{}': ()
212 "### 213 "###
@@ -375,7 +376,7 @@ fn issue_2669() {
375 ), 376 ),
376 @r###" 377 @r###"
377 [147; 262) '{ ... }': () 378 [147; 262) '{ ... }': ()
378 [161; 164) 'end': fn end<{unknown}>() -> () 379 [161; 164) 'end': fn end<{unknown}>()
379 [161; 166) 'end()': () 380 [161; 166) 'end()': ()
380 [199; 252) '{ ... }': () 381 [199; 252) '{ ... }': ()
381 [221; 223) '_x': ! 382 [221; 223) '_x': !
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs
index c140bd513..c2f1ded2f 100644
--- a/crates/ra_hir_ty/src/tests/simple.rs
+++ b/crates/ra_hir_ty/src/tests/simple.rs
@@ -521,7 +521,7 @@ fn test() -> &mut &f64 {
521 [88; 89) 'a': u32 521 [88; 89) 'a': u32
522 [92; 108) 'unknow...nction': {unknown} 522 [92; 108) 'unknow...nction': {unknown}
523 [92; 110) 'unknow...tion()': u32 523 [92; 110) 'unknow...tion()': u32
524 [116; 125) 'takes_u32': fn takes_u32(u32) -> () 524 [116; 125) 'takes_u32': fn takes_u32(u32)
525 [116; 128) 'takes_u32(a)': () 525 [116; 128) 'takes_u32(a)': ()
526 [126; 127) 'a': u32 526 [126; 127) 'a': u32
527 [138; 139) 'b': i32 527 [138; 139) 'b': i32
@@ -948,6 +948,7 @@ fn foo() {
948 [165; 247) 'match ... }': i32 948 [165; 247) 'match ... }': i32
949 [171; 175) 'true': bool 949 [171; 175) 'true': bool
950 [186; 190) 'true': bool 950 [186; 190) 'true': bool
951 [186; 190) 'true': bool
951 [194; 195) '3': i32 952 [194; 195) '3': i32
952 [205; 206) '_': bool 953 [205; 206) '_': bool
953 [210; 241) '{ ... }': ! 954 [210; 241) '{ ... }': !
@@ -956,6 +957,7 @@ fn foo() {
956 [263; 320) 'match ... }': i32 957 [263; 320) 'match ... }': i32
957 [269; 273) 'true': bool 958 [269; 273) 'true': bool
958 [284; 288) 'true': bool 959 [284; 288) 'true': bool
960 [284; 288) 'true': bool
959 [292; 293) '4': i32 961 [292; 293) '4': i32
960 [303; 304) '_': bool 962 [303; 304) '_': bool
961 [308; 314) 'return': ! 963 [308; 314) 'return': !
@@ -1727,3 +1729,29 @@ fn foo() -> u32 {
1727 "### 1729 "###
1728 ); 1730 );
1729} 1731}
1732
1733#[test]
1734fn fn_pointer_return() {
1735 assert_snapshot!(
1736 infer(r#"
1737struct Vtable {
1738 method: fn(),
1739}
1740
1741fn main() {
1742 let vtable = Vtable { method: || {} };
1743 let m = vtable.method;
1744}
1745"#),
1746 @r###"
1747 [48; 121) '{ ...hod; }': ()
1748 [58; 64) 'vtable': Vtable
1749 [67; 91) 'Vtable...| {} }': Vtable
1750 [84; 89) '|| {}': || -> ()
1751 [87; 89) '{}': ()
1752 [101; 102) 'm': fn()
1753 [105; 111) 'vtable': Vtable
1754 [105; 118) 'vtable.method': fn()
1755 "###
1756 );
1757}
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index f009a708c..22ae6ca90 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -263,7 +263,7 @@ fn test() {
263 [119; 120) 'S': S<u32>(u32) -> S<u32> 263 [119; 120) 'S': S<u32>(u32) -> S<u32>
264 [119; 129) 'S(unknown)': S<u32> 264 [119; 129) 'S(unknown)': S<u32>
265 [121; 128) 'unknown': u32 265 [121; 128) 'unknown': u32
266 [135; 138) 'foo': fn foo<S<u32>>(S<u32>) -> () 266 [135; 138) 'foo': fn foo<S<u32>>(S<u32>)
267 [135; 141) 'foo(s)': () 267 [135; 141) 'foo(s)': ()
268 [139; 140) 's': S<u32> 268 [139; 140) 's': S<u32>
269 "### 269 "###
@@ -962,7 +962,7 @@ fn test(x: impl Trait<u64>, y: &impl Trait<u32>) {
962 [224; 225) 'S': S<u16>(u16) -> S<u16> 962 [224; 225) 'S': S<u16>(u16) -> S<u16>
963 [224; 228) 'S(1)': S<u16> 963 [224; 228) 'S(1)': S<u16>
964 [226; 227) '1': u16 964 [226; 227) '1': u16
965 [234; 237) 'bar': fn bar(S<u16>) -> () 965 [234; 237) 'bar': fn bar(S<u16>)
966 [234; 240) 'bar(z)': () 966 [234; 240) 'bar(z)': ()
967 [238; 239) 'z': S<u16> 967 [238; 239) 'z': S<u16>
968 [246; 247) 'x': impl Trait<u64> 968 [246; 247) 'x': impl Trait<u64>
@@ -1108,8 +1108,8 @@ fn test() {
1108 [40; 47) 'loop {}': ! 1108 [40; 47) 'loop {}': !
1109 [45; 47) '{}': () 1109 [45; 47) '{}': ()
1110 [91; 124) '{ ...foo; }': () 1110 [91; 124) '{ ...foo; }': ()
1111 [101; 102) 'f': fn(S) -> () 1111 [101; 102) 'f': fn(S)
1112 [118; 121) 'foo': fn foo(S) -> () 1112 [118; 121) 'foo': fn foo(S)
1113 "### 1113 "###
1114 ); 1114 );
1115} 1115}
@@ -1962,7 +1962,7 @@ fn test() -> impl Trait<i32> {
1962 [229; 241) 'S(default())': S<u32> 1962 [229; 241) 'S(default())': S<u32>
1963 [231; 238) 'default': fn default<u32>() -> u32 1963 [231; 238) 'default': fn default<u32>() -> u32
1964 [231; 240) 'default()': u32 1964 [231; 240) 'default()': u32
1965 [247; 250) 'foo': fn foo(S<u32>) -> () 1965 [247; 250) 'foo': fn foo(S<u32>)
1966 [247; 254) 'foo(s1)': () 1966 [247; 254) 'foo(s1)': ()
1967 [251; 253) 's1': S<u32> 1967 [251; 253) 's1': S<u32>
1968 [264; 265) 'x': i32 1968 [264; 265) 'x': i32
@@ -2012,7 +2012,7 @@ fn main() {
2012 [147; 149) '_v': F 2012 [147; 149) '_v': F
2013 [192; 195) '{ }': () 2013 [192; 195) '{ }': ()
2014 [207; 238) '{ ... }); }': () 2014 [207; 238) '{ ... }); }': ()
2015 [213; 223) 'f::<(), _>': fn f<(), |&()| -> ()>(|&()| -> ()) -> () 2015 [213; 223) 'f::<(), _>': fn f<(), |&()| -> ()>(|&()| -> ())
2016 [213; 235) 'f::<()... z; })': () 2016 [213; 235) 'f::<()... z; })': ()
2017 [224; 234) '|z| { z; }': |&()| -> () 2017 [224; 234) '|z| { z; }': |&()| -> ()
2018 [225; 226) 'z': &() 2018 [225; 226) 'z': &()
@@ -2021,3 +2021,28 @@ fn main() {
2021 "### 2021 "###
2022 ); 2022 );
2023} 2023}
2024
2025#[test]
2026fn dyn_trait_through_chalk() {
2027 let t = type_at(
2028 r#"
2029//- /main.rs
2030struct Box<T> {}
2031#[lang = "deref"]
2032trait Deref {
2033 type Target;
2034}
2035impl<T> Deref for Box<T> {
2036 type Target = T;
2037}
2038trait Trait {
2039 fn foo(&self);
2040}
2041
2042fn test(x: Box<dyn Trait>) {
2043 x.foo()<|>;
2044}
2045"#,
2046 );
2047 assert_eq!(t, "()");
2048}
diff --git a/crates/ra_hir_ty/src/traits.rs b/crates/ra_hir_ty/src/traits.rs
index a1ca33c98..5a1e12ce9 100644
--- a/crates/ra_hir_ty/src/traits.rs
+++ b/crates/ra_hir_ty/src/traits.rs
@@ -7,7 +7,7 @@ use ra_db::{impl_intern_key, salsa, CrateId};
7use ra_prof::profile; 7use ra_prof::profile;
8use rustc_hash::FxHashSet; 8use rustc_hash::FxHashSet;
9 9
10use crate::db::HirDatabase; 10use crate::{db::HirDatabase, DebruijnIndex};
11 11
12use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; 12use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk};
13 13
@@ -128,7 +128,11 @@ impl TypeWalk for ProjectionPredicate {
128 self.ty.walk(f); 128 self.ty.walk(f);
129 } 129 }
130 130
131 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { 131 fn walk_mut_binders(
132 &mut self,
133 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
134 binders: DebruijnIndex,
135 ) {
132 self.projection_ty.walk_mut_binders(f, binders); 136 self.projection_ty.walk_mut_binders(f, binders);
133 self.ty.walk_mut_binders(f, binders); 137 self.ty.walk_mut_binders(f, binders);
134 } 138 }
@@ -144,7 +148,7 @@ pub(crate) fn trait_solve_query(
144 Obligation::Trait(it) => db.trait_data(it.trait_).name.to_string(), 148 Obligation::Trait(it) => db.trait_data(it.trait_).name.to_string(),
145 Obligation::Projection(_) => "projection".to_string(), 149 Obligation::Projection(_) => "projection".to_string(),
146 }); 150 });
147 log::debug!("trait_solve_query({})", goal.value.value.display(db)); 151 log::info!("trait_solve_query({})", goal.value.value.display(db));
148 152
149 if let Obligation::Projection(pred) = &goal.value.value { 153 if let Obligation::Projection(pred) = &goal.value.value {
150 if let Ty::Bound(_) = &pred.projection_ty.parameters[0] { 154 if let Ty::Bound(_) = &pred.projection_ty.parameters[0] {
@@ -153,7 +157,7 @@ pub(crate) fn trait_solve_query(
153 } 157 }
154 } 158 }
155 159
156 let canonical = goal.to_chalk(db).cast(); 160 let canonical = goal.to_chalk(db).cast(&Interner);
157 161
158 // We currently don't deal with universes (I think / hope they're not yet 162 // We currently don't deal with universes (I think / hope they're not yet
159 // relevant for our use cases?) 163 // relevant for our use cases?)
@@ -194,8 +198,8 @@ fn solution_from_chalk(
194 let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<Interner>>| { 198 let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<Interner>>| {
195 let value = subst 199 let value = subst
196 .value 200 .value
197 .into_iter() 201 .iter(&Interner)
198 .map(|p| match p.ty() { 202 .map(|p| match p.ty(&Interner) {
199 Some(ty) => from_chalk(db, ty.clone()), 203 Some(ty) => from_chalk(db, ty.clone()),
200 None => unimplemented!(), 204 None => unimplemented!(),
201 }) 205 })
diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs
index 73e3c5c78..ccab246bf 100644
--- a/crates/ra_hir_ty/src/traits/builtin.rs
+++ b/crates/ra_hir_ty/src/traits/builtin.rs
@@ -8,7 +8,8 @@ use super::{AssocTyValue, Impl, UnsizeToSuperTraitObjectData};
8use crate::{ 8use crate::{
9 db::HirDatabase, 9 db::HirDatabase,
10 utils::{all_super_traits, generics}, 10 utils::{all_super_traits, generics},
11 ApplicationTy, Binders, GenericPredicate, Substs, TraitRef, Ty, TypeCtor, 11 ApplicationTy, Binders, BoundVar, DebruijnIndex, GenericPredicate, Substs, TraitRef, Ty,
12 TypeCtor, TypeWalk,
12}; 13};
13 14
14pub(super) struct BuiltinImplData { 15pub(super) struct BuiltinImplData {
@@ -164,11 +165,15 @@ fn closure_fn_trait_impl_datum(
164 165
165 let arg_ty = Ty::apply( 166 let arg_ty = Ty::apply(
166 TypeCtor::Tuple { cardinality: num_args }, 167 TypeCtor::Tuple { cardinality: num_args },
167 Substs::builder(num_args as usize).fill_with_bound_vars(0).build(), 168 Substs::builder(num_args as usize)
169 .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
170 .build(),
168 ); 171 );
169 let sig_ty = Ty::apply( 172 let sig_ty = Ty::apply(
170 TypeCtor::FnPtr { num_args }, 173 TypeCtor::FnPtr { num_args },
171 Substs::builder(num_args as usize + 1).fill_with_bound_vars(0).build(), 174 Substs::builder(num_args as usize + 1)
175 .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
176 .build(),
172 ); 177 );
173 178
174 let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty); 179 let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty);
@@ -203,7 +208,7 @@ fn closure_fn_trait_output_assoc_ty_value(
203 } 208 }
204 }; 209 };
205 210
206 let output_ty = Ty::Bound(num_args.into()); 211 let output_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, num_args.into()));
207 212
208 let fn_once_trait = 213 let fn_once_trait =
209 get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist"); 214 get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist");
@@ -241,7 +246,7 @@ fn array_unsize_impl_datum(db: &dyn HirDatabase, krate: CrateId) -> BuiltinImplD
241 // the existence of the Unsize trait has been checked before 246 // the existence of the Unsize trait has been checked before
242 .expect("Unsize trait missing"); 247 .expect("Unsize trait missing");
243 248
244 let var = Ty::Bound(0); 249 let var = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0));
245 let substs = Substs::builder(2) 250 let substs = Substs::builder(2)
246 .push(Ty::apply_one(TypeCtor::Array, var.clone())) 251 .push(Ty::apply_one(TypeCtor::Array, var.clone()))
247 .push(Ty::apply_one(TypeCtor::Slice, var)) 252 .push(Ty::apply_one(TypeCtor::Slice, var))
@@ -270,19 +275,18 @@ fn trait_object_unsize_impl_datum(
270 // the existence of the Unsize trait has been checked before 275 // the existence of the Unsize trait has been checked before
271 .expect("Unsize trait missing"); 276 .expect("Unsize trait missing");
272 277
273 let self_ty = Ty::Bound(0); 278 let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0));
274 279
275 let target_substs = Substs::build_for_def(db, trait_) 280 let target_substs = Substs::build_for_def(db, trait_)
276 .push(Ty::Bound(0)) 281 .push(Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)))
277 // starting from ^2 because we want to start with ^1 outside of the 282 .fill_with_bound_vars(DebruijnIndex::ONE, 1)
278 // `dyn`, which is ^2 inside
279 .fill_with_bound_vars(2)
280 .build(); 283 .build();
281 let num_vars = target_substs.len(); 284 let num_vars = target_substs.len();
282 let target_trait_ref = TraitRef { trait_, substs: target_substs }; 285 let target_trait_ref = TraitRef { trait_, substs: target_substs };
283 let target_bounds = vec![GenericPredicate::Implemented(target_trait_ref)]; 286 let target_bounds = vec![GenericPredicate::Implemented(target_trait_ref)];
284 287
285 let self_substs = Substs::build_for_def(db, trait_).fill_with_bound_vars(0).build(); 288 let self_substs =
289 Substs::build_for_def(db, trait_).fill_with_bound_vars(DebruijnIndex::INNERMOST, 0).build();
286 let self_trait_ref = TraitRef { trait_, substs: self_substs }; 290 let self_trait_ref = TraitRef { trait_, substs: self_substs };
287 let where_clauses = vec![GenericPredicate::Implemented(self_trait_ref)]; 291 let where_clauses = vec![GenericPredicate::Implemented(self_trait_ref)];
288 292
@@ -305,24 +309,26 @@ fn super_trait_object_unsize_impl_datum(
305 // the existence of the Unsize trait has been checked before 309 // the existence of the Unsize trait has been checked before
306 .expect("Unsize trait missing"); 310 .expect("Unsize trait missing");
307 311
308 let self_substs = Substs::build_for_def(db, data.trait_).fill_with_bound_vars(0).build(); 312 let self_substs = Substs::build_for_def(db, data.trait_)
313 .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
314 .build();
315 let self_trait_ref = TraitRef { trait_: data.trait_, substs: self_substs.clone() };
309 316
310 let num_vars = self_substs.len() - 1; 317 let num_vars = self_substs.len() - 1;
311 318
312 let self_trait_ref = TraitRef { trait_: data.trait_, substs: self_substs.clone() };
313 let self_bounds = vec![GenericPredicate::Implemented(self_trait_ref.clone())];
314
315 // we need to go from our trait to the super trait, substituting type parameters 319 // we need to go from our trait to the super trait, substituting type parameters
316 let path = crate::utils::find_super_trait_path(db.upcast(), data.trait_, data.super_trait); 320 let path = crate::utils::find_super_trait_path(db.upcast(), data.trait_, data.super_trait);
317 321
318 let mut current_trait_ref = self_trait_ref; 322 let mut current_trait_ref = self_trait_ref.clone();
319 for t in path.into_iter().skip(1) { 323 for t in path.into_iter().skip(1) {
320 let bounds = db.generic_predicates(current_trait_ref.trait_.into()); 324 let bounds = db.generic_predicates(current_trait_ref.trait_.into());
321 let super_trait_ref = bounds 325 let super_trait_ref = bounds
322 .iter() 326 .iter()
323 .find_map(|b| match &b.value { 327 .find_map(|b| match &b.value {
324 GenericPredicate::Implemented(tr) 328 GenericPredicate::Implemented(tr)
325 if tr.trait_ == t && tr.substs[0] == Ty::Bound(0) => 329 if tr.trait_ == t
330 && tr.substs[0]
331 == Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)) =>
326 { 332 {
327 Some(Binders { value: tr, num_binders: b.num_binders }) 333 Some(Binders { value: tr, num_binders: b.num_binders })
328 } 334 }
@@ -332,7 +338,18 @@ fn super_trait_object_unsize_impl_datum(
332 current_trait_ref = super_trait_ref.cloned().subst(&current_trait_ref.substs); 338 current_trait_ref = super_trait_ref.cloned().subst(&current_trait_ref.substs);
333 } 339 }
334 340
335 let super_bounds = vec![GenericPredicate::Implemented(current_trait_ref)]; 341 // We need to renumber the variables a bit now: from ^0.0, ^0.1, ^0.2, ...
342 // to ^0.0, ^1.0, ^1.1. The reason for this is that the first variable comes
343 // from the dyn Trait binder, while the other variables come from the impl.
344 let new_substs = Substs::builder(num_vars + 1)
345 .push(Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)))
346 .fill_with_bound_vars(DebruijnIndex::ONE, 0)
347 .build();
348
349 let self_bounds =
350 vec![GenericPredicate::Implemented(self_trait_ref.subst_bound_vars(&new_substs))];
351 let super_bounds =
352 vec![GenericPredicate::Implemented(current_trait_ref.subst_bound_vars(&new_substs))];
336 353
337 let substs = Substs::builder(2) 354 let substs = Substs::builder(2)
338 .push(Ty::Dyn(self_bounds.into())) 355 .push(Ty::Dyn(self_bounds.into()))
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs
index 943d5f125..1bc0f0713 100644
--- a/crates/ra_hir_ty/src/traits/chalk.rs
+++ b/crates/ra_hir_ty/src/traits/chalk.rs
@@ -3,7 +3,10 @@ use std::{fmt, sync::Arc};
3 3
4use log::debug; 4use log::debug;
5 5
6use chalk_ir::{cast::Cast, Goal, GoalData, Parameter, PlaceholderIndex, TypeName, UniverseIndex}; 6use chalk_ir::{
7 cast::Cast, fold::shift::Shift, Goal, GoalData, Parameter, PlaceholderIndex, TypeName,
8 UniverseIndex,
9};
7 10
8use hir_def::{AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId}; 11use hir_def::{AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId};
9use ra_db::{ 12use ra_db::{
@@ -59,53 +62,126 @@ impl chalk_ir::interner::Interner for Interner {
59 None 62 None
60 } 63 }
61 64
65 fn debug_ty(_ty: &chalk_ir::Ty<Self>, _fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
66 None
67 }
68
69 fn debug_lifetime(
70 _lifetime: &chalk_ir::Lifetime<Self>,
71 _fmt: &mut fmt::Formatter<'_>,
72 ) -> Option<fmt::Result> {
73 None
74 }
75
76 fn debug_parameter(
77 _parameter: &Parameter<Self>,
78 _fmt: &mut fmt::Formatter<'_>,
79 ) -> Option<fmt::Result> {
80 None
81 }
82
83 fn debug_goal(_goal: &Goal<Self>, _fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
84 None
85 }
86
87 fn debug_goals(
88 _goals: &chalk_ir::Goals<Self>,
89 _fmt: &mut fmt::Formatter<'_>,
90 ) -> Option<fmt::Result> {
91 None
92 }
93
94 fn debug_program_clause_implication(
95 _pci: &chalk_ir::ProgramClauseImplication<Self>,
96 _fmt: &mut fmt::Formatter<'_>,
97 ) -> Option<fmt::Result> {
98 None
99 }
100
101 fn debug_application_ty(
102 _application_ty: &chalk_ir::ApplicationTy<Self>,
103 _fmt: &mut fmt::Formatter<'_>,
104 ) -> Option<fmt::Result> {
105 None
106 }
107
108 fn debug_substitution(
109 _substitution: &chalk_ir::Substitution<Self>,
110 _fmt: &mut fmt::Formatter<'_>,
111 ) -> Option<fmt::Result> {
112 None
113 }
114
115 fn debug_separator_trait_ref(
116 _separator_trait_ref: &chalk_ir::SeparatorTraitRef<Self>,
117 _fmt: &mut fmt::Formatter<'_>,
118 ) -> Option<fmt::Result> {
119 None
120 }
121
62 fn intern_ty(&self, ty: chalk_ir::TyData<Self>) -> Box<chalk_ir::TyData<Self>> { 122 fn intern_ty(&self, ty: chalk_ir::TyData<Self>) -> Box<chalk_ir::TyData<Self>> {
63 Box::new(ty) 123 Box::new(ty)
64 } 124 }
65 125
66 fn ty_data(ty: &Box<chalk_ir::TyData<Self>>) -> &chalk_ir::TyData<Self> { 126 fn ty_data<'a>(&self, ty: &'a Box<chalk_ir::TyData<Self>>) -> &'a chalk_ir::TyData<Self> {
67 ty 127 ty
68 } 128 }
69 129
70 fn intern_lifetime(lifetime: chalk_ir::LifetimeData<Self>) -> chalk_ir::LifetimeData<Self> { 130 fn intern_lifetime(
131 &self,
132 lifetime: chalk_ir::LifetimeData<Self>,
133 ) -> chalk_ir::LifetimeData<Self> {
71 lifetime 134 lifetime
72 } 135 }
73 136
74 fn lifetime_data(lifetime: &chalk_ir::LifetimeData<Self>) -> &chalk_ir::LifetimeData<Self> { 137 fn lifetime_data<'a>(
138 &self,
139 lifetime: &'a chalk_ir::LifetimeData<Self>,
140 ) -> &'a chalk_ir::LifetimeData<Self> {
75 lifetime 141 lifetime
76 } 142 }
77 143
78 fn intern_parameter(parameter: chalk_ir::ParameterData<Self>) -> chalk_ir::ParameterData<Self> { 144 fn intern_parameter(
145 &self,
146 parameter: chalk_ir::ParameterData<Self>,
147 ) -> chalk_ir::ParameterData<Self> {
79 parameter 148 parameter
80 } 149 }
81 150
82 fn parameter_data(parameter: &chalk_ir::ParameterData<Self>) -> &chalk_ir::ParameterData<Self> { 151 fn parameter_data<'a>(
152 &self,
153 parameter: &'a chalk_ir::ParameterData<Self>,
154 ) -> &'a chalk_ir::ParameterData<Self> {
83 parameter 155 parameter
84 } 156 }
85 157
86 fn intern_goal(goal: GoalData<Self>) -> Arc<GoalData<Self>> { 158 fn intern_goal(&self, goal: GoalData<Self>) -> Arc<GoalData<Self>> {
87 Arc::new(goal) 159 Arc::new(goal)
88 } 160 }
89 161
90 fn intern_goals(data: impl IntoIterator<Item = Goal<Self>>) -> Self::InternedGoals { 162 fn intern_goals(&self, data: impl IntoIterator<Item = Goal<Self>>) -> Self::InternedGoals {
91 data.into_iter().collect() 163 data.into_iter().collect()
92 } 164 }
93 165
94 fn goal_data(goal: &Arc<GoalData<Self>>) -> &GoalData<Self> { 166 fn goal_data<'a>(&self, goal: &'a Arc<GoalData<Self>>) -> &'a GoalData<Self> {
95 goal 167 goal
96 } 168 }
97 169
98 fn goals_data(goals: &Vec<Goal<Interner>>) -> &[Goal<Interner>] { 170 fn goals_data<'a>(&self, goals: &'a Vec<Goal<Interner>>) -> &'a [Goal<Interner>] {
99 goals 171 goals
100 } 172 }
101 173
102 fn intern_substitution<E>( 174 fn intern_substitution<E>(
175 &self,
103 data: impl IntoIterator<Item = Result<Parameter<Self>, E>>, 176 data: impl IntoIterator<Item = Result<Parameter<Self>, E>>,
104 ) -> Result<Vec<Parameter<Self>>, E> { 177 ) -> Result<Vec<Parameter<Self>>, E> {
105 data.into_iter().collect() 178 data.into_iter().collect()
106 } 179 }
107 180
108 fn substitution_data(substitution: &Vec<Parameter<Self>>) -> &[Parameter<Self>] { 181 fn substitution_data<'a>(
182 &self,
183 substitution: &'a Vec<Parameter<Self>>,
184 ) -> &'a [Parameter<Self>] {
109 substitution 185 substitution
110 } 186 }
111} 187}
@@ -145,12 +221,14 @@ impl ToChalk for Ty {
145 Ty::Apply(apply_ty) => { 221 Ty::Apply(apply_ty) => {
146 let name = apply_ty.ctor.to_chalk(db); 222 let name = apply_ty.ctor.to_chalk(db);
147 let substitution = apply_ty.parameters.to_chalk(db); 223 let substitution = apply_ty.parameters.to_chalk(db);
148 chalk_ir::ApplicationTy { name, substitution }.cast().intern(&Interner) 224 chalk_ir::ApplicationTy { name, substitution }.cast(&Interner).intern(&Interner)
149 } 225 }
150 Ty::Projection(proj_ty) => { 226 Ty::Projection(proj_ty) => {
151 let associated_ty_id = proj_ty.associated_ty.to_chalk(db); 227 let associated_ty_id = proj_ty.associated_ty.to_chalk(db);
152 let substitution = proj_ty.parameters.to_chalk(db); 228 let substitution = proj_ty.parameters.to_chalk(db);
153 chalk_ir::AliasTy { associated_ty_id, substitution }.cast().intern(&Interner) 229 chalk_ir::AliasTy { associated_ty_id, substitution }
230 .cast(&Interner)
231 .intern(&Interner)
154 } 232 }
155 Ty::Placeholder(id) => { 233 Ty::Placeholder(id) => {
156 let interned_id = db.intern_type_param_id(id); 234 let interned_id = db.intern_type_param_id(id);
@@ -160,7 +238,7 @@ impl ToChalk for Ty {
160 } 238 }
161 .to_ty::<Interner>(&Interner) 239 .to_ty::<Interner>(&Interner)
162 } 240 }
163 Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(&Interner), 241 Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx).intern(&Interner),
164 Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), 242 Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"),
165 Ty::Dyn(predicates) => { 243 Ty::Dyn(predicates) => {
166 let where_clauses = predicates 244 let where_clauses = predicates
@@ -173,14 +251,14 @@ impl ToChalk for Ty {
173 chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner) 251 chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner)
174 } 252 }
175 Ty::Opaque(_) | Ty::Unknown => { 253 Ty::Opaque(_) | Ty::Unknown => {
176 let substitution = chalk_ir::Substitution::empty(); 254 let substitution = chalk_ir::Substitution::empty(&Interner);
177 let name = TypeName::Error; 255 let name = TypeName::Error;
178 chalk_ir::ApplicationTy { name, substitution }.cast().intern(&Interner) 256 chalk_ir::ApplicationTy { name, substitution }.cast(&Interner).intern(&Interner)
179 } 257 }
180 } 258 }
181 } 259 }
182 fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self { 260 fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self {
183 match chalk.data().clone() { 261 match chalk.data(&Interner).clone() {
184 chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name { 262 chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name {
185 TypeName::Error => Ty::Unknown, 263 TypeName::Error => Ty::Unknown,
186 _ => { 264 _ => {
@@ -202,7 +280,7 @@ impl ToChalk for Ty {
202 Ty::Projection(ProjectionTy { associated_ty, parameters }) 280 Ty::Projection(ProjectionTy { associated_ty, parameters })
203 } 281 }
204 chalk_ir::TyData::Function(_) => unimplemented!(), 282 chalk_ir::TyData::Function(_) => unimplemented!(),
205 chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx as u32), 283 chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx),
206 chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown, 284 chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown,
207 chalk_ir::TyData::Dyn(where_clauses) => { 285 chalk_ir::TyData::Dyn(where_clauses) => {
208 assert_eq!(where_clauses.bounds.binders.len(), 1); 286 assert_eq!(where_clauses.bounds.binders.len(), 1);
@@ -218,13 +296,13 @@ impl ToChalk for Substs {
218 type Chalk = chalk_ir::Substitution<Interner>; 296 type Chalk = chalk_ir::Substitution<Interner>;
219 297
220 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Substitution<Interner> { 298 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Substitution<Interner> {
221 chalk_ir::Substitution::from(self.iter().map(|ty| ty.clone().to_chalk(db))) 299 chalk_ir::Substitution::from(&Interner, self.iter().map(|ty| ty.clone().to_chalk(db)))
222 } 300 }
223 301
224 fn from_chalk(db: &dyn HirDatabase, parameters: chalk_ir::Substitution<Interner>) -> Substs { 302 fn from_chalk(db: &dyn HirDatabase, parameters: chalk_ir::Substitution<Interner>) -> Substs {
225 let tys = parameters 303 let tys = parameters
226 .into_iter() 304 .iter(&Interner)
227 .map(|p| match p.ty() { 305 .map(|p| match p.ty(&Interner) {
228 Some(ty) => from_chalk(db, ty.clone()), 306 Some(ty) => from_chalk(db, ty.clone()),
229 None => unimplemented!(), 307 None => unimplemented!(),
230 }) 308 })
@@ -332,15 +410,15 @@ impl ToChalk for GenericPredicate {
332 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::QuantifiedWhereClause<Interner> { 410 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::QuantifiedWhereClause<Interner> {
333 match self { 411 match self {
334 GenericPredicate::Implemented(trait_ref) => { 412 GenericPredicate::Implemented(trait_ref) => {
335 make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0) 413 let chalk_trait_ref = trait_ref.to_chalk(db);
414 let chalk_trait_ref = chalk_trait_ref.shifted_in(&Interner);
415 make_binders(chalk_ir::WhereClause::Implemented(chalk_trait_ref), 0)
416 }
417 GenericPredicate::Projection(projection_pred) => {
418 let ty = projection_pred.ty.to_chalk(db).shifted_in(&Interner);
419 let alias = projection_pred.projection_ty.to_chalk(db).shifted_in(&Interner);
420 make_binders(chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq { alias, ty }), 0)
336 } 421 }
337 GenericPredicate::Projection(projection_pred) => make_binders(
338 chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq {
339 alias: projection_pred.projection_ty.to_chalk(db),
340 ty: projection_pred.ty.to_chalk(db),
341 }),
342 0,
343 ),
344 GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"), 422 GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"),
345 } 423 }
346 } 424 }
@@ -349,7 +427,12 @@ impl ToChalk for GenericPredicate {
349 db: &dyn HirDatabase, 427 db: &dyn HirDatabase,
350 where_clause: chalk_ir::QuantifiedWhereClause<Interner>, 428 where_clause: chalk_ir::QuantifiedWhereClause<Interner>,
351 ) -> GenericPredicate { 429 ) -> GenericPredicate {
352 match where_clause.value { 430 // we don't produce any where clauses with binders and can't currently deal with them
431 match where_clause
432 .value
433 .shifted_out(&Interner)
434 .expect("unexpected bound vars in where clause")
435 {
353 chalk_ir::WhereClause::Implemented(tr) => { 436 chalk_ir::WhereClause::Implemented(tr) => {
354 GenericPredicate::Implemented(from_chalk(db, tr)) 437 GenericPredicate::Implemented(from_chalk(db, tr))
355 } 438 }
@@ -400,8 +483,8 @@ impl ToChalk for Obligation {
400 483
401 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> { 484 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> {
402 match self { 485 match self {
403 Obligation::Trait(tr) => tr.to_chalk(db).cast(), 486 Obligation::Trait(tr) => tr.to_chalk(db).cast(&Interner),
404 Obligation::Projection(pr) => pr.to_chalk(db).cast(), 487 Obligation::Projection(pr) => pr.to_chalk(db).cast(&Interner),
405 } 488 }
406 } 489 }
407 490
@@ -438,8 +521,8 @@ impl ToChalk for Arc<super::TraitEnvironment> {
438 continue; 521 continue;
439 } 522 }
440 let program_clause: chalk_ir::ProgramClause<Interner> = 523 let program_clause: chalk_ir::ProgramClause<Interner> =
441 pred.clone().to_chalk(db).cast(); 524 pred.clone().to_chalk(db).cast(&Interner);
442 clauses.push(program_clause.into_from_env_clause()); 525 clauses.push(program_clause.into_from_env_clause(&Interner));
443 } 526 }
444 chalk_ir::Environment::new().add_clauses(clauses) 527 chalk_ir::Environment::new().add_clauses(clauses)
445 } 528 }
@@ -504,7 +587,8 @@ impl ToChalk for builtin::BuiltinImplAssocTyValueData {
504 type Chalk = AssociatedTyValue; 587 type Chalk = AssociatedTyValue;
505 588
506 fn to_chalk(self, db: &dyn HirDatabase) -> AssociatedTyValue { 589 fn to_chalk(self, db: &dyn HirDatabase) -> AssociatedTyValue {
507 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: self.value.to_chalk(db) }; 590 let ty = self.value.to_chalk(db);
591 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty };
508 592
509 chalk_rust_ir::AssociatedTyValue { 593 chalk_rust_ir::AssociatedTyValue {
510 associated_ty_id: self.assoc_ty_id.to_chalk(db), 594 associated_ty_id: self.assoc_ty_id.to_chalk(db),
@@ -578,9 +662,9 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
578 .map(|impl_| impl_.to_chalk(self.db)) 662 .map(|impl_| impl_.to_chalk(self.db))
579 .collect(); 663 .collect();
580 664
581 let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref().clone()); 665 let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref(&Interner).clone());
582 let arg: Option<Ty> = 666 let arg: Option<Ty> =
583 parameters.get(1).map(|p| from_chalk(self.db, p.assert_ty_ref().clone())); 667 parameters.get(1).map(|p| from_chalk(self.db, p.assert_ty_ref(&Interner).clone()));
584 668
585 builtin::get_builtin_impls(self.db, self.krate, &ty, &arg, trait_, |i| { 669 builtin::get_builtin_impls(self.db, self.krate, &ty, &arg, trait_, |i| {
586 result.push(i.to_chalk(self.db)) 670 result.push(i.to_chalk(self.db))
@@ -663,11 +747,13 @@ pub(crate) fn trait_datum_query(
663 let associated_ty_ids = 747 let associated_ty_ids =
664 trait_data.associated_types().map(|type_alias| type_alias.to_chalk(db)).collect(); 748 trait_data.associated_types().map(|type_alias| type_alias.to_chalk(db)).collect();
665 let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses }; 749 let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses };
750 let well_known = None; // FIXME set this (depending on lang items)
666 let trait_datum = TraitDatum { 751 let trait_datum = TraitDatum {
667 id: trait_id, 752 id: trait_id,
668 binders: make_binders(trait_datum_bound, bound_vars.len()), 753 binders: make_binders(trait_datum_bound, bound_vars.len()),
669 flags, 754 flags,
670 associated_ty_ids, 755 associated_ty_ids,
756 well_known,
671 }; 757 };
672 Arc::new(trait_datum) 758 Arc::new(trait_datum)
673} 759}
diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs
index b40d4eb73..1e5022fa4 100644
--- a/crates/ra_hir_ty/src/utils.rs
+++ b/crates/ra_hir_ty/src/utils.rs
@@ -201,11 +201,11 @@ impl Generics {
201 (parent, self_params, list_params, impl_trait_params) 201 (parent, self_params, list_params, impl_trait_params)
202 } 202 }
203 203
204 pub(crate) fn param_idx(&self, param: TypeParamId) -> Option<u32> { 204 pub(crate) fn param_idx(&self, param: TypeParamId) -> Option<usize> {
205 Some(self.find_param(param)?.0) 205 Some(self.find_param(param)?.0)
206 } 206 }
207 207
208 fn find_param(&self, param: TypeParamId) -> Option<(u32, &TypeParamData)> { 208 fn find_param(&self, param: TypeParamId) -> Option<(usize, &TypeParamData)> {
209 if param.parent == self.def { 209 if param.parent == self.def {
210 let (idx, (_local_id, data)) = self 210 let (idx, (_local_id, data)) = self
211 .params 211 .params
@@ -215,7 +215,7 @@ impl Generics {
215 .find(|(_, (idx, _))| *idx == param.local_id) 215 .find(|(_, (idx, _))| *idx == param.local_id)
216 .unwrap(); 216 .unwrap();
217 let (_total, parent_len, _child) = self.len_split(); 217 let (_total, parent_len, _child) = self.len_split();
218 Some(((parent_len + idx) as u32, data)) 218 Some((parent_len + idx, data))
219 } else { 219 } else {
220 self.parent_generics.as_ref().and_then(|g| g.find_param(param)) 220 self.parent_generics.as_ref().and_then(|g| g.find_param(param))
221 } 221 }