aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src')
-rw-r--r--crates/ra_hir_def/src/body/lower.rs27
-rw-r--r--crates/ra_hir_def/src/data.rs8
-rw-r--r--crates/ra_hir_def/src/expr.rs6
-rw-r--r--crates/ra_hir_def/src/path.rs21
-rw-r--r--crates/ra_hir_def/src/path/lower.rs21
-rw-r--r--crates/ra_hir_def/src/type_ref.rs12
6 files changed, 76 insertions, 19 deletions
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
35use super::{ExprSource, PatSource}; 35use super::{ExprSource, PatSource};
36use ast::AstChildren;
36 37
37pub(super) fn lower( 38pub(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
684impl From<ast::BinOp> for BinaryOp { 701impl 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::{
15use crate::{ 15use 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 {
374pub enum Pat { 374pub 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::{
14use ra_db::CrateId; 14use ra_db::CrateId;
15use ra_syntax::ast; 15use ra_syntax::ast;
16 16
17use crate::{type_ref::TypeRef, InFile}; 17use 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)]
20pub struct ModPath { 23pub 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)]
122pub 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};
12use ra_syntax::ast::{self, AstNode, TypeAscriptionOwner}; 12use ra_syntax::ast::{self, AstNode, TypeAscriptionOwner, TypeBoundsOwner};
13 13
14use super::AssociatedTypeBinding;
14use crate::{ 15use 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
19pub(super) use lower_use::lower_use_tree; 20pub(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 }