diff options
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r-- | crates/ra_hir_def/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/ra_hir_def/src/body/lower.rs | 27 | ||||
-rw-r--r-- | crates/ra_hir_def/src/data.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir_def/src/expr.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir_def/src/path.rs | 21 | ||||
-rw-r--r-- | crates/ra_hir_def/src/path/lower.rs | 21 | ||||
-rw-r--r-- | crates/ra_hir_def/src/type_ref.rs | 12 |
7 files changed, 77 insertions, 20 deletions
diff --git a/crates/ra_hir_def/Cargo.toml b/crates/ra_hir_def/Cargo.toml index 56e791e3e..b85358308 100644 --- a/crates/ra_hir_def/Cargo.toml +++ b/crates/ra_hir_def/Cargo.toml | |||
@@ -28,4 +28,4 @@ ra_cfg = { path = "../ra_cfg" } | |||
28 | tt = { path = "../ra_tt", package = "ra_tt" } | 28 | tt = { path = "../ra_tt", package = "ra_tt" } |
29 | 29 | ||
30 | [dev-dependencies] | 30 | [dev-dependencies] |
31 | insta = "0.15.0" | 31 | insta = "0.16.0" |
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 6caa87db4..79abe55ce 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -33,6 +33,7 @@ use crate::{ | |||
33 | }; | 33 | }; |
34 | 34 | ||
35 | use super::{ExprSource, PatSource}; | 35 | use super::{ExprSource, PatSource}; |
36 | use ast::AstChildren; | ||
36 | 37 | ||
37 | pub(super) fn lower( | 38 | pub(super) fn lower( |
38 | db: &dyn DefDatabase, | 39 | db: &dyn DefDatabase, |
@@ -598,8 +599,8 @@ impl ExprCollector<'_> { | |||
598 | } | 599 | } |
599 | ast::Pat::TupleStructPat(p) => { | 600 | ast::Pat::TupleStructPat(p) => { |
600 | let path = p.path().and_then(|path| self.expander.parse_path(path)); | 601 | let path = p.path().and_then(|path| self.expander.parse_path(path)); |
601 | let args = p.args().map(|p| self.collect_pat(p)).collect(); | 602 | let (args, ellipsis) = self.collect_tuple_pat(p.args()); |
602 | Pat::TupleStruct { path, args } | 603 | Pat::TupleStruct { path, args, ellipsis } |
603 | } | 604 | } |
604 | ast::Pat::RefPat(p) => { | 605 | ast::Pat::RefPat(p) => { |
605 | let pat = self.collect_pat_opt(p.pat()); | 606 | let pat = self.collect_pat_opt(p.pat()); |
@@ -616,10 +617,10 @@ impl ExprCollector<'_> { | |||
616 | } | 617 | } |
617 | ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat()), | 618 | ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat()), |
618 | ast::Pat::TuplePat(p) => { | 619 | ast::Pat::TuplePat(p) => { |
619 | let args = p.args().map(|p| self.collect_pat(p)).collect(); | 620 | let (args, ellipsis) = self.collect_tuple_pat(p.args()); |
620 | Pat::Tuple(args) | 621 | Pat::Tuple { args, ellipsis } |
621 | } | 622 | } |
622 | ast::Pat::PlaceholderPat(_) | ast::Pat::DotDotPat(_) => Pat::Wild, | 623 | ast::Pat::PlaceholderPat(_) => Pat::Wild, |
623 | ast::Pat::RecordPat(p) => { | 624 | ast::Pat::RecordPat(p) => { |
624 | let path = p.path().and_then(|path| self.expander.parse_path(path)); | 625 | let path = p.path().and_then(|path| self.expander.parse_path(path)); |
625 | let record_field_pat_list = | 626 | let record_field_pat_list = |
@@ -665,6 +666,9 @@ impl ExprCollector<'_> { | |||
665 | Pat::Missing | 666 | Pat::Missing |
666 | } | 667 | } |
667 | } | 668 | } |
669 | ast::Pat::DotDotPat(_) => unreachable!( | ||
670 | "`DotDotPat` requires special handling and should not be mapped to a Pat." | ||
671 | ), | ||
668 | // FIXME: implement | 672 | // FIXME: implement |
669 | ast::Pat::BoxPat(_) | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing, | 673 | ast::Pat::BoxPat(_) | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing, |
670 | }; | 674 | }; |
@@ -679,6 +683,19 @@ impl ExprCollector<'_> { | |||
679 | self.missing_pat() | 683 | self.missing_pat() |
680 | } | 684 | } |
681 | } | 685 | } |
686 | |||
687 | fn collect_tuple_pat(&mut self, args: AstChildren<ast::Pat>) -> (Vec<PatId>, Option<usize>) { | ||
688 | // Find the location of the `..`, if there is one. Note that we do not | ||
689 | // consider the possiblity of there being multiple `..` here. | ||
690 | let ellipsis = args.clone().position(|p| matches!(p, ast::Pat::DotDotPat(_))); | ||
691 | // We want to skip the `..` pattern here, since we account for it above. | ||
692 | let args = args | ||
693 | .filter(|p| !matches!(p, ast::Pat::DotDotPat(_))) | ||
694 | .map(|p| self.collect_pat(p)) | ||
695 | .collect(); | ||
696 | |||
697 | (args, ellipsis) | ||
698 | } | ||
682 | } | 699 | } |
683 | 700 | ||
684 | impl From<ast::BinOp> for BinaryOp { | 701 | impl From<ast::BinOp> for BinaryOp { |
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index 56a20c5bd..b3c91fea2 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs | |||
@@ -15,7 +15,7 @@ use ra_syntax::ast::{ | |||
15 | use crate::{ | 15 | use crate::{ |
16 | attr::Attrs, | 16 | attr::Attrs, |
17 | db::DefDatabase, | 17 | db::DefDatabase, |
18 | path::{path, GenericArgs, Path}, | 18 | path::{path, AssociatedTypeBinding, GenericArgs, Path}, |
19 | src::HasSource, | 19 | src::HasSource, |
20 | type_ref::{Mutability, TypeBound, TypeRef}, | 20 | type_ref::{Mutability, TypeBound, TypeRef}, |
21 | visibility::RawVisibility, | 21 | visibility::RawVisibility, |
@@ -95,7 +95,11 @@ fn desugar_future_path(orig: TypeRef) -> Path { | |||
95 | let path = path![std::future::Future]; | 95 | let path = path![std::future::Future]; |
96 | let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments.len() - 1).collect(); | 96 | let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments.len() - 1).collect(); |
97 | let mut last = GenericArgs::empty(); | 97 | let mut last = GenericArgs::empty(); |
98 | last.bindings.push((name![Output], orig)); | 98 | last.bindings.push(AssociatedTypeBinding { |
99 | name: name![Output], | ||
100 | type_ref: Some(orig), | ||
101 | bounds: Vec::new(), | ||
102 | }); | ||
99 | generic_args.push(Some(Arc::new(last))); | 103 | generic_args.push(Some(Arc::new(last))); |
100 | 104 | ||
101 | Path::from_known_path(path, generic_args) | 105 | Path::from_known_path(path, generic_args) |
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs index e11bdf3ec..a0cdad529 100644 --- a/crates/ra_hir_def/src/expr.rs +++ b/crates/ra_hir_def/src/expr.rs | |||
@@ -374,7 +374,7 @@ pub struct RecordFieldPat { | |||
374 | pub enum Pat { | 374 | pub enum Pat { |
375 | Missing, | 375 | Missing, |
376 | Wild, | 376 | Wild, |
377 | Tuple(Vec<PatId>), | 377 | Tuple { args: Vec<PatId>, ellipsis: Option<usize> }, |
378 | Or(Vec<PatId>), | 378 | Or(Vec<PatId>), |
379 | Record { path: Option<Path>, args: Vec<RecordFieldPat>, ellipsis: bool }, | 379 | Record { path: Option<Path>, args: Vec<RecordFieldPat>, ellipsis: bool }, |
380 | Range { start: ExprId, end: ExprId }, | 380 | Range { start: ExprId, end: ExprId }, |
@@ -382,7 +382,7 @@ pub enum Pat { | |||
382 | Path(Path), | 382 | Path(Path), |
383 | Lit(ExprId), | 383 | Lit(ExprId), |
384 | Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> }, | 384 | Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> }, |
385 | TupleStruct { path: Option<Path>, args: Vec<PatId> }, | 385 | TupleStruct { path: Option<Path>, args: Vec<PatId>, ellipsis: Option<usize> }, |
386 | Ref { pat: PatId, mutability: Mutability }, | 386 | Ref { pat: PatId, mutability: Mutability }, |
387 | } | 387 | } |
388 | 388 | ||
@@ -393,7 +393,7 @@ impl Pat { | |||
393 | Pat::Bind { subpat, .. } => { | 393 | Pat::Bind { subpat, .. } => { |
394 | subpat.iter().copied().for_each(f); | 394 | subpat.iter().copied().for_each(f); |
395 | } | 395 | } |
396 | Pat::Or(args) | Pat::Tuple(args) | Pat::TupleStruct { args, .. } => { | 396 | Pat::Or(args) | Pat::Tuple { args, .. } | Pat::TupleStruct { args, .. } => { |
397 | args.iter().copied().for_each(f); | 397 | args.iter().copied().for_each(f); |
398 | } | 398 | } |
399 | Pat::Ref { pat, .. } => f(*pat), | 399 | Pat::Ref { pat, .. } => f(*pat), |
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 91c7b3e09..162b3c8c7 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs | |||
@@ -14,7 +14,10 @@ use hir_expand::{ | |||
14 | use ra_db::CrateId; | 14 | use ra_db::CrateId; |
15 | use ra_syntax::ast; | 15 | use ra_syntax::ast; |
16 | 16 | ||
17 | use crate::{type_ref::TypeRef, InFile}; | 17 | use crate::{ |
18 | type_ref::{TypeBound, TypeRef}, | ||
19 | InFile, | ||
20 | }; | ||
18 | 21 | ||
19 | #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] | 22 | #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] |
20 | pub struct ModPath { | 23 | pub struct ModPath { |
@@ -111,7 +114,21 @@ pub struct GenericArgs { | |||
111 | /// is left out. | 114 | /// is left out. |
112 | pub has_self_type: bool, | 115 | pub has_self_type: bool, |
113 | /// Associated type bindings like in `Iterator<Item = T>`. | 116 | /// Associated type bindings like in `Iterator<Item = T>`. |
114 | pub bindings: Vec<(Name, TypeRef)>, | 117 | pub bindings: Vec<AssociatedTypeBinding>, |
118 | } | ||
119 | |||
120 | /// An associated type binding like in `Iterator<Item = T>`. | ||
121 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
122 | pub struct AssociatedTypeBinding { | ||
123 | /// The name of the associated type. | ||
124 | pub name: Name, | ||
125 | /// The type bound to this associated type (in `Item = T`, this would be the | ||
126 | /// `T`). This can be `None` if there are bounds instead. | ||
127 | pub type_ref: Option<TypeRef>, | ||
128 | /// Bounds for the associated type, like in `Iterator<Item: | ||
129 | /// SomeOtherTrait>`. (This is the unstable `associated_type_bounds` | ||
130 | /// feature.) | ||
131 | pub bounds: Vec<TypeBound>, | ||
115 | } | 132 | } |
116 | 133 | ||
117 | /// A single generic argument. | 134 | /// A single generic argument. |
diff --git a/crates/ra_hir_def/src/path/lower.rs b/crates/ra_hir_def/src/path/lower.rs index 0f806d6fb..9ec2e0dcd 100644 --- a/crates/ra_hir_def/src/path/lower.rs +++ b/crates/ra_hir_def/src/path/lower.rs | |||
@@ -9,11 +9,12 @@ use hir_expand::{ | |||
9 | hygiene::Hygiene, | 9 | hygiene::Hygiene, |
10 | name::{name, AsName}, | 10 | name::{name, AsName}, |
11 | }; | 11 | }; |
12 | use ra_syntax::ast::{self, AstNode, TypeAscriptionOwner}; | 12 | use ra_syntax::ast::{self, AstNode, TypeAscriptionOwner, TypeBoundsOwner}; |
13 | 13 | ||
14 | use super::AssociatedTypeBinding; | ||
14 | use crate::{ | 15 | use crate::{ |
15 | path::{GenericArg, GenericArgs, ModPath, Path, PathKind}, | 16 | path::{GenericArg, GenericArgs, ModPath, Path, PathKind}, |
16 | type_ref::TypeRef, | 17 | type_ref::{TypeBound, TypeRef}, |
17 | }; | 18 | }; |
18 | 19 | ||
19 | pub(super) use lower_use::lower_use_tree; | 20 | pub(super) use lower_use::lower_use_tree; |
@@ -136,10 +137,16 @@ pub(super) fn lower_generic_args(node: ast::TypeArgList) -> Option<GenericArgs> | |||
136 | // lifetimes ignored for now | 137 | // lifetimes ignored for now |
137 | let mut bindings = Vec::new(); | 138 | let mut bindings = Vec::new(); |
138 | for assoc_type_arg in node.assoc_type_args() { | 139 | for assoc_type_arg in node.assoc_type_args() { |
140 | let assoc_type_arg: ast::AssocTypeArg = assoc_type_arg; | ||
139 | if let Some(name_ref) = assoc_type_arg.name_ref() { | 141 | if let Some(name_ref) = assoc_type_arg.name_ref() { |
140 | let name = name_ref.as_name(); | 142 | let name = name_ref.as_name(); |
141 | let type_ref = TypeRef::from_ast_opt(assoc_type_arg.type_ref()); | 143 | let type_ref = assoc_type_arg.type_ref().map(TypeRef::from_ast); |
142 | bindings.push((name, type_ref)); | 144 | let bounds = if let Some(l) = assoc_type_arg.type_bound_list() { |
145 | l.bounds().map(TypeBound::from_ast).collect() | ||
146 | } else { | ||
147 | Vec::new() | ||
148 | }; | ||
149 | bindings.push(AssociatedTypeBinding { name, type_ref, bounds }); | ||
143 | } | 150 | } |
144 | } | 151 | } |
145 | if args.is_empty() && bindings.is_empty() { | 152 | if args.is_empty() && bindings.is_empty() { |
@@ -168,7 +175,11 @@ fn lower_generic_args_from_fn_path( | |||
168 | } | 175 | } |
169 | if let Some(ret_type) = ret_type { | 176 | if let Some(ret_type) = ret_type { |
170 | let type_ref = TypeRef::from_ast_opt(ret_type.type_ref()); | 177 | let type_ref = TypeRef::from_ast_opt(ret_type.type_ref()); |
171 | bindings.push((name![Output], type_ref)) | 178 | bindings.push(AssociatedTypeBinding { |
179 | name: name![Output], | ||
180 | type_ref: Some(type_ref), | ||
181 | bounds: Vec::new(), | ||
182 | }); | ||
172 | } | 183 | } |
173 | if args.is_empty() && bindings.is_empty() { | 184 | if args.is_empty() && bindings.is_empty() { |
174 | None | 185 | None |
diff --git a/crates/ra_hir_def/src/type_ref.rs b/crates/ra_hir_def/src/type_ref.rs index ea29c4176..f308c6bdf 100644 --- a/crates/ra_hir_def/src/type_ref.rs +++ b/crates/ra_hir_def/src/type_ref.rs | |||
@@ -163,8 +163,16 @@ impl TypeRef { | |||
163 | let crate::path::GenericArg::Type(type_ref) = arg; | 163 | let crate::path::GenericArg::Type(type_ref) = arg; |
164 | go(type_ref, f); | 164 | go(type_ref, f); |
165 | } | 165 | } |
166 | for (_, type_ref) in &args_and_bindings.bindings { | 166 | for binding in &args_and_bindings.bindings { |
167 | go(type_ref, f); | 167 | if let Some(type_ref) = &binding.type_ref { |
168 | go(type_ref, f); | ||
169 | } | ||
170 | for bound in &binding.bounds { | ||
171 | match bound { | ||
172 | TypeBound::Path(path) => go_path(path, f), | ||
173 | TypeBound::Error => (), | ||
174 | } | ||
175 | } | ||
168 | } | 176 | } |
169 | } | 177 | } |
170 | } | 178 | } |