diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/generics.rs | 20 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 133 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 65 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 16 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 175 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/type_ref.rs | 49 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/expressions/atom.rs | 2 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/patterns.rs | 2 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast.rs | 2 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/extensions.rs | 29 | ||||
-rw-r--r-- | crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.rs | 2 | ||||
-rw-r--r-- | crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.txt | 59 |
13 files changed, 501 insertions, 57 deletions
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index e75337cdf..d6728cc9f 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs | |||
@@ -11,7 +11,7 @@ use crate::{ | |||
11 | db::{AstDatabase, DefDatabase, HirDatabase}, | 11 | db::{AstDatabase, DefDatabase, HirDatabase}, |
12 | name::SELF_TYPE, | 12 | name::SELF_TYPE, |
13 | path::Path, | 13 | path::Path, |
14 | type_ref::TypeRef, | 14 | type_ref::{TypeBound, TypeRef}, |
15 | AdtDef, AsName, Container, Enum, EnumVariant, Function, HasSource, ImplBlock, Name, Struct, | 15 | AdtDef, AsName, Container, Enum, EnumVariant, Function, HasSource, ImplBlock, Name, Struct, |
16 | Trait, TypeAlias, Union, | 16 | Trait, TypeAlias, Union, |
17 | }; | 17 | }; |
@@ -35,10 +35,12 @@ pub struct GenericParams { | |||
35 | 35 | ||
36 | /// A single predicate from a where clause, i.e. `where Type: Trait`. Combined | 36 | /// A single predicate from a where clause, i.e. `where Type: Trait`. Combined |
37 | /// where clauses like `where T: Foo + Bar` are turned into multiple of these. | 37 | /// where clauses like `where T: Foo + Bar` are turned into multiple of these. |
38 | /// It might still result in multiple actual predicates though, because of | ||
39 | /// associated type bindings like `Iterator<Item = u32>`. | ||
38 | #[derive(Clone, PartialEq, Eq, Debug)] | 40 | #[derive(Clone, PartialEq, Eq, Debug)] |
39 | pub struct WherePredicate { | 41 | pub struct WherePredicate { |
40 | pub(crate) type_ref: TypeRef, | 42 | pub(crate) type_ref: TypeRef, |
41 | pub(crate) trait_ref: Path, | 43 | pub(crate) bound: TypeBound, |
42 | } | 44 | } |
43 | 45 | ||
44 | // FIXME: consts can have type parameters from their parents (i.e. associated consts of traits) | 46 | // FIXME: consts can have type parameters from their parents (i.e. associated consts of traits) |
@@ -143,18 +145,8 @@ impl GenericParams { | |||
143 | // FIXME: remove this bound | 145 | // FIXME: remove this bound |
144 | return; | 146 | return; |
145 | } | 147 | } |
146 | let path = bound | 148 | let bound = TypeBound::from_ast(bound); |
147 | .type_ref() | 149 | self.where_predicates.push(WherePredicate { type_ref, bound }); |
148 | .and_then(|tr| match tr { | ||
149 | ast::TypeRef::PathType(path) => path.path(), | ||
150 | _ => None, | ||
151 | }) | ||
152 | .and_then(Path::from_ast); | ||
153 | let path = match path { | ||
154 | Some(p) => p, | ||
155 | None => return, | ||
156 | }; | ||
157 | self.where_predicates.push(WherePredicate { type_ref, trait_ref: path }); | ||
158 | } | 150 | } |
159 | 151 | ||
160 | pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { | 152 | pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 642dd02cb..b54c80318 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -161,14 +161,28 @@ pub enum Ty { | |||
161 | name: Name, | 161 | name: Name, |
162 | }, | 162 | }, |
163 | 163 | ||
164 | /// A bound type variable. Only used during trait resolution to represent | 164 | /// A bound type variable. Used during trait resolution to represent Chalk |
165 | /// Chalk variables. | 165 | /// variables, and in `Dyn` and `Opaque` bounds to represent the `Self` type. |
166 | Bound(u32), | 166 | Bound(u32), |
167 | 167 | ||
168 | /// A type variable used during type checking. Not to be confused with a | 168 | /// A type variable used during type checking. Not to be confused with a |
169 | /// type parameter. | 169 | /// type parameter. |
170 | Infer(InferTy), | 170 | Infer(InferTy), |
171 | 171 | ||
172 | /// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust). | ||
173 | /// | ||
174 | /// The predicates are quantified over the `Self` type, i.e. `Ty::Bound(0)` | ||
175 | /// represents the `Self` type inside the bounds. This is currently | ||
176 | /// implicit; Chalk has the `Binders` struct to make it explicit, but it | ||
177 | /// didn't seem worth the overhead yet. | ||
178 | Dyn(Arc<[GenericPredicate]>), | ||
179 | |||
180 | /// An opaque type (`impl Trait`). | ||
181 | /// | ||
182 | /// The predicates are quantified over the `Self` type; see `Ty::Dyn` for | ||
183 | /// more. | ||
184 | Opaque(Arc<[GenericPredicate]>), | ||
185 | |||
172 | /// A placeholder for a type which could not be computed; this is propagated | 186 | /// A placeholder for a type which could not be computed; this is propagated |
173 | /// to avoid useless error messages. Doubles as a placeholder where type | 187 | /// to avoid useless error messages. Doubles as a placeholder where type |
174 | /// variables are inserted before type checking, since we want to try to | 188 | /// variables are inserted before type checking, since we want to try to |
@@ -194,6 +208,12 @@ impl Substs { | |||
194 | Substs(self.0.iter().cloned().take(n).collect::<Vec<_>>().into()) | 208 | Substs(self.0.iter().cloned().take(n).collect::<Vec<_>>().into()) |
195 | } | 209 | } |
196 | 210 | ||
211 | pub fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
212 | for t in self.0.iter() { | ||
213 | t.walk(f); | ||
214 | } | ||
215 | } | ||
216 | |||
197 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 217 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { |
198 | // Without an Arc::make_mut_slice, we can't avoid the clone here: | 218 | // Without an Arc::make_mut_slice, we can't avoid the clone here: |
199 | let mut v: Vec<_> = self.0.iter().cloned().collect(); | 219 | let mut v: Vec<_> = self.0.iter().cloned().collect(); |
@@ -270,6 +290,14 @@ impl TraitRef { | |||
270 | }); | 290 | }); |
271 | self | 291 | self |
272 | } | 292 | } |
293 | |||
294 | pub fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
295 | self.substs.walk(f); | ||
296 | } | ||
297 | |||
298 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | ||
299 | self.substs.walk_mut(f); | ||
300 | } | ||
273 | } | 301 | } |
274 | 302 | ||
275 | /// Like `generics::WherePredicate`, but with resolved types: A condition on the | 303 | /// Like `generics::WherePredicate`, but with resolved types: A condition on the |
@@ -299,6 +327,20 @@ impl GenericPredicate { | |||
299 | GenericPredicate::Error => self, | 327 | GenericPredicate::Error => self, |
300 | } | 328 | } |
301 | } | 329 | } |
330 | |||
331 | pub fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
332 | match self { | ||
333 | GenericPredicate::Implemented(trait_ref) => trait_ref.walk(f), | ||
334 | GenericPredicate::Error => {} | ||
335 | } | ||
336 | } | ||
337 | |||
338 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | ||
339 | match self { | ||
340 | GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut(f), | ||
341 | GenericPredicate::Error => {} | ||
342 | } | ||
343 | } | ||
302 | } | 344 | } |
303 | 345 | ||
304 | /// Basically a claim (currently not validated / checked) that the contained | 346 | /// Basically a claim (currently not validated / checked) that the contained |
@@ -386,6 +428,11 @@ impl Ty { | |||
386 | t.walk(f); | 428 | t.walk(f); |
387 | } | 429 | } |
388 | } | 430 | } |
431 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { | ||
432 | for p in predicates.iter() { | ||
433 | p.walk(f); | ||
434 | } | ||
435 | } | ||
389 | Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} | 436 | Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} |
390 | } | 437 | } |
391 | f(self); | 438 | f(self); |
@@ -402,6 +449,13 @@ impl Ty { | |||
402 | Ty::UnselectedProjection(p_ty) => { | 449 | Ty::UnselectedProjection(p_ty) => { |
403 | p_ty.parameters.walk_mut(f); | 450 | p_ty.parameters.walk_mut(f); |
404 | } | 451 | } |
452 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { | ||
453 | let mut v: Vec<_> = predicates.iter().cloned().collect(); | ||
454 | for p in &mut v { | ||
455 | p.walk_mut(f); | ||
456 | } | ||
457 | *predicates = v.into(); | ||
458 | } | ||
405 | Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} | 459 | Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} |
406 | } | 460 | } |
407 | f(self); | 461 | f(self); |
@@ -529,6 +583,19 @@ impl Ty { | |||
529 | ty => ty, | 583 | ty => ty, |
530 | }) | 584 | }) |
531 | } | 585 | } |
586 | |||
587 | /// If this is an `impl Trait` or `dyn Trait`, returns that trait. | ||
588 | pub fn inherent_trait(&self) -> Option<Trait> { | ||
589 | match self { | ||
590 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { | ||
591 | predicates.iter().find_map(|pred| match pred { | ||
592 | GenericPredicate::Implemented(tr) => Some(tr.trait_), | ||
593 | _ => None, | ||
594 | }) | ||
595 | } | ||
596 | _ => None, | ||
597 | } | ||
598 | } | ||
532 | } | 599 | } |
533 | 600 | ||
534 | impl HirDisplay for &Ty { | 601 | impl HirDisplay for &Ty { |
@@ -669,6 +736,28 @@ impl HirDisplay for Ty { | |||
669 | Ty::UnselectedProjection(p_ty) => p_ty.hir_fmt(f)?, | 736 | Ty::UnselectedProjection(p_ty) => p_ty.hir_fmt(f)?, |
670 | Ty::Param { name, .. } => write!(f, "{}", name)?, | 737 | Ty::Param { name, .. } => write!(f, "{}", name)?, |
671 | Ty::Bound(idx) => write!(f, "?{}", idx)?, | 738 | Ty::Bound(idx) => write!(f, "?{}", idx)?, |
739 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { | ||
740 | match self { | ||
741 | Ty::Dyn(_) => write!(f, "dyn ")?, | ||
742 | Ty::Opaque(_) => write!(f, "impl ")?, | ||
743 | _ => unreachable!(), | ||
744 | }; | ||
745 | // looping by hand here just to format the bounds in a slightly nicer way | ||
746 | let mut first = true; | ||
747 | for p in predicates.iter() { | ||
748 | if !first { | ||
749 | write!(f, " + ")?; | ||
750 | } | ||
751 | first = false; | ||
752 | match p { | ||
753 | // don't show the $0 self type | ||
754 | GenericPredicate::Implemented(trait_ref) => { | ||
755 | trait_ref.hir_fmt_ext(f, false)? | ||
756 | } | ||
757 | GenericPredicate::Error => p.hir_fmt(f)?, | ||
758 | } | ||
759 | } | ||
760 | } | ||
672 | Ty::Unknown => write!(f, "{{unknown}}")?, | 761 | Ty::Unknown => write!(f, "{{unknown}}")?, |
673 | Ty::Infer(..) => write!(f, "_")?, | 762 | Ty::Infer(..) => write!(f, "_")?, |
674 | } | 763 | } |
@@ -676,14 +765,16 @@ impl HirDisplay for Ty { | |||
676 | } | 765 | } |
677 | } | 766 | } |
678 | 767 | ||
679 | impl HirDisplay for TraitRef { | 768 | impl TraitRef { |
680 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | 769 | fn hir_fmt_ext( |
681 | write!( | 770 | &self, |
682 | f, | 771 | f: &mut HirFormatter<impl HirDatabase>, |
683 | "{}: {}", | 772 | with_self_ty: bool, |
684 | self.substs[0].display(f.db), | 773 | ) -> fmt::Result { |
685 | self.trait_.name(f.db).unwrap_or_else(Name::missing) | 774 | if with_self_ty { |
686 | )?; | 775 | write!(f, "{}: ", self.substs[0].display(f.db),)?; |
776 | } | ||
777 | write!(f, "{}", self.trait_.name(f.db).unwrap_or_else(Name::missing))?; | ||
687 | if self.substs.len() > 1 { | 778 | if self.substs.len() > 1 { |
688 | write!(f, "<")?; | 779 | write!(f, "<")?; |
689 | f.write_joined(&self.substs[1..], ", ")?; | 780 | f.write_joined(&self.substs[1..], ", ")?; |
@@ -693,6 +784,28 @@ impl HirDisplay for TraitRef { | |||
693 | } | 784 | } |
694 | } | 785 | } |
695 | 786 | ||
787 | impl HirDisplay for TraitRef { | ||
788 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | ||
789 | self.hir_fmt_ext(f, true) | ||
790 | } | ||
791 | } | ||
792 | |||
793 | impl HirDisplay for &GenericPredicate { | ||
794 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | ||
795 | HirDisplay::hir_fmt(*self, f) | ||
796 | } | ||
797 | } | ||
798 | |||
799 | impl HirDisplay for GenericPredicate { | ||
800 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | ||
801 | match self { | ||
802 | GenericPredicate::Implemented(trait_ref) => trait_ref.hir_fmt(f)?, | ||
803 | GenericPredicate::Error => write!(f, "{{error}}")?, | ||
804 | } | ||
805 | Ok(()) | ||
806 | } | ||
807 | } | ||
808 | |||
696 | impl HirDisplay for Obligation { | 809 | impl HirDisplay for Obligation { |
697 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | 810 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { |
698 | match self { | 811 | match self { |
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index debedcbb8..47d161277 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -17,7 +17,7 @@ use crate::{ | |||
17 | path::{GenericArg, PathSegment}, | 17 | path::{GenericArg, PathSegment}, |
18 | resolve::{Resolution, Resolver}, | 18 | resolve::{Resolution, Resolver}, |
19 | ty::AdtDef, | 19 | ty::AdtDef, |
20 | type_ref::TypeRef, | 20 | type_ref::{TypeBound, TypeRef}, |
21 | BuiltinType, Const, Enum, EnumVariant, Function, HirDatabase, ModuleDef, Path, Static, Struct, | 21 | BuiltinType, Const, Enum, EnumVariant, Function, HirDatabase, ModuleDef, Path, Static, Struct, |
22 | StructField, Trait, TypeAlias, Union, | 22 | StructField, Trait, TypeAlias, Union, |
23 | }; | 23 | }; |
@@ -58,6 +58,22 @@ impl Ty { | |||
58 | let sig = Substs(inner_tys.into()); | 58 | let sig = Substs(inner_tys.into()); |
59 | Ty::apply(TypeCtor::FnPtr { num_args: sig.len() as u16 - 1 }, sig) | 59 | Ty::apply(TypeCtor::FnPtr { num_args: sig.len() as u16 - 1 }, sig) |
60 | } | 60 | } |
61 | TypeRef::DynTrait(bounds) => { | ||
62 | let self_ty = Ty::Bound(0); | ||
63 | let predicates = bounds | ||
64 | .iter() | ||
65 | .map(|b| GenericPredicate::from_type_bound(db, resolver, b, self_ty.clone())) | ||
66 | .collect::<Vec<_>>(); | ||
67 | Ty::Dyn(predicates.into()) | ||
68 | } | ||
69 | TypeRef::ImplTrait(bounds) => { | ||
70 | let self_ty = Ty::Bound(0); | ||
71 | let predicates = bounds | ||
72 | .iter() | ||
73 | .map(|b| GenericPredicate::from_type_bound(db, resolver, b, self_ty.clone())) | ||
74 | .collect::<Vec<_>>(); | ||
75 | Ty::Opaque(predicates.into()) | ||
76 | } | ||
61 | TypeRef::Error => Ty::Unknown, | 77 | TypeRef::Error => Ty::Unknown, |
62 | } | 78 | } |
63 | } | 79 | } |
@@ -310,13 +326,46 @@ impl TraitRef { | |||
310 | TraitRef { trait_, substs } | 326 | TraitRef { trait_, substs } |
311 | } | 327 | } |
312 | 328 | ||
313 | pub(crate) fn for_where_predicate( | 329 | pub(crate) fn from_where_predicate( |
314 | db: &impl HirDatabase, | 330 | db: &impl HirDatabase, |
315 | resolver: &Resolver, | 331 | resolver: &Resolver, |
316 | pred: &WherePredicate, | 332 | pred: &WherePredicate, |
317 | ) -> Option<TraitRef> { | 333 | ) -> Option<TraitRef> { |
318 | let self_ty = Ty::from_hir(db, resolver, &pred.type_ref); | 334 | let self_ty = Ty::from_hir(db, resolver, &pred.type_ref); |
319 | TraitRef::from_path(db, resolver, &pred.trait_ref, Some(self_ty)) | 335 | TraitRef::from_type_bound(db, resolver, &pred.bound, self_ty) |
336 | } | ||
337 | |||
338 | pub(crate) fn from_type_bound( | ||
339 | db: &impl HirDatabase, | ||
340 | resolver: &Resolver, | ||
341 | bound: &TypeBound, | ||
342 | self_ty: Ty, | ||
343 | ) -> Option<TraitRef> { | ||
344 | match bound { | ||
345 | TypeBound::Path(path) => TraitRef::from_path(db, resolver, path, Some(self_ty)), | ||
346 | TypeBound::Error => None, | ||
347 | } | ||
348 | } | ||
349 | } | ||
350 | |||
351 | impl GenericPredicate { | ||
352 | pub(crate) fn from_where_predicate( | ||
353 | db: &impl HirDatabase, | ||
354 | resolver: &Resolver, | ||
355 | where_predicate: &WherePredicate, | ||
356 | ) -> GenericPredicate { | ||
357 | TraitRef::from_where_predicate(db, &resolver, where_predicate) | ||
358 | .map_or(GenericPredicate::Error, GenericPredicate::Implemented) | ||
359 | } | ||
360 | |||
361 | pub(crate) fn from_type_bound( | ||
362 | db: &impl HirDatabase, | ||
363 | resolver: &Resolver, | ||
364 | bound: &TypeBound, | ||
365 | self_ty: Ty, | ||
366 | ) -> GenericPredicate { | ||
367 | TraitRef::from_type_bound(db, &resolver, bound, self_ty) | ||
368 | .map_or(GenericPredicate::Error, GenericPredicate::Implemented) | ||
320 | } | 369 | } |
321 | } | 370 | } |
322 | 371 | ||
@@ -376,10 +425,7 @@ pub(crate) fn trait_env( | |||
376 | ) -> Arc<super::TraitEnvironment> { | 425 | ) -> Arc<super::TraitEnvironment> { |
377 | let predicates = resolver | 426 | let predicates = resolver |
378 | .where_predicates_in_scope() | 427 | .where_predicates_in_scope() |
379 | .map(|pred| { | 428 | .map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) |
380 | TraitRef::for_where_predicate(db, &resolver, pred) | ||
381 | .map_or(GenericPredicate::Error, GenericPredicate::Implemented) | ||
382 | }) | ||
383 | .collect::<Vec<_>>(); | 429 | .collect::<Vec<_>>(); |
384 | 430 | ||
385 | Arc::new(super::TraitEnvironment { predicates }) | 431 | Arc::new(super::TraitEnvironment { predicates }) |
@@ -393,10 +439,7 @@ pub(crate) fn generic_predicates_query( | |||
393 | let resolver = def.resolver(db); | 439 | let resolver = def.resolver(db); |
394 | let predicates = resolver | 440 | let predicates = resolver |
395 | .where_predicates_in_scope() | 441 | .where_predicates_in_scope() |
396 | .map(|pred| { | 442 | .map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) |
397 | TraitRef::for_where_predicate(db, &resolver, pred) | ||
398 | .map_or(GenericPredicate::Error, GenericPredicate::Implemented) | ||
399 | }) | ||
400 | .collect::<Vec<_>>(); | 443 | .collect::<Vec<_>>(); |
401 | predicates.into() | 444 | predicates.into() |
402 | } | 445 | } |
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 3f4c43aee..9873a0440 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -211,12 +211,19 @@ fn iterate_trait_method_candidates<T>( | |||
211 | let krate = resolver.krate()?; | 211 | let krate = resolver.krate()?; |
212 | // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that) | 212 | // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that) |
213 | let env = lower::trait_env(db, resolver); | 213 | let env = lower::trait_env(db, resolver); |
214 | 'traits: for t in resolver.traits_in_scope(db) { | 214 | // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope |
215 | let traits = ty.value.inherent_trait().into_iter().chain(resolver.traits_in_scope(db)); | ||
216 | 'traits: for t in traits { | ||
215 | let data = t.trait_data(db); | 217 | let data = t.trait_data(db); |
218 | |||
219 | // FIXME this is a bit of a hack, since Chalk should say the same thing | ||
220 | // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet | ||
221 | let inherently_implemented = ty.value.inherent_trait() == Some(t); | ||
222 | |||
216 | // we'll be lazy about checking whether the type implements the | 223 | // we'll be lazy about checking whether the type implements the |
217 | // trait, but if we find out it doesn't, we'll skip the rest of the | 224 | // trait, but if we find out it doesn't, we'll skip the rest of the |
218 | // iteration | 225 | // iteration |
219 | let mut known_implemented = false; | 226 | let mut known_implemented = inherently_implemented; |
220 | for item in data.items() { | 227 | for item in data.items() { |
221 | if let TraitItem::Function(m) = *item { | 228 | if let TraitItem::Function(m) = *item { |
222 | let data = m.data(db); | 229 | let data = m.data(db); |
@@ -271,6 +278,11 @@ pub(crate) fn implements_trait( | |||
271 | krate: Crate, | 278 | krate: Crate, |
272 | trait_: Trait, | 279 | trait_: Trait, |
273 | ) -> bool { | 280 | ) -> bool { |
281 | if ty.value.inherent_trait() == Some(trait_) { | ||
282 | // FIXME this is a bit of a hack, since Chalk should say the same thing | ||
283 | // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet | ||
284 | return true; | ||
285 | } | ||
274 | let env = lower::trait_env(db, resolver); | 286 | let env = lower::trait_env(db, resolver); |
275 | let goal = generic_implements_goal(db, env.clone(), trait_, ty.clone()); | 287 | let goal = generic_implements_goal(db, env.clone(), trait_, ty.clone()); |
276 | let solution = db.trait_solve(krate, goal); | 288 | let solution = db.trait_solve(krate, goal); |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 57fd5492d..c5818b738 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -3273,6 +3273,181 @@ fn test<T: ApplyL>(t: T) { | |||
3273 | assert_eq!(t, "{unknown}"); | 3273 | assert_eq!(t, "{unknown}"); |
3274 | } | 3274 | } |
3275 | 3275 | ||
3276 | #[test] | ||
3277 | fn impl_trait() { | ||
3278 | assert_snapshot_matches!( | ||
3279 | infer(r#" | ||
3280 | trait Trait<T> { | ||
3281 | fn foo(&self) -> T; | ||
3282 | fn foo2(&self) -> i64; | ||
3283 | } | ||
3284 | fn bar() -> impl Trait<u64> {} | ||
3285 | |||
3286 | fn test(x: impl Trait<u64>, y: &impl Trait<u64>) { | ||
3287 | x; | ||
3288 | y; | ||
3289 | let z = bar(); | ||
3290 | x.foo(); | ||
3291 | y.foo(); | ||
3292 | z.foo(); | ||
3293 | x.foo2(); | ||
3294 | y.foo2(); | ||
3295 | z.foo2(); | ||
3296 | } | ||
3297 | "#), | ||
3298 | @r###" | ||
3299 | â‹® | ||
3300 | â‹®[30; 34) 'self': &Self | ||
3301 | â‹®[55; 59) 'self': &Self | ||
3302 | â‹®[99; 101) '{}': () | ||
3303 | â‹®[111; 112) 'x': impl Trait<u64> | ||
3304 | â‹®[131; 132) 'y': &impl Trait<u64> | ||
3305 | â‹®[152; 269) '{ ...2(); }': () | ||
3306 | â‹®[158; 159) 'x': impl Trait<u64> | ||
3307 | â‹®[165; 166) 'y': &impl Trait<u64> | ||
3308 | â‹®[176; 177) 'z': impl Trait<u64> | ||
3309 | â‹®[180; 183) 'bar': fn bar() -> impl Trait<u64> | ||
3310 | â‹®[180; 185) 'bar()': impl Trait<u64> | ||
3311 | â‹®[191; 192) 'x': impl Trait<u64> | ||
3312 | â‹®[191; 198) 'x.foo()': {unknown} | ||
3313 | â‹®[204; 205) 'y': &impl Trait<u64> | ||
3314 | â‹®[204; 211) 'y.foo()': {unknown} | ||
3315 | â‹®[217; 218) 'z': impl Trait<u64> | ||
3316 | â‹®[217; 224) 'z.foo()': {unknown} | ||
3317 | â‹®[230; 231) 'x': impl Trait<u64> | ||
3318 | â‹®[230; 238) 'x.foo2()': i64 | ||
3319 | â‹®[244; 245) 'y': &impl Trait<u64> | ||
3320 | â‹®[244; 252) 'y.foo2()': i64 | ||
3321 | â‹®[258; 259) 'z': impl Trait<u64> | ||
3322 | â‹®[258; 266) 'z.foo2()': i64 | ||
3323 | "### | ||
3324 | ); | ||
3325 | } | ||
3326 | |||
3327 | #[test] | ||
3328 | fn dyn_trait() { | ||
3329 | assert_snapshot_matches!( | ||
3330 | infer(r#" | ||
3331 | trait Trait<T> { | ||
3332 | fn foo(&self) -> T; | ||
3333 | fn foo2(&self) -> i64; | ||
3334 | } | ||
3335 | fn bar() -> dyn Trait<u64> {} | ||
3336 | |||
3337 | fn test(x: dyn Trait<u64>, y: &dyn Trait<u64>) { | ||
3338 | x; | ||
3339 | y; | ||
3340 | let z = bar(); | ||
3341 | x.foo(); | ||
3342 | y.foo(); | ||
3343 | z.foo(); | ||
3344 | x.foo2(); | ||
3345 | y.foo2(); | ||
3346 | z.foo2(); | ||
3347 | } | ||
3348 | "#), | ||
3349 | @r###" | ||
3350 | â‹® | ||
3351 | â‹®[30; 34) 'self': &Self | ||
3352 | â‹®[55; 59) 'self': &Self | ||
3353 | â‹®[98; 100) '{}': () | ||
3354 | â‹®[110; 111) 'x': dyn Trait<u64> | ||
3355 | â‹®[129; 130) 'y': &dyn Trait<u64> | ||
3356 | â‹®[149; 266) '{ ...2(); }': () | ||
3357 | â‹®[155; 156) 'x': dyn Trait<u64> | ||
3358 | â‹®[162; 163) 'y': &dyn Trait<u64> | ||
3359 | â‹®[173; 174) 'z': dyn Trait<u64> | ||
3360 | â‹®[177; 180) 'bar': fn bar() -> dyn Trait<u64> | ||
3361 | â‹®[177; 182) 'bar()': dyn Trait<u64> | ||
3362 | â‹®[188; 189) 'x': dyn Trait<u64> | ||
3363 | â‹®[188; 195) 'x.foo()': {unknown} | ||
3364 | â‹®[201; 202) 'y': &dyn Trait<u64> | ||
3365 | â‹®[201; 208) 'y.foo()': {unknown} | ||
3366 | â‹®[214; 215) 'z': dyn Trait<u64> | ||
3367 | â‹®[214; 221) 'z.foo()': {unknown} | ||
3368 | â‹®[227; 228) 'x': dyn Trait<u64> | ||
3369 | â‹®[227; 235) 'x.foo2()': i64 | ||
3370 | â‹®[241; 242) 'y': &dyn Trait<u64> | ||
3371 | â‹®[241; 249) 'y.foo2()': i64 | ||
3372 | â‹®[255; 256) 'z': dyn Trait<u64> | ||
3373 | â‹®[255; 263) 'z.foo2()': i64 | ||
3374 | "### | ||
3375 | ); | ||
3376 | } | ||
3377 | |||
3378 | #[test] | ||
3379 | fn dyn_trait_bare() { | ||
3380 | assert_snapshot_matches!( | ||
3381 | infer(r#" | ||
3382 | trait Trait { | ||
3383 | fn foo(&self) -> u64; | ||
3384 | } | ||
3385 | fn bar() -> Trait {} | ||
3386 | |||
3387 | fn test(x: Trait, y: &Trait) -> u64 { | ||
3388 | x; | ||
3389 | y; | ||
3390 | let z = bar(); | ||
3391 | x.foo(); | ||
3392 | y.foo(); | ||
3393 | z.foo(); | ||
3394 | } | ||
3395 | "#), | ||
3396 | @r###" | ||
3397 | â‹® | ||
3398 | â‹®[27; 31) 'self': &Self | ||
3399 | â‹®[61; 63) '{}': () | ||
3400 | â‹®[73; 74) 'x': {unknown} | ||
3401 | â‹®[83; 84) 'y': &{unknown} | ||
3402 | â‹®[101; 176) '{ ...o(); }': () | ||
3403 | â‹®[107; 108) 'x': {unknown} | ||
3404 | â‹®[114; 115) 'y': &{unknown} | ||
3405 | â‹®[125; 126) 'z': {unknown} | ||
3406 | â‹®[129; 132) 'bar': fn bar() -> {unknown} | ||
3407 | â‹®[129; 134) 'bar()': {unknown} | ||
3408 | â‹®[140; 141) 'x': {unknown} | ||
3409 | â‹®[140; 147) 'x.foo()': {unknown} | ||
3410 | â‹®[153; 154) 'y': &{unknown} | ||
3411 | â‹®[153; 160) 'y.foo()': {unknown} | ||
3412 | â‹®[166; 167) 'z': {unknown} | ||
3413 | â‹®[166; 173) 'z.foo()': {unknown} | ||
3414 | "### | ||
3415 | ); | ||
3416 | } | ||
3417 | |||
3418 | #[test] | ||
3419 | fn weird_bounds() { | ||
3420 | assert_snapshot_matches!( | ||
3421 | infer(r#" | ||
3422 | trait Trait {} | ||
3423 | fn test() { | ||
3424 | let a: impl Trait + 'lifetime = foo; | ||
3425 | let b: impl 'lifetime = foo; | ||
3426 | let b: impl (Trait) = foo; | ||
3427 | let b: impl ('lifetime) = foo; | ||
3428 | let d: impl ?Sized = foo; | ||
3429 | let e: impl Trait + ?Sized = foo; | ||
3430 | } | ||
3431 | "#), | ||
3432 | @r###" | ||
3433 | â‹® | ||
3434 | â‹®[26; 237) '{ ...foo; }': () | ||
3435 | â‹®[36; 37) 'a': impl Trait + {error} | ||
3436 | â‹®[64; 67) 'foo': impl Trait + {error} | ||
3437 | â‹®[77; 78) 'b': impl {error} | ||
3438 | â‹®[97; 100) 'foo': impl {error} | ||
3439 | â‹®[110; 111) 'b': impl Trait | ||
3440 | â‹®[128; 131) 'foo': impl Trait | ||
3441 | â‹®[141; 142) 'b': impl {error} | ||
3442 | â‹®[163; 166) 'foo': impl {error} | ||
3443 | â‹®[176; 177) 'd': impl {error} | ||
3444 | â‹®[193; 196) 'foo': impl {error} | ||
3445 | â‹®[206; 207) 'e': impl Trait + {error} | ||
3446 | â‹®[231; 234) 'foo': impl Trait + {error} | ||
3447 | "### | ||
3448 | ); | ||
3449 | } | ||
3450 | |||
3276 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { | 3451 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { |
3277 | let file = db.parse(pos.file_id).ok().unwrap(); | 3452 | let file = db.parse(pos.file_id).ok().unwrap(); |
3278 | let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); | 3453 | let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); |
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 6df7094c5..2ebc06135 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs | |||
@@ -80,7 +80,9 @@ impl ToChalk for Ty { | |||
80 | // FIXME this is clearly incorrect, but probably not too incorrect | 80 | // FIXME this is clearly incorrect, but probably not too incorrect |
81 | // and I'm not sure what to actually do with Ty::Unknown | 81 | // and I'm not sure what to actually do with Ty::Unknown |
82 | // maybe an alternative would be `for<T> T`? (meaningless in rust, but expressible in chalk's Ty) | 82 | // maybe an alternative would be `for<T> T`? (meaningless in rust, but expressible in chalk's Ty) |
83 | Ty::Unknown => { | 83 | // |
84 | // FIXME also dyn and impl Trait are currently handled like Unknown because Chalk doesn't have them yet | ||
85 | Ty::Unknown | Ty::Dyn(_) | Ty::Opaque(_) => { | ||
84 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::max_value() }.to_ty() | 86 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::max_value() }.to_ty() |
85 | } | 87 | } |
86 | } | 88 | } |
diff --git a/crates/ra_hir/src/type_ref.rs b/crates/ra_hir/src/type_ref.rs index b92a0b55a..fa91bfb22 100644 --- a/crates/ra_hir/src/type_ref.rs +++ b/crates/ra_hir/src/type_ref.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! HIR for references to types. Paths in these are not yet resolved. They can | 1 | //! HIR for references to types. Paths in these are not yet resolved. They can |
2 | //! be directly created from an ast::TypeRef, without further queries. | 2 | //! be directly created from an ast::TypeRef, without further queries. |
3 | 3 | ||
4 | use ra_syntax::ast::{self, TypeAscriptionOwner}; | 4 | use ra_syntax::ast::{self, TypeAscriptionOwner, TypeBoundsOwner}; |
5 | 5 | ||
6 | use crate::Path; | 6 | use crate::Path; |
7 | 7 | ||
@@ -49,8 +49,16 @@ pub enum TypeRef { | |||
49 | /// A fn pointer. Last element of the vector is the return type. | 49 | /// A fn pointer. Last element of the vector is the return type. |
50 | Fn(Vec<TypeRef>), | 50 | Fn(Vec<TypeRef>), |
51 | // For | 51 | // For |
52 | // ImplTrait, | 52 | ImplTrait(Vec<TypeBound>), |
53 | // DynTrait, | 53 | DynTrait(Vec<TypeBound>), |
54 | Error, | ||
55 | } | ||
56 | |||
57 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | ||
58 | pub enum TypeBound { | ||
59 | Path(Path), | ||
60 | // also for<> bounds | ||
61 | // also Lifetimes | ||
54 | Error, | 62 | Error, |
55 | } | 63 | } |
56 | 64 | ||
@@ -95,8 +103,12 @@ impl TypeRef { | |||
95 | } | 103 | } |
96 | // for types are close enough for our purposes to the inner type for now... | 104 | // for types are close enough for our purposes to the inner type for now... |
97 | ast::TypeRef::ForType(inner) => TypeRef::from_ast_opt(inner.type_ref()), | 105 | ast::TypeRef::ForType(inner) => TypeRef::from_ast_opt(inner.type_ref()), |
98 | ast::TypeRef::ImplTraitType(_inner) => TypeRef::Error, | 106 | ast::TypeRef::ImplTraitType(inner) => { |
99 | ast::TypeRef::DynTraitType(_inner) => TypeRef::Error, | 107 | TypeRef::ImplTrait(type_bounds_from_ast(inner.type_bound_list())) |
108 | } | ||
109 | ast::TypeRef::DynTraitType(inner) => { | ||
110 | TypeRef::DynTrait(type_bounds_from_ast(inner.type_bound_list())) | ||
111 | } | ||
100 | } | 112 | } |
101 | } | 113 | } |
102 | 114 | ||
@@ -112,3 +124,30 @@ impl TypeRef { | |||
112 | TypeRef::Tuple(Vec::new()) | 124 | TypeRef::Tuple(Vec::new()) |
113 | } | 125 | } |
114 | } | 126 | } |
127 | |||
128 | pub(crate) fn type_bounds_from_ast(type_bounds_opt: Option<ast::TypeBoundList>) -> Vec<TypeBound> { | ||
129 | if let Some(type_bounds) = type_bounds_opt { | ||
130 | type_bounds.bounds().map(TypeBound::from_ast).collect() | ||
131 | } else { | ||
132 | vec![] | ||
133 | } | ||
134 | } | ||
135 | |||
136 | impl TypeBound { | ||
137 | pub(crate) fn from_ast(node: ast::TypeBound) -> Self { | ||
138 | match node.kind() { | ||
139 | ast::TypeBoundKind::PathType(path_type) => { | ||
140 | let path = match path_type.path() { | ||
141 | Some(p) => p, | ||
142 | None => return TypeBound::Error, | ||
143 | }; | ||
144 | let path = match Path::from_ast(path) { | ||
145 | Some(p) => p, | ||
146 | None => return TypeBound::Error, | ||
147 | }; | ||
148 | TypeBound::Path(path) | ||
149 | } | ||
150 | ast::TypeBoundKind::ForType(_) | ast::TypeBoundKind::Lifetime(_) => TypeBound::Error, | ||
151 | } | ||
152 | } | ||
153 | } | ||
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs index bc942ae01..ab8fb9f6e 100644 --- a/crates/ra_parser/src/grammar/expressions/atom.rs +++ b/crates/ra_parser/src/grammar/expressions/atom.rs | |||
@@ -414,6 +414,8 @@ pub(crate) fn match_arm_list(p: &mut Parser) { | |||
414 | // X | Y if Z => (), | 414 | // X | Y if Z => (), |
415 | // | X | Y if Z => (), | 415 | // | X | Y if Z => (), |
416 | // | X => (), | 416 | // | X => (), |
417 | // box X => (), | ||
418 | // Some(box X) => (), | ||
417 | // }; | 419 | // }; |
418 | // } | 420 | // } |
419 | fn match_arm(p: &mut Parser) -> BlockLike { | 421 | fn match_arm(p: &mut Parser) -> BlockLike { |
diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs index df6000707..1f6a6fd48 100644 --- a/crates/ra_parser/src/grammar/patterns.rs +++ b/crates/ra_parser/src/grammar/patterns.rs | |||
@@ -2,7 +2,7 @@ use super::*; | |||
2 | 2 | ||
3 | pub(super) const PATTERN_FIRST: TokenSet = expressions::LITERAL_FIRST | 3 | pub(super) const PATTERN_FIRST: TokenSet = expressions::LITERAL_FIRST |
4 | .union(paths::PATH_FIRST) | 4 | .union(paths::PATH_FIRST) |
5 | .union(token_set![REF_KW, MUT_KW, L_PAREN, L_BRACK, AMP, UNDERSCORE, MINUS]); | 5 | .union(token_set![BOX_KW, REF_KW, MUT_KW, L_PAREN, L_BRACK, AMP, UNDERSCORE, MINUS]); |
6 | 6 | ||
7 | pub(super) fn pattern(p: &mut Parser) { | 7 | pub(super) fn pattern(p: &mut Parser) { |
8 | pattern_r(p, PAT_RECOVERY_SET); | 8 | pattern_r(p, PAT_RECOVERY_SET); |
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index 6f0489617..afdfca66e 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs | |||
@@ -15,7 +15,7 @@ use crate::{ | |||
15 | 15 | ||
16 | pub use self::{ | 16 | pub use self::{ |
17 | expr_extensions::{ArrayExprKind, BinOp, ElseBranch, LiteralKind, PrefixOp}, | 17 | expr_extensions::{ArrayExprKind, BinOp, ElseBranch, LiteralKind, PrefixOp}, |
18 | extensions::{FieldKind, PathSegmentKind, SelfParamKind, StructKind}, | 18 | extensions::{FieldKind, PathSegmentKind, SelfParamKind, StructKind, TypeBoundKind}, |
19 | generated::*, | 19 | generated::*, |
20 | tokens::*, | 20 | tokens::*, |
21 | traits::*, | 21 | traits::*, |
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs index efe261fc2..e0ea3e5ab 100644 --- a/crates/ra_syntax/src/ast/extensions.rs +++ b/crates/ra_syntax/src/ast/extensions.rs | |||
@@ -382,7 +382,36 @@ impl ast::WherePred { | |||
382 | } | 382 | } |
383 | } | 383 | } |
384 | 384 | ||
385 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||
386 | pub enum TypeBoundKind { | ||
387 | /// Trait | ||
388 | PathType(ast::PathType), | ||
389 | /// for<'a> ... | ||
390 | ForType(ast::ForType), | ||
391 | /// 'a | ||
392 | Lifetime(ast::SyntaxToken), | ||
393 | } | ||
394 | |||
385 | impl ast::TypeBound { | 395 | impl ast::TypeBound { |
396 | pub fn kind(&self) -> TypeBoundKind { | ||
397 | if let Some(path_type) = children(self).next() { | ||
398 | TypeBoundKind::PathType(path_type) | ||
399 | } else if let Some(for_type) = children(self).next() { | ||
400 | TypeBoundKind::ForType(for_type) | ||
401 | } else if let Some(lifetime) = self.lifetime() { | ||
402 | TypeBoundKind::Lifetime(lifetime) | ||
403 | } else { | ||
404 | unreachable!() | ||
405 | } | ||
406 | } | ||
407 | |||
408 | fn lifetime(&self) -> Option<SyntaxToken> { | ||
409 | self.syntax() | ||
410 | .children_with_tokens() | ||
411 | .filter_map(|it| it.into_token()) | ||
412 | .find(|it| it.kind() == LIFETIME) | ||
413 | } | ||
414 | |||
386 | pub fn question_mark_token(&self) -> Option<SyntaxToken> { | 415 | pub fn question_mark_token(&self) -> Option<SyntaxToken> { |
387 | self.syntax() | 416 | self.syntax() |
388 | .children_with_tokens() | 417 | .children_with_tokens() |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.rs b/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.rs index 9e009e24f..2d476278d 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.rs +++ b/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.rs | |||
@@ -5,5 +5,7 @@ fn foo() { | |||
5 | X | Y if Z => (), | 5 | X | Y if Z => (), |
6 | | X | Y if Z => (), | 6 | | X | Y if Z => (), |
7 | | X => (), | 7 | | X => (), |
8 | box X => (), | ||
9 | Some(box X) => (), | ||
8 | }; | 10 | }; |
9 | } | 11 | } |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.txt b/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.txt index 041e7179e..28d501459 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.txt +++ b/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.txt | |||
@@ -1,5 +1,5 @@ | |||
1 | SOURCE_FILE@[0; 167) | 1 | SOURCE_FILE@[0; 215) |
2 | FN_DEF@[0; 166) | 2 | FN_DEF@[0; 214) |
3 | FN_KW@[0; 2) "fn" | 3 | FN_KW@[0; 2) "fn" |
4 | WHITESPACE@[2; 3) " " | 4 | WHITESPACE@[2; 3) " " |
5 | NAME@[3; 6) | 5 | NAME@[3; 6) |
@@ -8,18 +8,18 @@ SOURCE_FILE@[0; 167) | |||
8 | L_PAREN@[6; 7) "(" | 8 | L_PAREN@[6; 7) "(" |
9 | R_PAREN@[7; 8) ")" | 9 | R_PAREN@[7; 8) ")" |
10 | WHITESPACE@[8; 9) " " | 10 | WHITESPACE@[8; 9) " " |
11 | BLOCK@[9; 166) | 11 | BLOCK@[9; 214) |
12 | L_CURLY@[9; 10) "{" | 12 | L_CURLY@[9; 10) "{" |
13 | WHITESPACE@[10; 15) "\n " | 13 | WHITESPACE@[10; 15) "\n " |
14 | EXPR_STMT@[15; 164) | 14 | EXPR_STMT@[15; 212) |
15 | MATCH_EXPR@[15; 163) | 15 | MATCH_EXPR@[15; 211) |
16 | MATCH_KW@[15; 20) "match" | 16 | MATCH_KW@[15; 20) "match" |
17 | WHITESPACE@[20; 21) " " | 17 | WHITESPACE@[20; 21) " " |
18 | TUPLE_EXPR@[21; 23) | 18 | TUPLE_EXPR@[21; 23) |
19 | L_PAREN@[21; 22) "(" | 19 | L_PAREN@[21; 22) "(" |
20 | R_PAREN@[22; 23) ")" | 20 | R_PAREN@[22; 23) ")" |
21 | WHITESPACE@[23; 24) " " | 21 | WHITESPACE@[23; 24) " " |
22 | MATCH_ARM_LIST@[24; 163) | 22 | MATCH_ARM_LIST@[24; 211) |
23 | L_CURLY@[24; 25) "{" | 23 | L_CURLY@[24; 25) "{" |
24 | WHITESPACE@[25; 34) "\n " | 24 | WHITESPACE@[25; 34) "\n " |
25 | MATCH_ARM@[34; 41) | 25 | MATCH_ARM@[34; 41) |
@@ -141,9 +141,44 @@ SOURCE_FILE@[0; 167) | |||
141 | L_PAREN@[154; 155) "(" | 141 | L_PAREN@[154; 155) "(" |
142 | R_PAREN@[155; 156) ")" | 142 | R_PAREN@[155; 156) ")" |
143 | COMMA@[156; 157) "," | 143 | COMMA@[156; 157) "," |
144 | WHITESPACE@[157; 162) "\n " | 144 | WHITESPACE@[157; 166) "\n " |
145 | R_CURLY@[162; 163) "}" | 145 | MATCH_ARM@[166; 177) |
146 | SEMI@[163; 164) ";" | 146 | BIND_PAT@[166; 171) |
147 | WHITESPACE@[164; 165) "\n" | 147 | BOX_KW@[166; 169) "box" |
148 | R_CURLY@[165; 166) "}" | 148 | WHITESPACE@[169; 170) " " |
149 | WHITESPACE@[166; 167) "\n" | 149 | NAME@[170; 171) |
150 | IDENT@[170; 171) "X" | ||
151 | WHITESPACE@[171; 172) " " | ||
152 | FAT_ARROW@[172; 174) "=>" | ||
153 | WHITESPACE@[174; 175) " " | ||
154 | TUPLE_EXPR@[175; 177) | ||
155 | L_PAREN@[175; 176) "(" | ||
156 | R_PAREN@[176; 177) ")" | ||
157 | COMMA@[177; 178) "," | ||
158 | WHITESPACE@[178; 187) "\n " | ||
159 | MATCH_ARM@[187; 204) | ||
160 | TUPLE_STRUCT_PAT@[187; 198) | ||
161 | PATH@[187; 191) | ||
162 | PATH_SEGMENT@[187; 191) | ||
163 | NAME_REF@[187; 191) | ||
164 | IDENT@[187; 191) "Some" | ||
165 | L_PAREN@[191; 192) "(" | ||
166 | BIND_PAT@[192; 197) | ||
167 | BOX_KW@[192; 195) "box" | ||
168 | WHITESPACE@[195; 196) " " | ||
169 | NAME@[196; 197) | ||
170 | IDENT@[196; 197) "X" | ||
171 | R_PAREN@[197; 198) ")" | ||
172 | WHITESPACE@[198; 199) " " | ||
173 | FAT_ARROW@[199; 201) "=>" | ||
174 | WHITESPACE@[201; 202) " " | ||
175 | TUPLE_EXPR@[202; 204) | ||
176 | L_PAREN@[202; 203) "(" | ||
177 | R_PAREN@[203; 204) ")" | ||
178 | COMMA@[204; 205) "," | ||
179 | WHITESPACE@[205; 210) "\n " | ||
180 | R_CURLY@[210; 211) "}" | ||
181 | SEMI@[211; 212) ";" | ||
182 | WHITESPACE@[212; 213) "\n" | ||
183 | R_CURLY@[213; 214) "}" | ||
184 | WHITESPACE@[214; 215) "\n" | ||