aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/path/lower.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src/path/lower.rs')
-rw-r--r--crates/ra_hir_def/src/path/lower.rs23
1 files changed, 15 insertions, 8 deletions
diff --git a/crates/ra_hir_def/src/path/lower.rs b/crates/ra_hir_def/src/path/lower.rs
index b902cacd1..6a0c019fd 100644
--- a/crates/ra_hir_def/src/path/lower.rs
+++ b/crates/ra_hir_def/src/path/lower.rs
@@ -13,6 +13,7 @@ use ra_syntax::ast::{self, AstNode, TypeAscriptionOwner, TypeBoundsOwner};
13 13
14use super::AssociatedTypeBinding; 14use super::AssociatedTypeBinding;
15use crate::{ 15use crate::{
16 body::LowerCtx,
16 path::{GenericArg, GenericArgs, ModPath, Path, PathKind}, 17 path::{GenericArg, GenericArgs, ModPath, Path, PathKind},
17 type_ref::{TypeBound, TypeRef}, 18 type_ref::{TypeBound, TypeRef},
18}; 19};
@@ -26,6 +27,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
26 let mut type_anchor = None; 27 let mut type_anchor = None;
27 let mut segments = Vec::new(); 28 let mut segments = Vec::new();
28 let mut generic_args = Vec::new(); 29 let mut generic_args = Vec::new();
30 let ctx = LowerCtx::with_hygiene(hygiene);
29 loop { 31 loop {
30 let segment = path.segment()?; 32 let segment = path.segment()?;
31 33
@@ -40,9 +42,10 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
40 Either::Left(name) => { 42 Either::Left(name) => {
41 let args = segment 43 let args = segment
42 .type_arg_list() 44 .type_arg_list()
43 .and_then(lower_generic_args) 45 .and_then(|it| lower_generic_args(&ctx, it))
44 .or_else(|| { 46 .or_else(|| {
45 lower_generic_args_from_fn_path( 47 lower_generic_args_from_fn_path(
48 &ctx,
46 segment.param_list(), 49 segment.param_list(),
47 segment.ret_type(), 50 segment.ret_type(),
48 ) 51 )
@@ -60,7 +63,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
60 ast::PathSegmentKind::Type { type_ref, trait_ref } => { 63 ast::PathSegmentKind::Type { type_ref, trait_ref } => {
61 assert!(path.qualifier().is_none()); // this can only occur at the first segment 64 assert!(path.qualifier().is_none()); // this can only occur at the first segment
62 65
63 let self_type = TypeRef::from_ast(type_ref?); 66 let self_type = TypeRef::from_ast(&ctx, type_ref?);
64 67
65 match trait_ref { 68 match trait_ref {
66 // <T>::foo 69 // <T>::foo
@@ -143,10 +146,13 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
143 } 146 }
144} 147}
145 148
146pub(super) fn lower_generic_args(node: ast::TypeArgList) -> Option<GenericArgs> { 149pub(super) fn lower_generic_args(
150 lower_ctx: &LowerCtx,
151 node: ast::TypeArgList,
152) -> Option<GenericArgs> {
147 let mut args = Vec::new(); 153 let mut args = Vec::new();
148 for type_arg in node.type_args() { 154 for type_arg in node.type_args() {
149 let type_ref = TypeRef::from_ast_opt(type_arg.type_ref()); 155 let type_ref = TypeRef::from_ast_opt(lower_ctx, type_arg.type_ref());
150 args.push(GenericArg::Type(type_ref)); 156 args.push(GenericArg::Type(type_ref));
151 } 157 }
152 // lifetimes ignored for now 158 // lifetimes ignored for now
@@ -155,9 +161,9 @@ pub(super) fn lower_generic_args(node: ast::TypeArgList) -> Option<GenericArgs>
155 let assoc_type_arg: ast::AssocTypeArg = assoc_type_arg; 161 let assoc_type_arg: ast::AssocTypeArg = assoc_type_arg;
156 if let Some(name_ref) = assoc_type_arg.name_ref() { 162 if let Some(name_ref) = assoc_type_arg.name_ref() {
157 let name = name_ref.as_name(); 163 let name = name_ref.as_name();
158 let type_ref = assoc_type_arg.type_ref().map(TypeRef::from_ast); 164 let type_ref = assoc_type_arg.type_ref().map(|it| TypeRef::from_ast(lower_ctx, it));
159 let bounds = if let Some(l) = assoc_type_arg.type_bound_list() { 165 let bounds = if let Some(l) = assoc_type_arg.type_bound_list() {
160 l.bounds().map(TypeBound::from_ast).collect() 166 l.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect()
161 } else { 167 } else {
162 Vec::new() 168 Vec::new()
163 }; 169 };
@@ -174,6 +180,7 @@ pub(super) fn lower_generic_args(node: ast::TypeArgList) -> Option<GenericArgs>
174/// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y) 180/// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y)
175/// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`). 181/// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`).
176fn lower_generic_args_from_fn_path( 182fn lower_generic_args_from_fn_path(
183 ctx: &LowerCtx,
177 params: Option<ast::ParamList>, 184 params: Option<ast::ParamList>,
178 ret_type: Option<ast::RetType>, 185 ret_type: Option<ast::RetType>,
179) -> Option<GenericArgs> { 186) -> Option<GenericArgs> {
@@ -182,14 +189,14 @@ fn lower_generic_args_from_fn_path(
182 if let Some(params) = params { 189 if let Some(params) = params {
183 let mut param_types = Vec::new(); 190 let mut param_types = Vec::new();
184 for param in params.params() { 191 for param in params.params() {
185 let type_ref = TypeRef::from_ast_opt(param.ascribed_type()); 192 let type_ref = TypeRef::from_ast_opt(&ctx, param.ascribed_type());
186 param_types.push(type_ref); 193 param_types.push(type_ref);
187 } 194 }
188 let arg = GenericArg::Type(TypeRef::Tuple(param_types)); 195 let arg = GenericArg::Type(TypeRef::Tuple(param_types));
189 args.push(arg); 196 args.push(arg);
190 } 197 }
191 if let Some(ret_type) = ret_type { 198 if let Some(ret_type) = ret_type {
192 let type_ref = TypeRef::from_ast_opt(ret_type.type_ref()); 199 let type_ref = TypeRef::from_ast_opt(&ctx, ret_type.type_ref());
193 bindings.push(AssociatedTypeBinding { 200 bindings.push(AssociatedTypeBinding {
194 name: name![Output], 201 name: name![Output],
195 type_ref: Some(type_ref), 202 type_ref: Some(type_ref),