diff options
Diffstat (limited to 'crates')
63 files changed, 2053 insertions, 1189 deletions
diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs index 81f999090..5aab5fb8b 100644 --- a/crates/ra_assists/src/assist_ctx.rs +++ b/crates/ra_assists/src/assist_ctx.rs | |||
@@ -1,5 +1,4 @@ | |||
1 | //! This module defines `AssistCtx` -- the API surface that is exposed to assists. | 1 | //! This module defines `AssistCtx` -- the API surface that is exposed to assists. |
2 | use either::Either; | ||
3 | use hir::{InFile, SourceAnalyzer, SourceBinder}; | 2 | use hir::{InFile, SourceAnalyzer, SourceBinder}; |
4 | use ra_db::{FileRange, SourceDatabase}; | 3 | use ra_db::{FileRange, SourceDatabase}; |
5 | use ra_fmt::{leading_indent, reindent}; | 4 | use ra_fmt::{leading_indent, reindent}; |
@@ -11,12 +10,36 @@ use ra_syntax::{ | |||
11 | }; | 10 | }; |
12 | use ra_text_edit::TextEditBuilder; | 11 | use ra_text_edit::TextEditBuilder; |
13 | 12 | ||
14 | use crate::{AssistAction, AssistId, AssistLabel, ResolvedAssist}; | 13 | use crate::{AssistAction, AssistId, AssistLabel, GroupLabel, ResolvedAssist}; |
15 | 14 | ||
16 | #[derive(Clone, Debug)] | 15 | #[derive(Clone, Debug)] |
17 | pub(crate) enum Assist { | 16 | pub(crate) struct Assist(pub(crate) Vec<AssistInfo>); |
18 | Unresolved { label: AssistLabel }, | 17 | |
19 | Resolved { assist: ResolvedAssist }, | 18 | #[derive(Clone, Debug)] |
19 | pub(crate) struct AssistInfo { | ||
20 | pub(crate) label: AssistLabel, | ||
21 | pub(crate) group_label: Option<GroupLabel>, | ||
22 | pub(crate) action: Option<AssistAction>, | ||
23 | } | ||
24 | |||
25 | impl AssistInfo { | ||
26 | fn new(label: AssistLabel) -> AssistInfo { | ||
27 | AssistInfo { label, group_label: None, action: None } | ||
28 | } | ||
29 | |||
30 | fn resolved(self, action: AssistAction) -> AssistInfo { | ||
31 | AssistInfo { action: Some(action), ..self } | ||
32 | } | ||
33 | |||
34 | fn with_group(self, group_label: GroupLabel) -> AssistInfo { | ||
35 | AssistInfo { group_label: Some(group_label), ..self } | ||
36 | } | ||
37 | |||
38 | pub(crate) fn into_resolved(self) -> Option<ResolvedAssist> { | ||
39 | let label = self.label; | ||
40 | let group_label = self.group_label; | ||
41 | self.action.map(|action| ResolvedAssist { label, group_label, action }) | ||
42 | } | ||
20 | } | 43 | } |
21 | 44 | ||
22 | pub(crate) type AssistHandler = fn(AssistCtx) -> Option<Assist>; | 45 | pub(crate) type AssistHandler = fn(AssistCtx) -> Option<Assist>; |
@@ -84,44 +107,21 @@ impl<'a> AssistCtx<'a> { | |||
84 | ) -> Option<Assist> { | 107 | ) -> Option<Assist> { |
85 | let label = AssistLabel::new(label.into(), id); | 108 | let label = AssistLabel::new(label.into(), id); |
86 | 109 | ||
87 | let assist = if self.should_compute_edit { | 110 | let mut info = AssistInfo::new(label); |
111 | if self.should_compute_edit { | ||
88 | let action = { | 112 | let action = { |
89 | let mut edit = ActionBuilder::default(); | 113 | let mut edit = ActionBuilder::default(); |
90 | f(&mut edit); | 114 | f(&mut edit); |
91 | edit.build() | 115 | edit.build() |
92 | }; | 116 | }; |
93 | Assist::Resolved { assist: ResolvedAssist { label, action_data: Either::Left(action) } } | 117 | info = info.resolved(action) |
94 | } else { | ||
95 | Assist::Unresolved { label } | ||
96 | }; | 118 | }; |
97 | 119 | ||
98 | Some(assist) | 120 | Some(Assist(vec![info])) |
99 | } | 121 | } |
100 | 122 | ||
101 | pub(crate) fn add_assist_group( | 123 | pub(crate) fn add_assist_group(self, group_name: impl Into<String>) -> AssistGroup<'a> { |
102 | self, | 124 | AssistGroup { ctx: self, group_name: group_name.into(), assists: Vec::new() } |
103 | id: AssistId, | ||
104 | label: impl Into<String>, | ||
105 | f: impl FnOnce() -> Vec<ActionBuilder>, | ||
106 | ) -> Option<Assist> { | ||
107 | let label = AssistLabel::new(label.into(), id); | ||
108 | let assist = if self.should_compute_edit { | ||
109 | let actions = f(); | ||
110 | assert!(!actions.is_empty(), "Assist cannot have no"); | ||
111 | |||
112 | Assist::Resolved { | ||
113 | assist: ResolvedAssist { | ||
114 | label, | ||
115 | action_data: Either::Right( | ||
116 | actions.into_iter().map(ActionBuilder::build).collect(), | ||
117 | ), | ||
118 | }, | ||
119 | } | ||
120 | } else { | ||
121 | Assist::Unresolved { label } | ||
122 | }; | ||
123 | |||
124 | Some(assist) | ||
125 | } | 125 | } |
126 | 126 | ||
127 | pub(crate) fn token_at_offset(&self) -> TokenAtOffset<SyntaxToken> { | 127 | pub(crate) fn token_at_offset(&self) -> TokenAtOffset<SyntaxToken> { |
@@ -155,20 +155,48 @@ impl<'a> AssistCtx<'a> { | |||
155 | } | 155 | } |
156 | } | 156 | } |
157 | 157 | ||
158 | pub(crate) struct AssistGroup<'a> { | ||
159 | ctx: AssistCtx<'a>, | ||
160 | group_name: String, | ||
161 | assists: Vec<AssistInfo>, | ||
162 | } | ||
163 | |||
164 | impl<'a> AssistGroup<'a> { | ||
165 | pub(crate) fn add_assist( | ||
166 | &mut self, | ||
167 | id: AssistId, | ||
168 | label: impl Into<String>, | ||
169 | f: impl FnOnce(&mut ActionBuilder), | ||
170 | ) { | ||
171 | let label = AssistLabel::new(label.into(), id); | ||
172 | |||
173 | let mut info = AssistInfo::new(label).with_group(GroupLabel(self.group_name.clone())); | ||
174 | if self.ctx.should_compute_edit { | ||
175 | let action = { | ||
176 | let mut edit = ActionBuilder::default(); | ||
177 | f(&mut edit); | ||
178 | edit.build() | ||
179 | }; | ||
180 | info = info.resolved(action) | ||
181 | }; | ||
182 | |||
183 | self.assists.push(info) | ||
184 | } | ||
185 | |||
186 | pub(crate) fn finish(self) -> Option<Assist> { | ||
187 | assert!(!self.assists.is_empty()); | ||
188 | Some(Assist(self.assists)) | ||
189 | } | ||
190 | } | ||
191 | |||
158 | #[derive(Default)] | 192 | #[derive(Default)] |
159 | pub(crate) struct ActionBuilder { | 193 | pub(crate) struct ActionBuilder { |
160 | edit: TextEditBuilder, | 194 | edit: TextEditBuilder, |
161 | cursor_position: Option<TextUnit>, | 195 | cursor_position: Option<TextUnit>, |
162 | target: Option<TextRange>, | 196 | target: Option<TextRange>, |
163 | label: Option<String>, | ||
164 | } | 197 | } |
165 | 198 | ||
166 | impl ActionBuilder { | 199 | impl ActionBuilder { |
167 | /// Adds a custom label to the action, if it needs to be different from the assist label | ||
168 | pub(crate) fn label(&mut self, label: impl Into<String>) { | ||
169 | self.label = Some(label.into()) | ||
170 | } | ||
171 | |||
172 | /// Replaces specified `range` of text with a given string. | 200 | /// Replaces specified `range` of text with a given string. |
173 | pub(crate) fn replace(&mut self, range: TextRange, replace_with: impl Into<String>) { | 201 | pub(crate) fn replace(&mut self, range: TextRange, replace_with: impl Into<String>) { |
174 | self.edit.replace(range, replace_with.into()) | 202 | self.edit.replace(range, replace_with.into()) |
@@ -227,7 +255,6 @@ impl ActionBuilder { | |||
227 | edit: self.edit.finish(), | 255 | edit: self.edit.finish(), |
228 | cursor_position: self.cursor_position, | 256 | cursor_position: self.cursor_position, |
229 | target: self.target, | 257 | target: self.target, |
230 | label: self.label, | ||
231 | } | 258 | } |
232 | } | 259 | } |
233 | } | 260 | } |
diff --git a/crates/ra_assists/src/doc_tests.rs b/crates/ra_assists/src/doc_tests.rs index ae0e5605c..c0f9bc1fb 100644 --- a/crates/ra_assists/src/doc_tests.rs +++ b/crates/ra_assists/src/doc_tests.rs | |||
@@ -30,6 +30,6 @@ fn check(assist_id: &str, before: &str, after: &str) { | |||
30 | ) | 30 | ) |
31 | }); | 31 | }); |
32 | 32 | ||
33 | let actual = assist.get_first_action().edit.apply(&before); | 33 | let actual = assist.action.edit.apply(&before); |
34 | assert_eq_text!(after, &actual); | 34 | assert_eq_text!(after, &actual); |
35 | } | 35 | } |
diff --git a/crates/ra_assists/src/doc_tests/generated.rs b/crates/ra_assists/src/doc_tests/generated.rs index 0d95b957b..4ab09b167 100644 --- a/crates/ra_assists/src/doc_tests/generated.rs +++ b/crates/ra_assists/src/doc_tests/generated.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | //! Generated file, do not edit by hand, see `crate/ra_tools/src/codegen` | 1 | //! Generated file, do not edit by hand, see `xtask/src/codegen` |
2 | 2 | ||
3 | use super::check; | 3 | use super::check; |
4 | 4 | ||
@@ -161,21 +161,6 @@ impl Trait<u32> for () { | |||
161 | } | 161 | } |
162 | 162 | ||
163 | #[test] | 163 | #[test] |
164 | fn doctest_add_import() { | ||
165 | check( | ||
166 | "add_import", | ||
167 | r#####" | ||
168 | fn process(map: std::collections::<|>HashMap<String, String>) {} | ||
169 | "#####, | ||
170 | r#####" | ||
171 | use std::collections::HashMap; | ||
172 | |||
173 | fn process(map: HashMap<String, String>) {} | ||
174 | "#####, | ||
175 | ) | ||
176 | } | ||
177 | |||
178 | #[test] | ||
179 | fn doctest_add_new() { | 164 | fn doctest_add_new() { |
180 | check( | 165 | check( |
181 | "add_new", | 166 | "add_new", |
@@ -592,6 +577,21 @@ fn handle(action: Action) { | |||
592 | } | 577 | } |
593 | 578 | ||
594 | #[test] | 579 | #[test] |
580 | fn doctest_replace_qualified_name_with_use() { | ||
581 | check( | ||
582 | "replace_qualified_name_with_use", | ||
583 | r#####" | ||
584 | fn process(map: std::collections::<|>HashMap<String, String>) {} | ||
585 | "#####, | ||
586 | r#####" | ||
587 | use std::collections::HashMap; | ||
588 | |||
589 | fn process(map: HashMap<String, String>) {} | ||
590 | "#####, | ||
591 | ) | ||
592 | } | ||
593 | |||
594 | #[test] | ||
595 | fn doctest_split_import() { | 595 | fn doctest_split_import() { |
596 | check( | 596 | check( |
597 | "split_import", | 597 | "split_import", |
diff --git a/crates/ra_assists/src/handlers/add_new.rs b/crates/ra_assists/src/handlers/add_new.rs index a08639311..2701eddb8 100644 --- a/crates/ra_assists/src/handlers/add_new.rs +++ b/crates/ra_assists/src/handlers/add_new.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use format_buf::format; | 1 | use format_buf::format; |
2 | use hir::InFile; | 2 | use hir::{Adt, InFile}; |
3 | use join_to_string::join; | 3 | use join_to_string::join; |
4 | use ra_syntax::{ | 4 | use ra_syntax::{ |
5 | ast::{ | 5 | ast::{ |
@@ -135,16 +135,22 @@ fn find_struct_impl(ctx: &AssistCtx, strukt: &ast::StructDef) -> Option<Option<a | |||
135 | })?; | 135 | })?; |
136 | let mut sb = ctx.source_binder(); | 136 | let mut sb = ctx.source_binder(); |
137 | 137 | ||
138 | let struct_ty = { | 138 | let struct_def = { |
139 | let src = InFile { file_id: ctx.frange.file_id.into(), value: strukt.clone() }; | 139 | let src = InFile { file_id: ctx.frange.file_id.into(), value: strukt.clone() }; |
140 | sb.to_def(src)?.ty(db) | 140 | sb.to_def(src)? |
141 | }; | 141 | }; |
142 | 142 | ||
143 | let block = module.descendants().filter_map(ast::ImplBlock::cast).find_map(|impl_blk| { | 143 | let block = module.descendants().filter_map(ast::ImplBlock::cast).find_map(|impl_blk| { |
144 | let src = InFile { file_id: ctx.frange.file_id.into(), value: impl_blk.clone() }; | 144 | let src = InFile { file_id: ctx.frange.file_id.into(), value: impl_blk.clone() }; |
145 | let blk = sb.to_def(src)?; | 145 | let blk = sb.to_def(src)?; |
146 | 146 | ||
147 | let same_ty = blk.target_ty(db) == struct_ty; | 147 | // FIXME: handle e.g. `struct S<T>; impl<U> S<U> {}` |
148 | // (we currently use the wrong type parameter) | ||
149 | // also we wouldn't want to use e.g. `impl S<u32>` | ||
150 | let same_ty = match blk.target_ty(db).as_adt() { | ||
151 | Some(def) => def == Adt::Struct(struct_def), | ||
152 | None => false, | ||
153 | }; | ||
148 | let not_trait_impl = blk.target_trait(db).is_none(); | 154 | let not_trait_impl = blk.target_trait(db).is_none(); |
149 | 155 | ||
150 | if !(same_ty && not_trait_impl) { | 156 | if !(same_ty && not_trait_impl) { |
diff --git a/crates/ra_assists/src/handlers/auto_import.rs b/crates/ra_assists/src/handlers/auto_import.rs index 84b5474f9..1fb701da5 100644 --- a/crates/ra_assists/src/handlers/auto_import.rs +++ b/crates/ra_assists/src/handlers/auto_import.rs | |||
@@ -1,13 +1,9 @@ | |||
1 | use hir::ModPath; | ||
2 | use ra_ide_db::imports_locator::ImportsLocator; | 1 | use ra_ide_db::imports_locator::ImportsLocator; |
3 | use ra_syntax::{ | 2 | use ra_syntax::ast::{self, AstNode}; |
4 | ast::{self, AstNode}, | ||
5 | SyntaxNode, | ||
6 | }; | ||
7 | 3 | ||
8 | use crate::{ | 4 | use crate::{ |
9 | assist_ctx::{ActionBuilder, Assist, AssistCtx}, | 5 | assist_ctx::{Assist, AssistCtx}, |
10 | auto_import_text_edit, AssistId, | 6 | insert_use_statement, AssistId, |
11 | }; | 7 | }; |
12 | use std::collections::BTreeSet; | 8 | use std::collections::BTreeSet; |
13 | 9 | ||
@@ -31,31 +27,34 @@ use std::collections::BTreeSet; | |||
31 | // # pub mod std { pub mod collections { pub struct HashMap { } } } | 27 | // # pub mod std { pub mod collections { pub struct HashMap { } } } |
32 | // ``` | 28 | // ``` |
33 | pub(crate) fn auto_import(ctx: AssistCtx) -> Option<Assist> { | 29 | pub(crate) fn auto_import(ctx: AssistCtx) -> Option<Assist> { |
34 | let path_to_import: ast::Path = ctx.find_node_at_offset()?; | 30 | let path_under_caret: ast::Path = ctx.find_node_at_offset()?; |
35 | let path_to_import_syntax = path_to_import.syntax(); | 31 | if path_under_caret.syntax().ancestors().find_map(ast::UseItem::cast).is_some() { |
36 | if path_to_import_syntax.ancestors().find_map(ast::UseItem::cast).is_some() { | ||
37 | return None; | 32 | return None; |
38 | } | 33 | } |
39 | let name_to_import = | ||
40 | path_to_import_syntax.descendants().find_map(ast::NameRef::cast)?.syntax().to_string(); | ||
41 | 34 | ||
42 | let module = path_to_import_syntax.ancestors().find_map(ast::Module::cast); | 35 | let module = path_under_caret.syntax().ancestors().find_map(ast::Module::cast); |
43 | let position = match module.and_then(|it| it.item_list()) { | 36 | let position = match module.and_then(|it| it.item_list()) { |
44 | Some(item_list) => item_list.syntax().clone(), | 37 | Some(item_list) => item_list.syntax().clone(), |
45 | None => { | 38 | None => { |
46 | let current_file = path_to_import_syntax.ancestors().find_map(ast::SourceFile::cast)?; | 39 | let current_file = |
40 | path_under_caret.syntax().ancestors().find_map(ast::SourceFile::cast)?; | ||
47 | current_file.syntax().clone() | 41 | current_file.syntax().clone() |
48 | } | 42 | } |
49 | }; | 43 | }; |
50 | let source_analyzer = ctx.source_analyzer(&position, None); | 44 | let source_analyzer = ctx.source_analyzer(&position, None); |
51 | let module_with_name_to_import = source_analyzer.module()?; | 45 | let module_with_name_to_import = source_analyzer.module()?; |
52 | if source_analyzer.resolve_path(ctx.db, &path_to_import).is_some() { | 46 | |
47 | let name_ref_to_import = | ||
48 | path_under_caret.syntax().descendants().find_map(ast::NameRef::cast)?; | ||
49 | if source_analyzer | ||
50 | .resolve_path(ctx.db, &name_ref_to_import.syntax().ancestors().find_map(ast::Path::cast)?) | ||
51 | .is_some() | ||
52 | { | ||
53 | return None; | 53 | return None; |
54 | } | 54 | } |
55 | 55 | ||
56 | let mut imports_locator = ImportsLocator::new(ctx.db); | 56 | let name_to_import = name_ref_to_import.syntax().to_string(); |
57 | 57 | let proposed_imports = ImportsLocator::new(ctx.db) | |
58 | let proposed_imports = imports_locator | ||
59 | .find_imports(&name_to_import) | 58 | .find_imports(&name_to_import) |
60 | .into_iter() | 59 | .into_iter() |
61 | .filter_map(|module_def| module_with_name_to_import.find_use_path(ctx.db, module_def)) | 60 | .filter_map(|module_def| module_with_name_to_import.find_use_path(ctx.db, module_def)) |
@@ -67,24 +66,24 @@ pub(crate) fn auto_import(ctx: AssistCtx) -> Option<Assist> { | |||
67 | return None; | 66 | return None; |
68 | } | 67 | } |
69 | 68 | ||
70 | ctx.add_assist_group(AssistId("auto_import"), format!("Import {}", name_to_import), || { | 69 | let mut group = ctx.add_assist_group(format!("Import {}", name_to_import)); |
71 | proposed_imports | 70 | for import in proposed_imports { |
72 | .into_iter() | 71 | group.add_assist(AssistId("auto_import"), format!("Import `{}`", &import), |edit| { |
73 | .map(|import| import_to_action(import, &position, &path_to_import_syntax)) | 72 | edit.target(path_under_caret.syntax().text_range()); |
74 | .collect() | 73 | insert_use_statement( |
75 | }) | 74 | &position, |
76 | } | 75 | path_under_caret.syntax(), |
77 | 76 | &import, | |
78 | fn import_to_action(import: ModPath, position: &SyntaxNode, anchor: &SyntaxNode) -> ActionBuilder { | 77 | edit.text_edit_builder(), |
79 | let mut action_builder = ActionBuilder::default(); | 78 | ); |
80 | action_builder.label(format!("Import `{}`", &import)); | 79 | }); |
81 | auto_import_text_edit(position, anchor, &import, action_builder.text_edit_builder()); | 80 | } |
82 | action_builder | 81 | group.finish() |
83 | } | 82 | } |
84 | 83 | ||
85 | #[cfg(test)] | 84 | #[cfg(test)] |
86 | mod tests { | 85 | mod tests { |
87 | use crate::helpers::{check_assist, check_assist_not_applicable}; | 86 | use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target}; |
88 | 87 | ||
89 | use super::*; | 88 | use super::*; |
90 | 89 | ||
@@ -255,4 +254,40 @@ mod tests { | |||
255 | ", | 254 | ", |
256 | ); | 255 | ); |
257 | } | 256 | } |
257 | |||
258 | #[test] | ||
259 | fn auto_import_target() { | ||
260 | check_assist_target( | ||
261 | auto_import, | ||
262 | r" | ||
263 | struct AssistInfo { | ||
264 | group_label: Option<<|>GroupLabel>, | ||
265 | } | ||
266 | |||
267 | mod m { pub struct GroupLabel; } | ||
268 | ", | ||
269 | "GroupLabel", | ||
270 | ) | ||
271 | } | ||
272 | |||
273 | #[test] | ||
274 | fn not_applicable_when_path_start_is_imported() { | ||
275 | check_assist_not_applicable( | ||
276 | auto_import, | ||
277 | r" | ||
278 | pub mod mod1 { | ||
279 | pub mod mod2 { | ||
280 | pub mod mod3 { | ||
281 | pub struct TestStruct; | ||
282 | } | ||
283 | } | ||
284 | } | ||
285 | |||
286 | use mod1::mod2; | ||
287 | fn main() { | ||
288 | mod2::mod3::TestStruct<|> | ||
289 | } | ||
290 | ", | ||
291 | ); | ||
292 | } | ||
258 | } | 293 | } |
diff --git a/crates/ra_assists/src/handlers/fill_match_arms.rs b/crates/ra_assists/src/handlers/fill_match_arms.rs index 0908fc246..ae2437ed3 100644 --- a/crates/ra_assists/src/handlers/fill_match_arms.rs +++ b/crates/ra_assists/src/handlers/fill_match_arms.rs | |||
@@ -75,10 +75,10 @@ pub(crate) fn fill_match_arms(ctx: AssistCtx) -> Option<Assist> { | |||
75 | } | 75 | } |
76 | 76 | ||
77 | fn is_trivial(arm: &ast::MatchArm) -> bool { | 77 | fn is_trivial(arm: &ast::MatchArm) -> bool { |
78 | arm.pats().any(|pat| match pat { | 78 | match arm.pat() { |
79 | ast::Pat::PlaceholderPat(..) => true, | 79 | Some(ast::Pat::PlaceholderPat(..)) => true, |
80 | _ => false, | 80 | _ => false, |
81 | }) | 81 | } |
82 | } | 82 | } |
83 | 83 | ||
84 | fn resolve_enum_def( | 84 | fn resolve_enum_def( |
diff --git a/crates/ra_assists/src/handlers/merge_match_arms.rs b/crates/ra_assists/src/handlers/merge_match_arms.rs index 670614dd8..b2a194cb5 100644 --- a/crates/ra_assists/src/handlers/merge_match_arms.rs +++ b/crates/ra_assists/src/handlers/merge_match_arms.rs | |||
@@ -75,7 +75,7 @@ pub(crate) fn merge_match_arms(ctx: AssistCtx) -> Option<Assist> { | |||
75 | } else { | 75 | } else { |
76 | arms_to_merge | 76 | arms_to_merge |
77 | .iter() | 77 | .iter() |
78 | .flat_map(ast::MatchArm::pats) | 78 | .filter_map(ast::MatchArm::pat) |
79 | .map(|x| x.syntax().to_string()) | 79 | .map(|x| x.syntax().to_string()) |
80 | .collect::<Vec<String>>() | 80 | .collect::<Vec<String>>() |
81 | .join(" | ") | 81 | .join(" | ") |
@@ -96,10 +96,10 @@ pub(crate) fn merge_match_arms(ctx: AssistCtx) -> Option<Assist> { | |||
96 | } | 96 | } |
97 | 97 | ||
98 | fn contains_placeholder(a: &ast::MatchArm) -> bool { | 98 | fn contains_placeholder(a: &ast::MatchArm) -> bool { |
99 | a.pats().any(|x| match x { | 99 | match a.pat() { |
100 | ra_syntax::ast::Pat::PlaceholderPat(..) => true, | 100 | Some(ra_syntax::ast::Pat::PlaceholderPat(..)) => true, |
101 | _ => false, | 101 | _ => false, |
102 | }) | 102 | } |
103 | } | 103 | } |
104 | 104 | ||
105 | fn next_arm(arm: &ast::MatchArm) -> Option<ast::MatchArm> { | 105 | fn next_arm(arm: &ast::MatchArm) -> Option<ast::MatchArm> { |
diff --git a/crates/ra_assists/src/handlers/move_guard.rs b/crates/ra_assists/src/handlers/move_guard.rs index 2b91ce7c4..a61a2ba3e 100644 --- a/crates/ra_assists/src/handlers/move_guard.rs +++ b/crates/ra_assists/src/handlers/move_guard.rs | |||
@@ -90,7 +90,7 @@ pub(crate) fn move_guard_to_arm_body(ctx: AssistCtx) -> Option<Assist> { | |||
90 | // ``` | 90 | // ``` |
91 | pub(crate) fn move_arm_cond_to_match_guard(ctx: AssistCtx) -> Option<Assist> { | 91 | pub(crate) fn move_arm_cond_to_match_guard(ctx: AssistCtx) -> Option<Assist> { |
92 | let match_arm: MatchArm = ctx.find_node_at_offset::<MatchArm>()?; | 92 | let match_arm: MatchArm = ctx.find_node_at_offset::<MatchArm>()?; |
93 | let last_match_pat = match_arm.pats().last()?; | 93 | let match_pat = match_arm.pat()?; |
94 | 94 | ||
95 | let arm_body = match_arm.expr()?; | 95 | let arm_body = match_arm.expr()?; |
96 | let if_expr: IfExpr = IfExpr::cast(arm_body.syntax().clone())?; | 96 | let if_expr: IfExpr = IfExpr::cast(arm_body.syntax().clone())?; |
@@ -122,8 +122,8 @@ pub(crate) fn move_arm_cond_to_match_guard(ctx: AssistCtx) -> Option<Assist> { | |||
122 | _ => edit.replace(if_expr.syntax().text_range(), then_block.syntax().text()), | 122 | _ => edit.replace(if_expr.syntax().text_range(), then_block.syntax().text()), |
123 | } | 123 | } |
124 | 124 | ||
125 | edit.insert(last_match_pat.syntax().text_range().end(), buf); | 125 | edit.insert(match_pat.syntax().text_range().end(), buf); |
126 | edit.set_cursor(last_match_pat.syntax().text_range().end() + TextUnit::from(1)); | 126 | edit.set_cursor(match_pat.syntax().text_range().end() + TextUnit::from(1)); |
127 | }, | 127 | }, |
128 | ) | 128 | ) |
129 | } | 129 | } |
diff --git a/crates/ra_assists/src/handlers/add_import.rs b/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs index f03dddac8..b70c88ec2 100644 --- a/crates/ra_assists/src/handlers/add_import.rs +++ b/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs | |||
@@ -12,10 +12,10 @@ use crate::{ | |||
12 | AssistId, | 12 | AssistId, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | /// This function produces sequence of text edits into edit | 15 | /// Creates and inserts a use statement for the given path to import. |
16 | /// to import the target path in the most appropriate scope given | 16 | /// The use statement is inserted in the scope most appropriate to the |
17 | /// the cursor position | 17 | /// the cursor position given, additionally merged with the existing use imports. |
18 | pub fn auto_import_text_edit( | 18 | pub fn insert_use_statement( |
19 | // Ideally the position of the cursor, used to | 19 | // Ideally the position of the cursor, used to |
20 | position: &SyntaxNode, | 20 | position: &SyntaxNode, |
21 | // The statement to use as anchor (last resort) | 21 | // The statement to use as anchor (last resort) |
@@ -37,9 +37,9 @@ pub fn auto_import_text_edit( | |||
37 | } | 37 | } |
38 | } | 38 | } |
39 | 39 | ||
40 | // Assist: add_import | 40 | // Assist: replace_qualified_name_with_use |
41 | // | 41 | // |
42 | // Adds a use statement for a given fully-qualified path. | 42 | // Adds a use statement for a given fully-qualified name. |
43 | // | 43 | // |
44 | // ``` | 44 | // ``` |
45 | // fn process(map: std::collections::<|>HashMap<String, String>) {} | 45 | // fn process(map: std::collections::<|>HashMap<String, String>) {} |
@@ -50,7 +50,7 @@ pub fn auto_import_text_edit( | |||
50 | // | 50 | // |
51 | // fn process(map: HashMap<String, String>) {} | 51 | // fn process(map: HashMap<String, String>) {} |
52 | // ``` | 52 | // ``` |
53 | pub(crate) fn add_import(ctx: AssistCtx) -> Option<Assist> { | 53 | pub(crate) fn replace_qualified_name_with_use(ctx: AssistCtx) -> Option<Assist> { |
54 | let path: ast::Path = ctx.find_node_at_offset()?; | 54 | let path: ast::Path = ctx.find_node_at_offset()?; |
55 | // We don't want to mess with use statements | 55 | // We don't want to mess with use statements |
56 | if path.syntax().ancestors().find_map(ast::UseItem::cast).is_some() { | 56 | if path.syntax().ancestors().find_map(ast::UseItem::cast).is_some() { |
@@ -72,9 +72,13 @@ pub(crate) fn add_import(ctx: AssistCtx) -> Option<Assist> { | |||
72 | } | 72 | } |
73 | }; | 73 | }; |
74 | 74 | ||
75 | ctx.add_assist(AssistId("add_import"), format!("Import {}", fmt_segments(&segments)), |edit| { | 75 | ctx.add_assist( |
76 | apply_auto_import(&position, &path, &segments, edit.text_edit_builder()); | 76 | AssistId("replace_qualified_name_with_use"), |
77 | }) | 77 | "Replace qualified path with use", |
78 | |edit| { | ||
79 | replace_with_use(&position, &path, &segments, edit.text_edit_builder()); | ||
80 | }, | ||
81 | ) | ||
78 | } | 82 | } |
79 | 83 | ||
80 | fn collect_path_segments_raw( | 84 | fn collect_path_segments_raw( |
@@ -107,12 +111,6 @@ fn collect_path_segments_raw( | |||
107 | Some(segments.len() - oldlen) | 111 | Some(segments.len() - oldlen) |
108 | } | 112 | } |
109 | 113 | ||
110 | fn fmt_segments(segments: &[SmolStr]) -> String { | ||
111 | let mut buf = String::new(); | ||
112 | fmt_segments_raw(segments, &mut buf); | ||
113 | buf | ||
114 | } | ||
115 | |||
116 | fn fmt_segments_raw(segments: &[SmolStr], buf: &mut String) { | 114 | fn fmt_segments_raw(segments: &[SmolStr], buf: &mut String) { |
117 | let mut iter = segments.iter(); | 115 | let mut iter = segments.iter(); |
118 | if let Some(s) = iter.next() { | 116 | if let Some(s) = iter.next() { |
@@ -558,7 +556,7 @@ fn make_assist_add_nested_import( | |||
558 | } | 556 | } |
559 | } | 557 | } |
560 | 558 | ||
561 | fn apply_auto_import( | 559 | fn replace_with_use( |
562 | container: &SyntaxNode, | 560 | container: &SyntaxNode, |
563 | path: &ast::Path, | 561 | path: &ast::Path, |
564 | target: &[SmolStr], | 562 | target: &[SmolStr], |
@@ -567,7 +565,7 @@ fn apply_auto_import( | |||
567 | let action = best_action_for_target(container.clone(), path.syntax().clone(), target); | 565 | let action = best_action_for_target(container.clone(), path.syntax().clone(), target); |
568 | make_assist(&action, target, edit); | 566 | make_assist(&action, target, edit); |
569 | if let Some(last) = path.segment() { | 567 | if let Some(last) = path.segment() { |
570 | // Here we are assuming the assist will provide a correct use statement | 568 | // Here we are assuming the assist will provide a correct use statement |
571 | // so we can delete the path qualifier | 569 | // so we can delete the path qualifier |
572 | edit.delete(TextRange::from_to( | 570 | edit.delete(TextRange::from_to( |
573 | path.syntax().text_range().start(), | 571 | path.syntax().text_range().start(), |
@@ -603,9 +601,9 @@ mod tests { | |||
603 | use super::*; | 601 | use super::*; |
604 | 602 | ||
605 | #[test] | 603 | #[test] |
606 | fn test_auto_import_add_use_no_anchor() { | 604 | fn test_replace_add_use_no_anchor() { |
607 | check_assist( | 605 | check_assist( |
608 | add_import, | 606 | replace_qualified_name_with_use, |
609 | " | 607 | " |
610 | std::fmt::Debug<|> | 608 | std::fmt::Debug<|> |
611 | ", | 609 | ", |
@@ -617,9 +615,9 @@ Debug<|> | |||
617 | ); | 615 | ); |
618 | } | 616 | } |
619 | #[test] | 617 | #[test] |
620 | fn test_auto_import_add_use_no_anchor_with_item_below() { | 618 | fn test_replace_add_use_no_anchor_with_item_below() { |
621 | check_assist( | 619 | check_assist( |
622 | add_import, | 620 | replace_qualified_name_with_use, |
623 | " | 621 | " |
624 | std::fmt::Debug<|> | 622 | std::fmt::Debug<|> |
625 | 623 | ||
@@ -638,9 +636,9 @@ fn main() { | |||
638 | } | 636 | } |
639 | 637 | ||
640 | #[test] | 638 | #[test] |
641 | fn test_auto_import_add_use_no_anchor_with_item_above() { | 639 | fn test_replace_add_use_no_anchor_with_item_above() { |
642 | check_assist( | 640 | check_assist( |
643 | add_import, | 641 | replace_qualified_name_with_use, |
644 | " | 642 | " |
645 | fn main() { | 643 | fn main() { |
646 | } | 644 | } |
@@ -659,9 +657,9 @@ Debug<|> | |||
659 | } | 657 | } |
660 | 658 | ||
661 | #[test] | 659 | #[test] |
662 | fn test_auto_import_add_use_no_anchor_2seg() { | 660 | fn test_replace_add_use_no_anchor_2seg() { |
663 | check_assist( | 661 | check_assist( |
664 | add_import, | 662 | replace_qualified_name_with_use, |
665 | " | 663 | " |
666 | std::fmt<|>::Debug | 664 | std::fmt<|>::Debug |
667 | ", | 665 | ", |
@@ -674,9 +672,9 @@ fmt<|>::Debug | |||
674 | } | 672 | } |
675 | 673 | ||
676 | #[test] | 674 | #[test] |
677 | fn test_auto_import_add_use() { | 675 | fn test_replace_add_use() { |
678 | check_assist( | 676 | check_assist( |
679 | add_import, | 677 | replace_qualified_name_with_use, |
680 | " | 678 | " |
681 | use stdx; | 679 | use stdx; |
682 | 680 | ||
@@ -694,9 +692,9 @@ impl Debug<|> for Foo { | |||
694 | } | 692 | } |
695 | 693 | ||
696 | #[test] | 694 | #[test] |
697 | fn test_auto_import_file_use_other_anchor() { | 695 | fn test_replace_file_use_other_anchor() { |
698 | check_assist( | 696 | check_assist( |
699 | add_import, | 697 | replace_qualified_name_with_use, |
700 | " | 698 | " |
701 | impl std::fmt::Debug<|> for Foo { | 699 | impl std::fmt::Debug<|> for Foo { |
702 | } | 700 | } |
@@ -711,9 +709,9 @@ impl Debug<|> for Foo { | |||
711 | } | 709 | } |
712 | 710 | ||
713 | #[test] | 711 | #[test] |
714 | fn test_auto_import_add_use_other_anchor_indent() { | 712 | fn test_replace_add_use_other_anchor_indent() { |
715 | check_assist( | 713 | check_assist( |
716 | add_import, | 714 | replace_qualified_name_with_use, |
717 | " | 715 | " |
718 | impl std::fmt::Debug<|> for Foo { | 716 | impl std::fmt::Debug<|> for Foo { |
719 | } | 717 | } |
@@ -728,9 +726,9 @@ impl Debug<|> for Foo { | |||
728 | } | 726 | } |
729 | 727 | ||
730 | #[test] | 728 | #[test] |
731 | fn test_auto_import_split_different() { | 729 | fn test_replace_split_different() { |
732 | check_assist( | 730 | check_assist( |
733 | add_import, | 731 | replace_qualified_name_with_use, |
734 | " | 732 | " |
735 | use std::fmt; | 733 | use std::fmt; |
736 | 734 | ||
@@ -747,9 +745,9 @@ impl io<|> for Foo { | |||
747 | } | 745 | } |
748 | 746 | ||
749 | #[test] | 747 | #[test] |
750 | fn test_auto_import_split_self_for_use() { | 748 | fn test_replace_split_self_for_use() { |
751 | check_assist( | 749 | check_assist( |
752 | add_import, | 750 | replace_qualified_name_with_use, |
753 | " | 751 | " |
754 | use std::fmt; | 752 | use std::fmt; |
755 | 753 | ||
@@ -766,9 +764,9 @@ impl Debug<|> for Foo { | |||
766 | } | 764 | } |
767 | 765 | ||
768 | #[test] | 766 | #[test] |
769 | fn test_auto_import_split_self_for_target() { | 767 | fn test_replace_split_self_for_target() { |
770 | check_assist( | 768 | check_assist( |
771 | add_import, | 769 | replace_qualified_name_with_use, |
772 | " | 770 | " |
773 | use std::fmt::Debug; | 771 | use std::fmt::Debug; |
774 | 772 | ||
@@ -785,9 +783,9 @@ impl fmt<|> for Foo { | |||
785 | } | 783 | } |
786 | 784 | ||
787 | #[test] | 785 | #[test] |
788 | fn test_auto_import_add_to_nested_self_nested() { | 786 | fn test_replace_add_to_nested_self_nested() { |
789 | check_assist( | 787 | check_assist( |
790 | add_import, | 788 | replace_qualified_name_with_use, |
791 | " | 789 | " |
792 | use std::fmt::{Debug, nested::{Display}}; | 790 | use std::fmt::{Debug, nested::{Display}}; |
793 | 791 | ||
@@ -804,9 +802,9 @@ impl nested<|> for Foo { | |||
804 | } | 802 | } |
805 | 803 | ||
806 | #[test] | 804 | #[test] |
807 | fn test_auto_import_add_to_nested_self_already_included() { | 805 | fn test_replace_add_to_nested_self_already_included() { |
808 | check_assist( | 806 | check_assist( |
809 | add_import, | 807 | replace_qualified_name_with_use, |
810 | " | 808 | " |
811 | use std::fmt::{Debug, nested::{self, Display}}; | 809 | use std::fmt::{Debug, nested::{self, Display}}; |
812 | 810 | ||
@@ -823,9 +821,9 @@ impl nested<|> for Foo { | |||
823 | } | 821 | } |
824 | 822 | ||
825 | #[test] | 823 | #[test] |
826 | fn test_auto_import_add_to_nested_nested() { | 824 | fn test_replace_add_to_nested_nested() { |
827 | check_assist( | 825 | check_assist( |
828 | add_import, | 826 | replace_qualified_name_with_use, |
829 | " | 827 | " |
830 | use std::fmt::{Debug, nested::{Display}}; | 828 | use std::fmt::{Debug, nested::{Display}}; |
831 | 829 | ||
@@ -842,9 +840,9 @@ impl Debug<|> for Foo { | |||
842 | } | 840 | } |
843 | 841 | ||
844 | #[test] | 842 | #[test] |
845 | fn test_auto_import_split_common_target_longer() { | 843 | fn test_replace_split_common_target_longer() { |
846 | check_assist( | 844 | check_assist( |
847 | add_import, | 845 | replace_qualified_name_with_use, |
848 | " | 846 | " |
849 | use std::fmt::Debug; | 847 | use std::fmt::Debug; |
850 | 848 | ||
@@ -861,9 +859,9 @@ impl Display<|> for Foo { | |||
861 | } | 859 | } |
862 | 860 | ||
863 | #[test] | 861 | #[test] |
864 | fn test_auto_import_split_common_use_longer() { | 862 | fn test_replace_split_common_use_longer() { |
865 | check_assist( | 863 | check_assist( |
866 | add_import, | 864 | replace_qualified_name_with_use, |
867 | " | 865 | " |
868 | use std::fmt::nested::Debug; | 866 | use std::fmt::nested::Debug; |
869 | 867 | ||
@@ -880,9 +878,9 @@ impl Display<|> for Foo { | |||
880 | } | 878 | } |
881 | 879 | ||
882 | #[test] | 880 | #[test] |
883 | fn test_auto_import_use_nested_import() { | 881 | fn test_replace_use_nested_import() { |
884 | check_assist( | 882 | check_assist( |
885 | add_import, | 883 | replace_qualified_name_with_use, |
886 | " | 884 | " |
887 | use crate::{ | 885 | use crate::{ |
888 | ty::{Substs, Ty}, | 886 | ty::{Substs, Ty}, |
@@ -903,9 +901,9 @@ fn foo() { lower<|>::trait_env() } | |||
903 | } | 901 | } |
904 | 902 | ||
905 | #[test] | 903 | #[test] |
906 | fn test_auto_import_alias() { | 904 | fn test_replace_alias() { |
907 | check_assist( | 905 | check_assist( |
908 | add_import, | 906 | replace_qualified_name_with_use, |
909 | " | 907 | " |
910 | use std::fmt as foo; | 908 | use std::fmt as foo; |
911 | 909 | ||
@@ -922,9 +920,9 @@ impl Debug<|> for Foo { | |||
922 | } | 920 | } |
923 | 921 | ||
924 | #[test] | 922 | #[test] |
925 | fn test_auto_import_not_applicable_one_segment() { | 923 | fn test_replace_not_applicable_one_segment() { |
926 | check_assist_not_applicable( | 924 | check_assist_not_applicable( |
927 | add_import, | 925 | replace_qualified_name_with_use, |
928 | " | 926 | " |
929 | impl foo<|> for Foo { | 927 | impl foo<|> for Foo { |
930 | } | 928 | } |
@@ -933,9 +931,9 @@ impl foo<|> for Foo { | |||
933 | } | 931 | } |
934 | 932 | ||
935 | #[test] | 933 | #[test] |
936 | fn test_auto_import_not_applicable_in_use() { | 934 | fn test_replace_not_applicable_in_use() { |
937 | check_assist_not_applicable( | 935 | check_assist_not_applicable( |
938 | add_import, | 936 | replace_qualified_name_with_use, |
939 | " | 937 | " |
940 | use std::fmt<|>; | 938 | use std::fmt<|>; |
941 | ", | 939 | ", |
@@ -943,9 +941,9 @@ use std::fmt<|>; | |||
943 | } | 941 | } |
944 | 942 | ||
945 | #[test] | 943 | #[test] |
946 | fn test_auto_import_add_use_no_anchor_in_mod_mod() { | 944 | fn test_replace_add_use_no_anchor_in_mod_mod() { |
947 | check_assist( | 945 | check_assist( |
948 | add_import, | 946 | replace_qualified_name_with_use, |
949 | " | 947 | " |
950 | mod foo { | 948 | mod foo { |
951 | mod bar { | 949 | mod bar { |
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index eca6dec4b..828a8e9e8 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs | |||
@@ -12,16 +12,13 @@ mod doc_tests; | |||
12 | mod utils; | 12 | mod utils; |
13 | pub mod ast_transform; | 13 | pub mod ast_transform; |
14 | 14 | ||
15 | use std::cmp::Ordering; | ||
16 | |||
17 | use either::Either; | ||
18 | use ra_db::FileRange; | 15 | use ra_db::FileRange; |
19 | use ra_ide_db::RootDatabase; | 16 | use ra_ide_db::RootDatabase; |
20 | use ra_syntax::{TextRange, TextUnit}; | 17 | use ra_syntax::{TextRange, TextUnit}; |
21 | use ra_text_edit::TextEdit; | 18 | use ra_text_edit::TextEdit; |
22 | 19 | ||
23 | pub(crate) use crate::assist_ctx::{Assist, AssistCtx, AssistHandler}; | 20 | pub(crate) use crate::assist_ctx::{Assist, AssistCtx, AssistHandler}; |
24 | pub use crate::handlers::add_import::auto_import_text_edit; | 21 | pub use crate::handlers::replace_qualified_name_with_use::insert_use_statement; |
25 | 22 | ||
26 | /// Unique identifier of the assist, should not be shown to the user | 23 | /// Unique identifier of the assist, should not be shown to the user |
27 | /// directly. | 24 | /// directly. |
@@ -35,6 +32,9 @@ pub struct AssistLabel { | |||
35 | pub id: AssistId, | 32 | pub id: AssistId, |
36 | } | 33 | } |
37 | 34 | ||
35 | #[derive(Clone, Debug)] | ||
36 | pub struct GroupLabel(pub String); | ||
37 | |||
38 | impl AssistLabel { | 38 | impl AssistLabel { |
39 | pub(crate) fn new(label: String, id: AssistId) -> AssistLabel { | 39 | pub(crate) fn new(label: String, id: AssistId) -> AssistLabel { |
40 | // FIXME: make fields private, so that this invariant can't be broken | 40 | // FIXME: make fields private, so that this invariant can't be broken |
@@ -45,7 +45,6 @@ impl AssistLabel { | |||
45 | 45 | ||
46 | #[derive(Debug, Clone)] | 46 | #[derive(Debug, Clone)] |
47 | pub struct AssistAction { | 47 | pub struct AssistAction { |
48 | pub label: Option<String>, | ||
49 | pub edit: TextEdit, | 48 | pub edit: TextEdit, |
50 | pub cursor_position: Option<TextUnit>, | 49 | pub cursor_position: Option<TextUnit>, |
51 | // FIXME: This belongs to `AssistLabel` | 50 | // FIXME: This belongs to `AssistLabel` |
@@ -55,16 +54,8 @@ pub struct AssistAction { | |||
55 | #[derive(Debug, Clone)] | 54 | #[derive(Debug, Clone)] |
56 | pub struct ResolvedAssist { | 55 | pub struct ResolvedAssist { |
57 | pub label: AssistLabel, | 56 | pub label: AssistLabel, |
58 | pub action_data: Either<AssistAction, Vec<AssistAction>>, | 57 | pub group_label: Option<GroupLabel>, |
59 | } | 58 | pub action: AssistAction, |
60 | |||
61 | impl ResolvedAssist { | ||
62 | pub fn get_first_action(&self) -> AssistAction { | ||
63 | match &self.action_data { | ||
64 | Either::Left(action) => action.clone(), | ||
65 | Either::Right(actions) => actions[0].clone(), | ||
66 | } | ||
67 | } | ||
68 | } | 59 | } |
69 | 60 | ||
70 | /// Return all the assists applicable at the given position. | 61 | /// Return all the assists applicable at the given position. |
@@ -76,10 +67,8 @@ pub fn unresolved_assists(db: &RootDatabase, range: FileRange) -> Vec<AssistLabe | |||
76 | handlers::all() | 67 | handlers::all() |
77 | .iter() | 68 | .iter() |
78 | .filter_map(|f| f(ctx.clone())) | 69 | .filter_map(|f| f(ctx.clone())) |
79 | .map(|a| match a { | 70 | .flat_map(|it| it.0) |
80 | Assist::Unresolved { label } => label, | 71 | .map(|a| a.label) |
81 | Assist::Resolved { .. } => unreachable!(), | ||
82 | }) | ||
83 | .collect() | 72 | .collect() |
84 | } | 73 | } |
85 | 74 | ||
@@ -92,24 +81,13 @@ pub fn resolved_assists(db: &RootDatabase, range: FileRange) -> Vec<ResolvedAssi | |||
92 | let mut a = handlers::all() | 81 | let mut a = handlers::all() |
93 | .iter() | 82 | .iter() |
94 | .filter_map(|f| f(ctx.clone())) | 83 | .filter_map(|f| f(ctx.clone())) |
95 | .map(|a| match a { | 84 | .flat_map(|it| it.0) |
96 | Assist::Resolved { assist } => assist, | 85 | .map(|it| it.into_resolved().unwrap()) |
97 | Assist::Unresolved { .. } => unreachable!(), | ||
98 | }) | ||
99 | .collect::<Vec<_>>(); | 86 | .collect::<Vec<_>>(); |
100 | sort_assists(&mut a); | 87 | a.sort_by_key(|it| it.action.target.map_or(TextUnit::from(!0u32), |it| it.len())); |
101 | a | 88 | a |
102 | } | 89 | } |
103 | 90 | ||
104 | fn sort_assists(assists: &mut [ResolvedAssist]) { | ||
105 | assists.sort_by(|a, b| match (a.get_first_action().target, b.get_first_action().target) { | ||
106 | (Some(a), Some(b)) => a.len().cmp(&b.len()), | ||
107 | (Some(_), None) => Ordering::Less, | ||
108 | (None, Some(_)) => Ordering::Greater, | ||
109 | (None, None) => Ordering::Equal, | ||
110 | }); | ||
111 | } | ||
112 | |||
113 | mod handlers { | 91 | mod handlers { |
114 | use crate::AssistHandler; | 92 | use crate::AssistHandler; |
115 | 93 | ||
@@ -133,7 +111,7 @@ mod handlers { | |||
133 | mod replace_if_let_with_match; | 111 | mod replace_if_let_with_match; |
134 | mod split_import; | 112 | mod split_import; |
135 | mod remove_dbg; | 113 | mod remove_dbg; |
136 | pub(crate) mod add_import; | 114 | pub(crate) mod replace_qualified_name_with_use; |
137 | mod add_missing_impl_members; | 115 | mod add_missing_impl_members; |
138 | mod move_guard; | 116 | mod move_guard; |
139 | mod move_bounds; | 117 | mod move_bounds; |
@@ -158,7 +136,7 @@ mod handlers { | |||
158 | replace_if_let_with_match::replace_if_let_with_match, | 136 | replace_if_let_with_match::replace_if_let_with_match, |
159 | split_import::split_import, | 137 | split_import::split_import, |
160 | remove_dbg::remove_dbg, | 138 | remove_dbg::remove_dbg, |
161 | add_import::add_import, | 139 | replace_qualified_name_with_use::replace_qualified_name_with_use, |
162 | add_missing_impl_members::add_missing_impl_members, | 140 | add_missing_impl_members::add_missing_impl_members, |
163 | add_missing_impl_members::add_missing_default_members, | 141 | add_missing_impl_members::add_missing_default_members, |
164 | inline_local_variable::inline_local_variable, | 142 | inline_local_variable::inline_local_variable, |
@@ -184,7 +162,7 @@ mod helpers { | |||
184 | use ra_syntax::TextRange; | 162 | use ra_syntax::TextRange; |
185 | use test_utils::{add_cursor, assert_eq_text, extract_offset, extract_range}; | 163 | use test_utils::{add_cursor, assert_eq_text, extract_offset, extract_range}; |
186 | 164 | ||
187 | use crate::{Assist, AssistCtx, AssistHandler}; | 165 | use crate::{AssistCtx, AssistHandler}; |
188 | 166 | ||
189 | pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) { | 167 | pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) { |
190 | let (mut db, file_id) = RootDatabase::with_single_file(text); | 168 | let (mut db, file_id) = RootDatabase::with_single_file(text); |
@@ -202,10 +180,7 @@ mod helpers { | |||
202 | FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; | 180 | FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; |
203 | let assist = | 181 | let assist = |
204 | assist(AssistCtx::new(&db, frange, true)).expect("code action is not applicable"); | 182 | assist(AssistCtx::new(&db, frange, true)).expect("code action is not applicable"); |
205 | let action = match assist { | 183 | let action = assist.0[0].action.clone().unwrap(); |
206 | Assist::Unresolved { .. } => unreachable!(), | ||
207 | Assist::Resolved { assist } => assist.get_first_action(), | ||
208 | }; | ||
209 | 184 | ||
210 | let actual = action.edit.apply(&before); | 185 | let actual = action.edit.apply(&before); |
211 | let actual_cursor_pos = match action.cursor_position { | 186 | let actual_cursor_pos = match action.cursor_position { |
@@ -225,10 +200,7 @@ mod helpers { | |||
225 | let frange = FileRange { file_id, range }; | 200 | let frange = FileRange { file_id, range }; |
226 | let assist = | 201 | let assist = |
227 | assist(AssistCtx::new(&db, frange, true)).expect("code action is not applicable"); | 202 | assist(AssistCtx::new(&db, frange, true)).expect("code action is not applicable"); |
228 | let action = match assist { | 203 | let action = assist.0[0].action.clone().unwrap(); |
229 | Assist::Unresolved { .. } => unreachable!(), | ||
230 | Assist::Resolved { assist } => assist.get_first_action(), | ||
231 | }; | ||
232 | 204 | ||
233 | let mut actual = action.edit.apply(&before); | 205 | let mut actual = action.edit.apply(&before); |
234 | if let Some(pos) = action.cursor_position { | 206 | if let Some(pos) = action.cursor_position { |
@@ -244,10 +216,7 @@ mod helpers { | |||
244 | FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; | 216 | FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; |
245 | let assist = | 217 | let assist = |
246 | assist(AssistCtx::new(&db, frange, true)).expect("code action is not applicable"); | 218 | assist(AssistCtx::new(&db, frange, true)).expect("code action is not applicable"); |
247 | let action = match assist { | 219 | let action = assist.0[0].action.clone().unwrap(); |
248 | Assist::Unresolved { .. } => unreachable!(), | ||
249 | Assist::Resolved { assist } => assist.get_first_action(), | ||
250 | }; | ||
251 | 220 | ||
252 | let range = action.target.expect("expected target on action"); | 221 | let range = action.target.expect("expected target on action"); |
253 | assert_eq_text!(&before[range.start().to_usize()..range.end().to_usize()], target); | 222 | assert_eq_text!(&before[range.start().to_usize()..range.end().to_usize()], target); |
@@ -259,10 +228,7 @@ mod helpers { | |||
259 | let frange = FileRange { file_id, range }; | 228 | let frange = FileRange { file_id, range }; |
260 | let assist = | 229 | let assist = |
261 | assist(AssistCtx::new(&db, frange, true)).expect("code action is not applicable"); | 230 | assist(AssistCtx::new(&db, frange, true)).expect("code action is not applicable"); |
262 | let action = match assist { | 231 | let action = assist.0[0].action.clone().unwrap(); |
263 | Assist::Unresolved { .. } => unreachable!(), | ||
264 | Assist::Resolved { assist } => assist.get_first_action(), | ||
265 | }; | ||
266 | 232 | ||
267 | let range = action.target.expect("expected target on action"); | 233 | let range = action.target.expect("expected target on action"); |
268 | assert_eq_text!(&before[range.start().to_usize()..range.end().to_usize()], target); | 234 | assert_eq_text!(&before[range.start().to_usize()..range.end().to_usize()], target); |
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index eaacf8c9e..4d9641728 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -10,9 +10,9 @@ use hir_def::{ | |||
10 | per_ns::PerNs, | 10 | per_ns::PerNs, |
11 | resolver::HasResolver, | 11 | resolver::HasResolver, |
12 | type_ref::{Mutability, TypeRef}, | 12 | type_ref::{Mutability, TypeRef}, |
13 | AdtId, ConstId, DefWithBodyId, EnumId, FunctionId, HasModule, ImplId, LocalEnumVariantId, | 13 | AdtId, ConstId, DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, |
14 | LocalModuleId, LocalStructFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, | 14 | LocalEnumVariantId, LocalModuleId, LocalStructFieldId, Lookup, ModuleId, StaticId, StructId, |
15 | TypeParamId, UnionId, | 15 | TraitId, TypeAliasId, TypeParamId, UnionId, |
16 | }; | 16 | }; |
17 | use hir_expand::{ | 17 | use hir_expand::{ |
18 | diagnostics::DiagnosticSink, | 18 | diagnostics::DiagnosticSink, |
@@ -21,7 +21,7 @@ use hir_expand::{ | |||
21 | }; | 21 | }; |
22 | use hir_ty::{ | 22 | use hir_ty::{ |
23 | autoderef, display::HirFormatter, expr::ExprValidator, method_resolution, ApplicationTy, | 23 | autoderef, display::HirFormatter, expr::ExprValidator, method_resolution, ApplicationTy, |
24 | Canonical, InEnvironment, TraitEnvironment, Ty, TyDefId, TypeCtor, TypeWalk, | 24 | Canonical, InEnvironment, Substs, TraitEnvironment, Ty, TyDefId, TypeCtor, |
25 | }; | 25 | }; |
26 | use ra_db::{CrateId, Edition, FileId}; | 26 | use ra_db::{CrateId, Edition, FileId}; |
27 | use ra_prof::profile; | 27 | use ra_prof::profile; |
@@ -270,7 +270,13 @@ impl StructField { | |||
270 | 270 | ||
271 | pub fn ty(&self, db: &impl HirDatabase) -> Type { | 271 | pub fn ty(&self, db: &impl HirDatabase) -> Type { |
272 | let var_id = self.parent.into(); | 272 | let var_id = self.parent.into(); |
273 | let ty = db.field_types(var_id)[self.id].clone(); | 273 | let generic_def_id: GenericDefId = match self.parent { |
274 | VariantDef::Struct(it) => it.id.into(), | ||
275 | VariantDef::Union(it) => it.id.into(), | ||
276 | VariantDef::EnumVariant(it) => it.parent.id.into(), | ||
277 | }; | ||
278 | let substs = Substs::type_params(db, generic_def_id); | ||
279 | let ty = db.field_types(var_id)[self.id].clone().subst(&substs); | ||
274 | Type::new(db, self.parent.module(db).id.krate.into(), var_id, ty) | 280 | Type::new(db, self.parent.module(db).id.krate.into(), var_id, ty) |
275 | } | 281 | } |
276 | 282 | ||
@@ -755,7 +761,7 @@ pub struct TypeParam { | |||
755 | impl TypeParam { | 761 | impl TypeParam { |
756 | pub fn name(self, db: &impl HirDatabase) -> Name { | 762 | pub fn name(self, db: &impl HirDatabase) -> Name { |
757 | let params = db.generic_params(self.id.parent); | 763 | let params = db.generic_params(self.id.parent); |
758 | params.types[self.id.local_id].name.clone() | 764 | params.types[self.id.local_id].name.clone().unwrap_or_else(Name::missing) |
759 | } | 765 | } |
760 | 766 | ||
761 | pub fn module(self, db: &impl HirDatabase) -> Module { | 767 | pub fn module(self, db: &impl HirDatabase) -> Module { |
@@ -789,8 +795,9 @@ impl ImplBlock { | |||
789 | pub fn target_ty(&self, db: &impl HirDatabase) -> Type { | 795 | pub fn target_ty(&self, db: &impl HirDatabase) -> Type { |
790 | let impl_data = db.impl_data(self.id); | 796 | let impl_data = db.impl_data(self.id); |
791 | let resolver = self.id.resolver(db); | 797 | let resolver = self.id.resolver(db); |
798 | let ctx = hir_ty::TyLoweringContext::new(db, &resolver); | ||
792 | let environment = TraitEnvironment::lower(db, &resolver); | 799 | let environment = TraitEnvironment::lower(db, &resolver); |
793 | let ty = Ty::from_hir(db, &resolver, &impl_data.target_type); | 800 | let ty = Ty::from_hir(&ctx, &impl_data.target_type); |
794 | Type { | 801 | Type { |
795 | krate: self.id.lookup(db).container.module(db).krate, | 802 | krate: self.id.lookup(db).container.module(db).krate, |
796 | ty: InEnvironment { value: ty, environment }, | 803 | ty: InEnvironment { value: ty, environment }, |
@@ -851,9 +858,10 @@ impl Type { | |||
851 | fn from_def( | 858 | fn from_def( |
852 | db: &impl HirDatabase, | 859 | db: &impl HirDatabase, |
853 | krate: CrateId, | 860 | krate: CrateId, |
854 | def: impl HasResolver + Into<TyDefId>, | 861 | def: impl HasResolver + Into<TyDefId> + Into<GenericDefId>, |
855 | ) -> Type { | 862 | ) -> Type { |
856 | let ty = db.ty(def.into()); | 863 | let substs = Substs::type_params(db, def); |
864 | let ty = db.ty(def.into()).subst(&substs); | ||
857 | Type::new(db, krate, def, ty) | 865 | Type::new(db, krate, def, ty) |
858 | } | 866 | } |
859 | 867 | ||
@@ -950,7 +958,7 @@ impl Type { | |||
950 | match a_ty.ctor { | 958 | match a_ty.ctor { |
951 | TypeCtor::Tuple { .. } => { | 959 | TypeCtor::Tuple { .. } => { |
952 | for ty in a_ty.parameters.iter() { | 960 | for ty in a_ty.parameters.iter() { |
953 | let ty = ty.clone().subst(&a_ty.parameters); | 961 | let ty = ty.clone(); |
954 | res.push(self.derived(ty)); | 962 | res.push(self.derived(ty)); |
955 | } | 963 | } |
956 | } | 964 | } |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 86e422779..e1c7b7a20 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -58,7 +58,6 @@ pub use hir_def::{ | |||
58 | type_ref::Mutability, | 58 | type_ref::Mutability, |
59 | }; | 59 | }; |
60 | pub use hir_expand::{ | 60 | pub use hir_expand::{ |
61 | name::{name, Name}, | 61 | name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, Origin, |
62 | HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, Origin, | ||
63 | }; | 62 | }; |
64 | pub use hir_ty::{display::HirDisplay, CallableDef}; | 63 | pub use hir_ty::{display::HirDisplay, CallableDef}; |
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs index 4f8fc9602..bb9a35c5d 100644 --- a/crates/ra_hir/src/source_analyzer.rs +++ b/crates/ra_hir/src/source_analyzer.rs | |||
@@ -178,6 +178,10 @@ impl SourceAnalyzer { | |||
178 | } | 178 | } |
179 | } | 179 | } |
180 | 180 | ||
181 | fn trait_env(&self, db: &impl HirDatabase) -> Arc<TraitEnvironment> { | ||
182 | TraitEnvironment::lower(db, &self.resolver) | ||
183 | } | ||
184 | |||
181 | pub fn type_of(&self, db: &impl HirDatabase, expr: &ast::Expr) -> Option<Type> { | 185 | pub fn type_of(&self, db: &impl HirDatabase, expr: &ast::Expr) -> Option<Type> { |
182 | let expr_id = if let Some(expr) = self.expand_expr(db, InFile::new(self.file_id, expr)) { | 186 | let expr_id = if let Some(expr) = self.expand_expr(db, InFile::new(self.file_id, expr)) { |
183 | self.body_source_map.as_ref()?.node_expr(expr.as_ref())? | 187 | self.body_source_map.as_ref()?.node_expr(expr.as_ref())? |
@@ -186,14 +190,14 @@ impl SourceAnalyzer { | |||
186 | }; | 190 | }; |
187 | 191 | ||
188 | let ty = self.infer.as_ref()?[expr_id].clone(); | 192 | let ty = self.infer.as_ref()?[expr_id].clone(); |
189 | let environment = TraitEnvironment::lower(db, &self.resolver); | 193 | let environment = self.trait_env(db); |
190 | Some(Type { krate: self.resolver.krate()?, ty: InEnvironment { value: ty, environment } }) | 194 | Some(Type { krate: self.resolver.krate()?, ty: InEnvironment { value: ty, environment } }) |
191 | } | 195 | } |
192 | 196 | ||
193 | pub fn type_of_pat(&self, db: &impl HirDatabase, pat: &ast::Pat) -> Option<Type> { | 197 | pub fn type_of_pat(&self, db: &impl HirDatabase, pat: &ast::Pat) -> Option<Type> { |
194 | let pat_id = self.pat_id(pat)?; | 198 | let pat_id = self.pat_id(pat)?; |
195 | let ty = self.infer.as_ref()?[pat_id].clone(); | 199 | let ty = self.infer.as_ref()?[pat_id].clone(); |
196 | let environment = TraitEnvironment::lower(db, &self.resolver); | 200 | let environment = self.trait_env(db); |
197 | Some(Type { krate: self.resolver.krate()?, ty: InEnvironment { value: ty, environment } }) | 201 | Some(Type { krate: self.resolver.krate()?, ty: InEnvironment { value: ty, environment } }) |
198 | } | 202 | } |
199 | 203 | ||
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 5c779521b..1fc892362 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -164,9 +164,9 @@ where | |||
164 | let match_expr = self.collect_expr_opt(condition.expr()); | 164 | let match_expr = self.collect_expr_opt(condition.expr()); |
165 | let placeholder_pat = self.missing_pat(); | 165 | let placeholder_pat = self.missing_pat(); |
166 | let arms = vec![ | 166 | let arms = vec![ |
167 | MatchArm { pats: vec![pat], expr: then_branch, guard: None }, | 167 | MatchArm { pat, expr: then_branch, guard: None }, |
168 | MatchArm { | 168 | MatchArm { |
169 | pats: vec![placeholder_pat], | 169 | pat: placeholder_pat, |
170 | expr: else_branch.unwrap_or_else(|| self.empty_block()), | 170 | expr: else_branch.unwrap_or_else(|| self.empty_block()), |
171 | guard: None, | 171 | guard: None, |
172 | }, | 172 | }, |
@@ -203,8 +203,8 @@ where | |||
203 | let placeholder_pat = self.missing_pat(); | 203 | let placeholder_pat = self.missing_pat(); |
204 | let break_ = self.alloc_expr_desugared(Expr::Break { expr: None }); | 204 | let break_ = self.alloc_expr_desugared(Expr::Break { expr: None }); |
205 | let arms = vec![ | 205 | let arms = vec![ |
206 | MatchArm { pats: vec![pat], expr: body, guard: None }, | 206 | MatchArm { pat, expr: body, guard: None }, |
207 | MatchArm { pats: vec![placeholder_pat], expr: break_, guard: None }, | 207 | MatchArm { pat: placeholder_pat, expr: break_, guard: None }, |
208 | ]; | 208 | ]; |
209 | let match_expr = | 209 | let match_expr = |
210 | self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms }); | 210 | self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms }); |
@@ -250,7 +250,7 @@ where | |||
250 | match_arm_list | 250 | match_arm_list |
251 | .arms() | 251 | .arms() |
252 | .map(|arm| MatchArm { | 252 | .map(|arm| MatchArm { |
253 | pats: arm.pats().map(|p| self.collect_pat(p)).collect(), | 253 | pat: self.collect_pat_opt(arm.pat()), |
254 | expr: self.collect_expr_opt(arm.expr()), | 254 | expr: self.collect_expr_opt(arm.expr()), |
255 | guard: arm | 255 | guard: arm |
256 | .guard() | 256 | .guard() |
@@ -587,6 +587,11 @@ where | |||
587 | let path = p.path().and_then(|path| self.expander.parse_path(path)); | 587 | let path = p.path().and_then(|path| self.expander.parse_path(path)); |
588 | path.map(Pat::Path).unwrap_or(Pat::Missing) | 588 | path.map(Pat::Path).unwrap_or(Pat::Missing) |
589 | } | 589 | } |
590 | ast::Pat::OrPat(p) => { | ||
591 | let pats = p.pats().map(|p| self.collect_pat(p)).collect(); | ||
592 | Pat::Or(pats) | ||
593 | } | ||
594 | ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat()), | ||
590 | ast::Pat::TuplePat(p) => { | 595 | ast::Pat::TuplePat(p) => { |
591 | let args = p.args().map(|p| self.collect_pat(p)).collect(); | 596 | let args = p.args().map(|p| self.collect_pat(p)).collect(); |
592 | Pat::Tuple(args) | 597 | Pat::Tuple(args) |
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs index a63552327..a58a7b21f 100644 --- a/crates/ra_hir_def/src/body/scope.rs +++ b/crates/ra_hir_def/src/body/scope.rs | |||
@@ -158,9 +158,7 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope | |||
158 | compute_expr_scopes(*expr, body, scopes, scope); | 158 | compute_expr_scopes(*expr, body, scopes, scope); |
159 | for arm in arms { | 159 | for arm in arms { |
160 | let scope = scopes.new_scope(scope); | 160 | let scope = scopes.new_scope(scope); |
161 | for pat in &arm.pats { | 161 | scopes.add_bindings(body, scope, arm.pat); |
162 | scopes.add_bindings(body, scope, *pat); | ||
163 | } | ||
164 | scopes.set_scope(arm.expr, scope); | 162 | scopes.set_scope(arm.expr, scope); |
165 | compute_expr_scopes(arm.expr, body, scopes, scope); | 163 | compute_expr_scopes(arm.expr, body, scopes, scope); |
166 | } | 164 | } |
@@ -194,7 +192,7 @@ mod tests { | |||
194 | let (off, code) = extract_offset(code); | 192 | let (off, code) = extract_offset(code); |
195 | let code = { | 193 | let code = { |
196 | let mut buf = String::new(); | 194 | let mut buf = String::new(); |
197 | let off = u32::from(off) as usize; | 195 | let off = off.to_usize(); |
198 | buf.push_str(&code[..off]); | 196 | buf.push_str(&code[..off]); |
199 | buf.push_str("marker"); | 197 | buf.push_str("marker"); |
200 | buf.push_str(&code[off..]); | 198 | buf.push_str(&code[off..]); |
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs index 035824403..9707c5527 100644 --- a/crates/ra_hir_def/src/expr.rs +++ b/crates/ra_hir_def/src/expr.rs | |||
@@ -202,7 +202,7 @@ pub enum Array { | |||
202 | 202 | ||
203 | #[derive(Debug, Clone, Eq, PartialEq)] | 203 | #[derive(Debug, Clone, Eq, PartialEq)] |
204 | pub struct MatchArm { | 204 | pub struct MatchArm { |
205 | pub pats: Vec<PatId>, | 205 | pub pat: PatId, |
206 | pub guard: Option<ExprId>, | 206 | pub guard: Option<ExprId>, |
207 | pub expr: ExprId, | 207 | pub expr: ExprId, |
208 | } | 208 | } |
@@ -382,6 +382,7 @@ pub enum Pat { | |||
382 | Missing, | 382 | Missing, |
383 | Wild, | 383 | Wild, |
384 | Tuple(Vec<PatId>), | 384 | Tuple(Vec<PatId>), |
385 | Or(Vec<PatId>), | ||
385 | Record { | 386 | Record { |
386 | path: Option<Path>, | 387 | path: Option<Path>, |
387 | args: Vec<RecordFieldPat>, | 388 | args: Vec<RecordFieldPat>, |
@@ -420,7 +421,7 @@ impl Pat { | |||
420 | Pat::Bind { subpat, .. } => { | 421 | Pat::Bind { subpat, .. } => { |
421 | subpat.iter().copied().for_each(f); | 422 | subpat.iter().copied().for_each(f); |
422 | } | 423 | } |
423 | Pat::Tuple(args) | Pat::TupleStruct { args, .. } => { | 424 | Pat::Or(args) | Pat::Tuple(args) | Pat::TupleStruct { args, .. } => { |
424 | args.iter().copied().for_each(f); | 425 | args.iter().copied().for_each(f); |
425 | } | 426 | } |
426 | Pat::Ref { pat, .. } => f(*pat), | 427 | Pat::Ref { pat, .. } => f(*pat), |
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index e9c28c730..f765e6edc 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs | |||
@@ -27,8 +27,16 @@ use crate::{ | |||
27 | /// Data about a generic parameter (to a function, struct, impl, ...). | 27 | /// Data about a generic parameter (to a function, struct, impl, ...). |
28 | #[derive(Clone, PartialEq, Eq, Debug)] | 28 | #[derive(Clone, PartialEq, Eq, Debug)] |
29 | pub struct TypeParamData { | 29 | pub struct TypeParamData { |
30 | pub name: Name, | 30 | pub name: Option<Name>, |
31 | pub default: Option<TypeRef>, | 31 | pub default: Option<TypeRef>, |
32 | pub provenance: TypeParamProvenance, | ||
33 | } | ||
34 | |||
35 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] | ||
36 | pub enum TypeParamProvenance { | ||
37 | TypeParamList, | ||
38 | TraitSelf, | ||
39 | ArgumentImplTrait, | ||
32 | } | 40 | } |
33 | 41 | ||
34 | /// Data about the generic parameters of a function, struct, impl, etc. | 42 | /// Data about the generic parameters of a function, struct, impl, etc. |
@@ -45,10 +53,17 @@ pub struct GenericParams { | |||
45 | /// associated type bindings like `Iterator<Item = u32>`. | 53 | /// associated type bindings like `Iterator<Item = u32>`. |
46 | #[derive(Clone, PartialEq, Eq, Debug)] | 54 | #[derive(Clone, PartialEq, Eq, Debug)] |
47 | pub struct WherePredicate { | 55 | pub struct WherePredicate { |
48 | pub type_ref: TypeRef, | 56 | pub target: WherePredicateTarget, |
49 | pub bound: TypeBound, | 57 | pub bound: TypeBound, |
50 | } | 58 | } |
51 | 59 | ||
60 | #[derive(Clone, PartialEq, Eq, Debug)] | ||
61 | pub enum WherePredicateTarget { | ||
62 | TypeRef(TypeRef), | ||
63 | /// For desugared where predicates that can directly refer to a type param. | ||
64 | TypeParam(LocalTypeParamId), | ||
65 | } | ||
66 | |||
52 | type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::TraitDef, ast::TypeParam>>; | 67 | type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::TraitDef, ast::TypeParam>>; |
53 | 68 | ||
54 | impl GenericParams { | 69 | impl GenericParams { |
@@ -68,6 +83,11 @@ impl GenericParams { | |||
68 | GenericDefId::FunctionId(it) => { | 83 | GenericDefId::FunctionId(it) => { |
69 | let src = it.lookup(db).source(db); | 84 | let src = it.lookup(db).source(db); |
70 | generics.fill(&mut sm, &src.value); | 85 | generics.fill(&mut sm, &src.value); |
86 | // lower `impl Trait` in arguments | ||
87 | let data = db.function_data(it); | ||
88 | for param in &data.params { | ||
89 | generics.fill_implicit_impl_trait_args(param); | ||
90 | } | ||
71 | src.file_id | 91 | src.file_id |
72 | } | 92 | } |
73 | GenericDefId::AdtId(AdtId::StructId(it)) => { | 93 | GenericDefId::AdtId(AdtId::StructId(it)) => { |
@@ -89,8 +109,11 @@ impl GenericParams { | |||
89 | let src = it.lookup(db).source(db); | 109 | let src = it.lookup(db).source(db); |
90 | 110 | ||
91 | // traits get the Self type as an implicit first type parameter | 111 | // traits get the Self type as an implicit first type parameter |
92 | let self_param_id = | 112 | let self_param_id = generics.types.alloc(TypeParamData { |
93 | generics.types.alloc(TypeParamData { name: name![Self], default: None }); | 113 | name: Some(name![Self]), |
114 | default: None, | ||
115 | provenance: TypeParamProvenance::TraitSelf, | ||
116 | }); | ||
94 | sm.insert(self_param_id, Either::Left(src.value.clone())); | 117 | sm.insert(self_param_id, Either::Left(src.value.clone())); |
95 | // add super traits as bounds on Self | 118 | // add super traits as bounds on Self |
96 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar | 119 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar |
@@ -142,7 +165,11 @@ impl GenericParams { | |||
142 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); | 165 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); |
143 | // FIXME: Use `Path::from_src` | 166 | // FIXME: Use `Path::from_src` |
144 | let default = type_param.default_type().map(TypeRef::from_ast); | 167 | let default = type_param.default_type().map(TypeRef::from_ast); |
145 | let param = TypeParamData { name: name.clone(), default }; | 168 | let param = TypeParamData { |
169 | name: Some(name.clone()), | ||
170 | default, | ||
171 | provenance: TypeParamProvenance::TypeParamList, | ||
172 | }; | ||
146 | let param_id = self.types.alloc(param); | 173 | let param_id = self.types.alloc(param); |
147 | sm.insert(param_id, Either::Right(type_param.clone())); | 174 | sm.insert(param_id, Either::Right(type_param.clone())); |
148 | 175 | ||
@@ -170,11 +197,43 @@ impl GenericParams { | |||
170 | return; | 197 | return; |
171 | } | 198 | } |
172 | let bound = TypeBound::from_ast(bound); | 199 | let bound = TypeBound::from_ast(bound); |
173 | self.where_predicates.push(WherePredicate { type_ref, bound }); | 200 | self.where_predicates |
201 | .push(WherePredicate { target: WherePredicateTarget::TypeRef(type_ref), bound }); | ||
202 | } | ||
203 | |||
204 | fn fill_implicit_impl_trait_args(&mut self, type_ref: &TypeRef) { | ||
205 | type_ref.walk(&mut |type_ref| { | ||
206 | if let TypeRef::ImplTrait(bounds) = type_ref { | ||
207 | let param = TypeParamData { | ||
208 | name: None, | ||
209 | default: None, | ||
210 | provenance: TypeParamProvenance::ArgumentImplTrait, | ||
211 | }; | ||
212 | let param_id = self.types.alloc(param); | ||
213 | for bound in bounds { | ||
214 | self.where_predicates.push(WherePredicate { | ||
215 | target: WherePredicateTarget::TypeParam(param_id), | ||
216 | bound: bound.clone(), | ||
217 | }); | ||
218 | } | ||
219 | } | ||
220 | }); | ||
174 | } | 221 | } |
175 | 222 | ||
176 | pub fn find_by_name(&self, name: &Name) -> Option<LocalTypeParamId> { | 223 | pub fn find_by_name(&self, name: &Name) -> Option<LocalTypeParamId> { |
177 | self.types.iter().find_map(|(id, p)| if &p.name == name { Some(id) } else { None }) | 224 | self.types |
225 | .iter() | ||
226 | .find_map(|(id, p)| if p.name.as_ref() == Some(name) { Some(id) } else { None }) | ||
227 | } | ||
228 | |||
229 | pub fn find_trait_self_param(&self) -> Option<LocalTypeParamId> { | ||
230 | self.types.iter().find_map(|(id, p)| { | ||
231 | if p.provenance == TypeParamProvenance::TraitSelf { | ||
232 | Some(id) | ||
233 | } else { | ||
234 | None | ||
235 | } | ||
236 | }) | ||
178 | } | 237 | } |
179 | } | 238 | } |
180 | 239 | ||
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index f7bac5801..05cf4646a 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs | |||
@@ -490,10 +490,12 @@ impl Scope { | |||
490 | } | 490 | } |
491 | Scope::GenericParams { params, def } => { | 491 | Scope::GenericParams { params, def } => { |
492 | for (local_id, param) in params.types.iter() { | 492 | for (local_id, param) in params.types.iter() { |
493 | f( | 493 | if let Some(name) = ¶m.name { |
494 | param.name.clone(), | 494 | f( |
495 | ScopeDef::GenericParam(TypeParamId { local_id, parent: *def }), | 495 | name.clone(), |
496 | ) | 496 | ScopeDef::GenericParam(TypeParamId { local_id, parent: *def }), |
497 | ) | ||
498 | } | ||
497 | } | 499 | } |
498 | } | 500 | } |
499 | Scope::ImplBlockScope(i) => { | 501 | Scope::ImplBlockScope(i) => { |
diff --git a/crates/ra_hir_def/src/type_ref.rs b/crates/ra_hir_def/src/type_ref.rs index 5f10e9a88..102fdb13d 100644 --- a/crates/ra_hir_def/src/type_ref.rs +++ b/crates/ra_hir_def/src/type_ref.rs | |||
@@ -124,6 +124,48 @@ impl TypeRef { | |||
124 | pub(crate) fn unit() -> TypeRef { | 124 | pub(crate) fn unit() -> TypeRef { |
125 | TypeRef::Tuple(Vec::new()) | 125 | TypeRef::Tuple(Vec::new()) |
126 | } | 126 | } |
127 | |||
128 | pub fn walk(&self, f: &mut impl FnMut(&TypeRef)) { | ||
129 | go(self, f); | ||
130 | |||
131 | fn go(type_ref: &TypeRef, f: &mut impl FnMut(&TypeRef)) { | ||
132 | f(type_ref); | ||
133 | match type_ref { | ||
134 | TypeRef::Fn(types) | TypeRef::Tuple(types) => types.iter().for_each(|t| go(t, f)), | ||
135 | TypeRef::RawPtr(type_ref, _) | ||
136 | | TypeRef::Reference(type_ref, _) | ||
137 | | TypeRef::Array(type_ref) | ||
138 | | TypeRef::Slice(type_ref) => go(&type_ref, f), | ||
139 | TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => { | ||
140 | for bound in bounds { | ||
141 | match bound { | ||
142 | TypeBound::Path(path) => go_path(path, f), | ||
143 | TypeBound::Error => (), | ||
144 | } | ||
145 | } | ||
146 | } | ||
147 | TypeRef::Path(path) => go_path(path, f), | ||
148 | TypeRef::Never | TypeRef::Placeholder | TypeRef::Error => {} | ||
149 | }; | ||
150 | } | ||
151 | |||
152 | fn go_path(path: &Path, f: &mut impl FnMut(&TypeRef)) { | ||
153 | if let Some(type_ref) = path.type_anchor() { | ||
154 | go(type_ref, f); | ||
155 | } | ||
156 | for segment in path.segments().iter() { | ||
157 | if let Some(args_and_bindings) = segment.args_and_bindings { | ||
158 | for arg in &args_and_bindings.args { | ||
159 | let crate::path::GenericArg::Type(type_ref) = arg; | ||
160 | go(type_ref, f); | ||
161 | } | ||
162 | for (_, type_ref) in &args_and_bindings.bindings { | ||
163 | go(type_ref, f); | ||
164 | } | ||
165 | } | ||
166 | } | ||
167 | } | ||
168 | } | ||
127 | } | 169 | } |
128 | 170 | ||
129 | pub(crate) fn type_bounds_from_ast(type_bounds_opt: Option<ast::TypeBoundList>) -> Vec<TypeBound> { | 171 | pub(crate) fn type_bounds_from_ast(type_bounds_opt: Option<ast::TypeBoundList>) -> Vec<TypeBound> { |
diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs index 133805bdb..b2e10f445 100644 --- a/crates/ra_hir_expand/src/name.rs +++ b/crates/ra_hir_expand/src/name.rs | |||
@@ -187,13 +187,6 @@ pub mod known { | |||
187 | PartialOrd, | 187 | PartialOrd, |
188 | Eq, | 188 | Eq, |
189 | PartialEq, | 189 | PartialEq, |
190 | // FIXME delete those after `ImportResolver` is removed. | ||
191 | hash, | ||
192 | fmt, | ||
193 | io, | ||
194 | Display, | ||
195 | Iterator, | ||
196 | Hasher, | ||
197 | ); | 190 | ); |
198 | 191 | ||
199 | // self/Self cannot be used as an identifier | 192 | // self/Self cannot be used as an identifier |
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs index eb521c7a0..e9bfcfa17 100644 --- a/crates/ra_hir_ty/src/db.rs +++ b/crates/ra_hir_ty/src/db.rs | |||
@@ -3,17 +3,18 @@ | |||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use hir_def::{ | 5 | use hir_def::{ |
6 | db::DefDatabase, DefWithBodyId, GenericDefId, ImplId, LocalStructFieldId, TraitId, VariantId, | 6 | db::DefDatabase, DefWithBodyId, GenericDefId, ImplId, LocalStructFieldId, TraitId, TypeParamId, |
7 | VariantId, | ||
7 | }; | 8 | }; |
8 | use ra_arena::map::ArenaMap; | 9 | use ra_arena::map::ArenaMap; |
9 | use ra_db::{salsa, CrateId}; | 10 | use ra_db::{impl_intern_key, salsa, CrateId}; |
10 | use ra_prof::profile; | 11 | use ra_prof::profile; |
11 | 12 | ||
12 | use crate::{ | 13 | use crate::{ |
13 | method_resolution::CrateImplBlocks, | 14 | method_resolution::CrateImplBlocks, |
14 | traits::{chalk, AssocTyValue, Impl}, | 15 | traits::{chalk, AssocTyValue, Impl}, |
15 | CallableDef, FnSig, GenericPredicate, InferenceResult, Substs, TraitRef, Ty, TyDefId, TypeCtor, | 16 | Binders, CallableDef, GenericPredicate, InferenceResult, PolyFnSig, Substs, TraitRef, Ty, |
16 | ValueTyDefId, | 17 | TyDefId, TypeCtor, ValueTyDefId, |
17 | }; | 18 | }; |
18 | 19 | ||
19 | #[salsa::query_group(HirDatabaseStorage)] | 20 | #[salsa::query_group(HirDatabaseStorage)] |
@@ -27,34 +28,33 @@ pub trait HirDatabase: DefDatabase { | |||
27 | 28 | ||
28 | #[salsa::invoke(crate::lower::ty_query)] | 29 | #[salsa::invoke(crate::lower::ty_query)] |
29 | #[salsa::cycle(crate::lower::ty_recover)] | 30 | #[salsa::cycle(crate::lower::ty_recover)] |
30 | fn ty(&self, def: TyDefId) -> Ty; | 31 | fn ty(&self, def: TyDefId) -> Binders<Ty>; |
31 | 32 | ||
32 | #[salsa::invoke(crate::lower::value_ty_query)] | 33 | #[salsa::invoke(crate::lower::value_ty_query)] |
33 | fn value_ty(&self, def: ValueTyDefId) -> Ty; | 34 | fn value_ty(&self, def: ValueTyDefId) -> Binders<Ty>; |
34 | 35 | ||
35 | #[salsa::invoke(crate::lower::impl_self_ty_query)] | 36 | #[salsa::invoke(crate::lower::impl_self_ty_query)] |
36 | #[salsa::cycle(crate::lower::impl_self_ty_recover)] | 37 | #[salsa::cycle(crate::lower::impl_self_ty_recover)] |
37 | fn impl_self_ty(&self, def: ImplId) -> Ty; | 38 | fn impl_self_ty(&self, def: ImplId) -> Binders<Ty>; |
38 | 39 | ||
39 | #[salsa::invoke(crate::lower::impl_trait_query)] | 40 | #[salsa::invoke(crate::lower::impl_trait_query)] |
40 | fn impl_trait(&self, def: ImplId) -> Option<TraitRef>; | 41 | fn impl_trait(&self, def: ImplId) -> Option<Binders<TraitRef>>; |
41 | 42 | ||
42 | #[salsa::invoke(crate::lower::field_types_query)] | 43 | #[salsa::invoke(crate::lower::field_types_query)] |
43 | fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Ty>>; | 44 | fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Binders<Ty>>>; |
44 | 45 | ||
45 | #[salsa::invoke(crate::callable_item_sig)] | 46 | #[salsa::invoke(crate::callable_item_sig)] |
46 | fn callable_item_signature(&self, def: CallableDef) -> FnSig; | 47 | fn callable_item_signature(&self, def: CallableDef) -> PolyFnSig; |
47 | 48 | ||
48 | #[salsa::invoke(crate::lower::generic_predicates_for_param_query)] | 49 | #[salsa::invoke(crate::lower::generic_predicates_for_param_query)] |
49 | #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)] | 50 | #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)] |
50 | fn generic_predicates_for_param( | 51 | fn generic_predicates_for_param( |
51 | &self, | 52 | &self, |
52 | def: GenericDefId, | 53 | param_id: TypeParamId, |
53 | param_idx: u32, | 54 | ) -> Arc<[Binders<GenericPredicate>]>; |
54 | ) -> Arc<[GenericPredicate]>; | ||
55 | 55 | ||
56 | #[salsa::invoke(crate::lower::generic_predicates_query)] | 56 | #[salsa::invoke(crate::lower::generic_predicates_query)] |
57 | fn generic_predicates(&self, def: GenericDefId) -> Arc<[GenericPredicate]>; | 57 | fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<GenericPredicate>]>; |
58 | 58 | ||
59 | #[salsa::invoke(crate::lower::generic_defaults_query)] | 59 | #[salsa::invoke(crate::lower::generic_defaults_query)] |
60 | fn generic_defaults(&self, def: GenericDefId) -> Substs; | 60 | fn generic_defaults(&self, def: GenericDefId) -> Substs; |
@@ -77,6 +77,8 @@ pub trait HirDatabase: DefDatabase { | |||
77 | #[salsa::interned] | 77 | #[salsa::interned] |
78 | fn intern_type_ctor(&self, type_ctor: TypeCtor) -> crate::TypeCtorId; | 78 | fn intern_type_ctor(&self, type_ctor: TypeCtor) -> crate::TypeCtorId; |
79 | #[salsa::interned] | 79 | #[salsa::interned] |
80 | fn intern_type_param_id(&self, param_id: TypeParamId) -> GlobalTypeParamId; | ||
81 | #[salsa::interned] | ||
80 | fn intern_chalk_impl(&self, impl_: Impl) -> crate::traits::GlobalImplId; | 82 | fn intern_chalk_impl(&self, impl_: Impl) -> crate::traits::GlobalImplId; |
81 | #[salsa::interned] | 83 | #[salsa::interned] |
82 | fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> crate::traits::AssocTyValueId; | 84 | fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> crate::traits::AssocTyValueId; |
@@ -117,3 +119,7 @@ fn infer(db: &impl HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> { | |||
117 | fn hir_database_is_object_safe() { | 119 | fn hir_database_is_object_safe() { |
118 | fn _assert_object_safe(_: &dyn HirDatabase) {} | 120 | fn _assert_object_safe(_: &dyn HirDatabase) {} |
119 | } | 121 | } |
122 | |||
123 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
124 | pub struct GlobalTypeParamId(salsa::InternId); | ||
125 | impl_intern_key!(GlobalTypeParamId); | ||
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index e2eda3134..a9d958c8b 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs | |||
@@ -34,7 +34,6 @@ use hir_expand::{diagnostics::DiagnosticSink, name::name}; | |||
34 | use ra_arena::map::ArenaMap; | 34 | use ra_arena::map::ArenaMap; |
35 | use ra_prof::profile; | 35 | use ra_prof::profile; |
36 | use ra_syntax::SmolStr; | 36 | use ra_syntax::SmolStr; |
37 | use test_utils::tested_by; | ||
38 | 37 | ||
39 | use super::{ | 38 | use super::{ |
40 | primitive::{FloatTy, IntTy}, | 39 | primitive::{FloatTy, IntTy}, |
@@ -42,7 +41,9 @@ use super::{ | |||
42 | ApplicationTy, GenericPredicate, InEnvironment, ProjectionTy, Substs, TraitEnvironment, | 41 | ApplicationTy, GenericPredicate, InEnvironment, ProjectionTy, Substs, TraitEnvironment, |
43 | TraitRef, Ty, TypeCtor, TypeWalk, Uncertain, | 42 | TraitRef, Ty, TypeCtor, TypeWalk, Uncertain, |
44 | }; | 43 | }; |
45 | use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic}; | 44 | use crate::{ |
45 | db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, | ||
46 | }; | ||
46 | 47 | ||
47 | pub(crate) use unify::unify; | 48 | pub(crate) use unify::unify; |
48 | 49 | ||
@@ -271,38 +272,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
271 | self.result.diagnostics.push(diagnostic); | 272 | self.result.diagnostics.push(diagnostic); |
272 | } | 273 | } |
273 | 274 | ||
274 | fn make_ty(&mut self, type_ref: &TypeRef) -> Ty { | 275 | fn make_ty_with_mode( |
275 | let ty = Ty::from_hir( | 276 | &mut self, |
276 | self.db, | 277 | type_ref: &TypeRef, |
277 | // FIXME use right resolver for block | 278 | impl_trait_mode: ImplTraitLoweringMode, |
278 | &self.resolver, | 279 | ) -> Ty { |
279 | type_ref, | 280 | // FIXME use right resolver for block |
280 | ); | 281 | let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver) |
282 | .with_impl_trait_mode(impl_trait_mode); | ||
283 | let ty = Ty::from_hir(&ctx, type_ref); | ||
281 | let ty = self.insert_type_vars(ty); | 284 | let ty = self.insert_type_vars(ty); |
282 | self.normalize_associated_types_in(ty) | 285 | self.normalize_associated_types_in(ty) |
283 | } | 286 | } |
284 | 287 | ||
285 | /// Replaces `impl Trait` in `ty` by type variables and obligations for | 288 | fn make_ty(&mut self, type_ref: &TypeRef) -> Ty { |
286 | /// those variables. This is done for function arguments when calling a | 289 | self.make_ty_with_mode(type_ref, ImplTraitLoweringMode::Disallowed) |
287 | /// function, and for return types when inside the function body, i.e. in | ||
288 | /// the cases where the `impl Trait` is 'transparent'. In other cases, `impl | ||
289 | /// Trait` is represented by `Ty::Opaque`. | ||
290 | fn insert_vars_for_impl_trait(&mut self, ty: Ty) -> Ty { | ||
291 | ty.fold(&mut |ty| match ty { | ||
292 | Ty::Opaque(preds) => { | ||
293 | tested_by!(insert_vars_for_impl_trait); | ||
294 | let var = self.table.new_type_var(); | ||
295 | let var_subst = Substs::builder(1).push(var.clone()).build(); | ||
296 | self.obligations.extend( | ||
297 | preds | ||
298 | .iter() | ||
299 | .map(|pred| pred.clone().subst_bound_vars(&var_subst)) | ||
300 | .filter_map(Obligation::from_predicate), | ||
301 | ); | ||
302 | var | ||
303 | } | ||
304 | _ => ty, | ||
305 | }) | ||
306 | } | 290 | } |
307 | 291 | ||
308 | /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. | 292 | /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. |
@@ -446,19 +430,20 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
446 | None => return (Ty::Unknown, None), | 430 | None => return (Ty::Unknown, None), |
447 | }; | 431 | }; |
448 | let resolver = &self.resolver; | 432 | let resolver = &self.resolver; |
433 | let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); | ||
449 | // FIXME: this should resolve assoc items as well, see this example: | 434 | // FIXME: this should resolve assoc items as well, see this example: |
450 | // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521 | 435 | // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521 |
451 | match resolver.resolve_path_in_type_ns_fully(self.db, path.mod_path()) { | 436 | match resolver.resolve_path_in_type_ns_fully(self.db, path.mod_path()) { |
452 | Some(TypeNs::AdtId(AdtId::StructId(strukt))) => { | 437 | Some(TypeNs::AdtId(AdtId::StructId(strukt))) => { |
453 | let substs = Ty::substs_from_path(self.db, resolver, path, strukt.into()); | 438 | let substs = Ty::substs_from_path(&ctx, path, strukt.into()); |
454 | let ty = self.db.ty(strukt.into()); | 439 | let ty = self.db.ty(strukt.into()); |
455 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | 440 | let ty = self.insert_type_vars(ty.subst(&substs)); |
456 | (ty, Some(strukt.into())) | 441 | (ty, Some(strukt.into())) |
457 | } | 442 | } |
458 | Some(TypeNs::EnumVariantId(var)) => { | 443 | Some(TypeNs::EnumVariantId(var)) => { |
459 | let substs = Ty::substs_from_path(self.db, resolver, path, var.into()); | 444 | let substs = Ty::substs_from_path(&ctx, path, var.into()); |
460 | let ty = self.db.ty(var.parent.into()); | 445 | let ty = self.db.ty(var.parent.into()); |
461 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | 446 | let ty = self.insert_type_vars(ty.subst(&substs)); |
462 | (ty, Some(var.into())) | 447 | (ty, Some(var.into())) |
463 | } | 448 | } |
464 | Some(_) | None => (Ty::Unknown, None), | 449 | Some(_) | None => (Ty::Unknown, None), |
@@ -471,13 +456,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
471 | 456 | ||
472 | fn collect_fn(&mut self, data: &FunctionData) { | 457 | fn collect_fn(&mut self, data: &FunctionData) { |
473 | let body = Arc::clone(&self.body); // avoid borrow checker problem | 458 | let body = Arc::clone(&self.body); // avoid borrow checker problem |
474 | for (type_ref, pat) in data.params.iter().zip(body.params.iter()) { | 459 | let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver) |
475 | let ty = self.make_ty(type_ref); | 460 | .with_impl_trait_mode(ImplTraitLoweringMode::Param); |
461 | let param_tys = | ||
462 | data.params.iter().map(|type_ref| Ty::from_hir(&ctx, type_ref)).collect::<Vec<_>>(); | ||
463 | for (ty, pat) in param_tys.into_iter().zip(body.params.iter()) { | ||
464 | let ty = self.insert_type_vars(ty); | ||
465 | let ty = self.normalize_associated_types_in(ty); | ||
476 | 466 | ||
477 | self.infer_pat(*pat, &ty, BindingMode::default()); | 467 | self.infer_pat(*pat, &ty, BindingMode::default()); |
478 | } | 468 | } |
479 | let return_ty = self.make_ty(&data.ret_type); | 469 | let return_ty = self.make_ty_with_mode(&data.ret_type, ImplTraitLoweringMode::Disallowed); // FIXME implement RPIT |
480 | self.return_ty = self.insert_vars_for_impl_trait(return_ty); | 470 | self.return_ty = return_ty; |
481 | } | 471 | } |
482 | 472 | ||
483 | fn infer_body(&mut self) { | 473 | fn infer_body(&mut self) { |
diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs index 83c0c2c3f..f68a1439f 100644 --- a/crates/ra_hir_ty/src/infer/coerce.rs +++ b/crates/ra_hir_ty/src/infer/coerce.rs | |||
@@ -57,8 +57,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
57 | let trait_ref = db.impl_trait(impl_id)?; | 57 | let trait_ref = db.impl_trait(impl_id)?; |
58 | 58 | ||
59 | // `CoerseUnsized` has one generic parameter for the target type. | 59 | // `CoerseUnsized` has one generic parameter for the target type. |
60 | let cur_from_ty = trait_ref.substs.0.get(0)?; | 60 | let cur_from_ty = trait_ref.value.substs.0.get(0)?; |
61 | let cur_to_ty = trait_ref.substs.0.get(1)?; | 61 | let cur_to_ty = trait_ref.value.substs.0.get(1)?; |
62 | 62 | ||
63 | match (&cur_from_ty, cur_to_ty) { | 63 | match (&cur_from_ty, cur_to_ty) { |
64 | (ty_app!(ctor1, st1), ty_app!(ctor2, st2)) => { | 64 | (ty_app!(ctor1, st1), ty_app!(ctor2, st2)) => { |
@@ -66,9 +66,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
66 | // This works for smart-pointer-like coercion, which covers all impls from std. | 66 | // This works for smart-pointer-like coercion, which covers all impls from std. |
67 | st1.iter().zip(st2.iter()).enumerate().find_map(|(i, (ty1, ty2))| { | 67 | st1.iter().zip(st2.iter()).enumerate().find_map(|(i, (ty1, ty2))| { |
68 | match (ty1, ty2) { | 68 | match (ty1, ty2) { |
69 | (Ty::Param { idx: p1, .. }, Ty::Param { idx: p2, .. }) | 69 | (Ty::Bound(idx1), Ty::Bound(idx2)) if idx1 != idx2 => { |
70 | if p1 != p2 => | ||
71 | { | ||
72 | Some(((*ctor1, *ctor2), i)) | 70 | Some(((*ctor1, *ctor2), i)) |
73 | } | 71 | } |
74 | _ => None, | 72 | _ => None, |
@@ -256,8 +254,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
256 | let unsize_generic_index = { | 254 | let unsize_generic_index = { |
257 | let mut index = None; | 255 | let mut index = None; |
258 | let mut multiple_param = false; | 256 | let mut multiple_param = false; |
259 | field_tys[last_field_id].walk(&mut |ty| match ty { | 257 | field_tys[last_field_id].value.walk(&mut |ty| match ty { |
260 | &Ty::Param { idx, .. } => { | 258 | &Ty::Bound(idx) => { |
261 | if index.is_none() { | 259 | if index.is_none() { |
262 | index = Some(idx); | 260 | index = Some(idx); |
263 | } else if Some(idx) != index { | 261 | } else if Some(idx) != index { |
@@ -276,10 +274,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
276 | // Check other fields do not involve it. | 274 | // Check other fields do not involve it. |
277 | let mut multiple_used = false; | 275 | let mut multiple_used = false; |
278 | fields.for_each(|(field_id, _data)| { | 276 | fields.for_each(|(field_id, _data)| { |
279 | field_tys[field_id].walk(&mut |ty| match ty { | 277 | field_tys[field_id].value.walk(&mut |ty| match ty { |
280 | &Ty::Param { idx, .. } if idx == unsize_generic_index => { | 278 | &Ty::Bound(idx) if idx == unsize_generic_index => multiple_used = true, |
281 | multiple_used = true | ||
282 | } | ||
283 | _ => {} | 279 | _ => {} |
284 | }) | 280 | }) |
285 | }); | 281 | }); |
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 31259a01d..39d8bc0ca 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs | |||
@@ -10,7 +10,7 @@ use hir_def::{ | |||
10 | resolver::resolver_for_expr, | 10 | resolver::resolver_for_expr, |
11 | AdtId, AssocContainerId, Lookup, StructFieldId, | 11 | AdtId, AssocContainerId, Lookup, StructFieldId, |
12 | }; | 12 | }; |
13 | use hir_expand::name::{name, Name}; | 13 | use hir_expand::name::Name; |
14 | use ra_syntax::ast::RangeOp; | 14 | use ra_syntax::ast::RangeOp; |
15 | 15 | ||
16 | use crate::{ | 16 | use crate::{ |
@@ -19,8 +19,8 @@ use crate::{ | |||
19 | method_resolution, op, | 19 | method_resolution, op, |
20 | traits::InEnvironment, | 20 | traits::InEnvironment, |
21 | utils::{generics, variant_data, Generics}, | 21 | utils::{generics, variant_data, Generics}, |
22 | ApplicationTy, CallableDef, InferTy, IntTy, Mutability, Obligation, Substs, TraitRef, Ty, | 22 | ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Substs, TraitRef, |
23 | TypeCtor, TypeWalk, Uncertain, | 23 | Ty, TypeCtor, Uncertain, |
24 | }; | 24 | }; |
25 | 25 | ||
26 | use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; | 26 | use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; |
@@ -165,12 +165,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
165 | Expr::Match { expr, arms } => { | 165 | Expr::Match { expr, arms } => { |
166 | let input_ty = self.infer_expr(*expr, &Expectation::none()); | 166 | let input_ty = self.infer_expr(*expr, &Expectation::none()); |
167 | 167 | ||
168 | let mut result_ty = self.table.new_maybe_never_type_var(); | 168 | let mut result_ty = if arms.len() == 0 { |
169 | Ty::simple(TypeCtor::Never) | ||
170 | } else { | ||
171 | self.table.new_type_var() | ||
172 | }; | ||
169 | 173 | ||
170 | for arm in arms { | 174 | for arm in arms { |
171 | for &pat in &arm.pats { | 175 | let _pat_ty = self.infer_pat(arm.pat, &input_ty, BindingMode::default()); |
172 | let _pat_ty = self.infer_pat(pat, &input_ty, BindingMode::default()); | ||
173 | } | ||
174 | if let Some(guard_expr) = arm.guard { | 176 | if let Some(guard_expr) = arm.guard { |
175 | self.infer_expr( | 177 | self.infer_expr( |
176 | guard_expr, | 178 | guard_expr, |
@@ -236,8 +238,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
236 | self.result.record_field_resolutions.insert(field.expr, field_def); | 238 | self.result.record_field_resolutions.insert(field.expr, field_def); |
237 | } | 239 | } |
238 | let field_ty = field_def | 240 | let field_ty = field_def |
239 | .map_or(Ty::Unknown, |it| field_types[it.local_id].clone()) | 241 | .map_or(Ty::Unknown, |it| field_types[it.local_id].clone().subst(&substs)); |
240 | .subst(&substs); | ||
241 | self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty)); | 242 | self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty)); |
242 | } | 243 | } |
243 | if let Some(expr) = spread { | 244 | if let Some(expr) = spread { |
@@ -588,10 +589,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
588 | self.write_method_resolution(tgt_expr, func); | 589 | self.write_method_resolution(tgt_expr, func); |
589 | (ty, self.db.value_ty(func.into()), Some(generics(self.db, func.into()))) | 590 | (ty, self.db.value_ty(func.into()), Some(generics(self.db, func.into()))) |
590 | } | 591 | } |
591 | None => (receiver_ty, Ty::Unknown, None), | 592 | None => (receiver_ty, Binders::new(0, Ty::Unknown), None), |
592 | }; | 593 | }; |
593 | let substs = self.substs_for_method_call(def_generics, generic_args, &derefed_receiver_ty); | 594 | let substs = self.substs_for_method_call(def_generics, generic_args, &derefed_receiver_ty); |
594 | let method_ty = method_ty.apply_substs(substs); | 595 | let method_ty = method_ty.subst(&substs); |
595 | let method_ty = self.insert_type_vars(method_ty); | 596 | let method_ty = self.insert_type_vars(method_ty); |
596 | self.register_obligations_for_call(&method_ty); | 597 | self.register_obligations_for_call(&method_ty); |
597 | let (expected_receiver_ty, param_tys, ret_ty) = match method_ty.callable_sig(self.db) { | 598 | let (expected_receiver_ty, param_tys, ret_ty) = match method_ty.callable_sig(self.db) { |
@@ -635,7 +636,6 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
635 | continue; | 636 | continue; |
636 | } | 637 | } |
637 | 638 | ||
638 | let param_ty = self.insert_vars_for_impl_trait(param_ty); | ||
639 | let param_ty = self.normalize_associated_types_in(param_ty); | 639 | let param_ty = self.normalize_associated_types_in(param_ty); |
640 | self.infer_expr_coerce(arg, &Expectation::has_type(param_ty.clone())); | 640 | self.infer_expr_coerce(arg, &Expectation::has_type(param_ty.clone())); |
641 | } | 641 | } |
@@ -648,13 +648,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
648 | generic_args: Option<&GenericArgs>, | 648 | generic_args: Option<&GenericArgs>, |
649 | receiver_ty: &Ty, | 649 | receiver_ty: &Ty, |
650 | ) -> Substs { | 650 | ) -> Substs { |
651 | let (total_len, _parent_len, child_len) = | 651 | let (parent_params, self_params, type_params, impl_trait_params) = |
652 | def_generics.as_ref().map_or((0, 0, 0), |g| g.len_split()); | 652 | def_generics.as_ref().map_or((0, 0, 0, 0), |g| g.provenance_split()); |
653 | assert_eq!(self_params, 0); // method shouldn't have another Self param | ||
654 | let total_len = parent_params + type_params + impl_trait_params; | ||
653 | let mut substs = Vec::with_capacity(total_len); | 655 | let mut substs = Vec::with_capacity(total_len); |
654 | // Parent arguments are unknown, except for the receiver type | 656 | // Parent arguments are unknown, except for the receiver type |
655 | if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) { | 657 | if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) { |
656 | for (_id, param) in parent_generics { | 658 | for (_id, param) in parent_generics { |
657 | if param.name == name![Self] { | 659 | if param.provenance == hir_def::generics::TypeParamProvenance::TraitSelf { |
658 | substs.push(receiver_ty.clone()); | 660 | substs.push(receiver_ty.clone()); |
659 | } else { | 661 | } else { |
660 | substs.push(Ty::Unknown); | 662 | substs.push(Ty::Unknown); |
@@ -664,7 +666,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
664 | // handle provided type arguments | 666 | // handle provided type arguments |
665 | if let Some(generic_args) = generic_args { | 667 | if let Some(generic_args) = generic_args { |
666 | // if args are provided, it should be all of them, but we can't rely on that | 668 | // if args are provided, it should be all of them, but we can't rely on that |
667 | for arg in generic_args.args.iter().take(child_len) { | 669 | for arg in generic_args.args.iter().take(type_params) { |
668 | match arg { | 670 | match arg { |
669 | GenericArg::Type(type_ref) => { | 671 | GenericArg::Type(type_ref) => { |
670 | let ty = self.make_ty(type_ref); | 672 | let ty = self.make_ty(type_ref); |
diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs index a14662884..a5dfdf6c4 100644 --- a/crates/ra_hir_ty/src/infer/pat.rs +++ b/crates/ra_hir_ty/src/infer/pat.rs | |||
@@ -12,7 +12,7 @@ use hir_expand::name::Name; | |||
12 | use test_utils::tested_by; | 12 | use test_utils::tested_by; |
13 | 13 | ||
14 | use super::{BindingMode, InferenceContext}; | 14 | use super::{BindingMode, InferenceContext}; |
15 | use crate::{db::HirDatabase, utils::variant_data, Substs, Ty, TypeCtor, TypeWalk}; | 15 | use crate::{db::HirDatabase, utils::variant_data, Substs, Ty, TypeCtor}; |
16 | 16 | ||
17 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | 17 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { |
18 | fn infer_tuple_struct_pat( | 18 | fn infer_tuple_struct_pat( |
@@ -34,8 +34,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
34 | let expected_ty = var_data | 34 | let expected_ty = var_data |
35 | .as_ref() | 35 | .as_ref() |
36 | .and_then(|d| d.field(&Name::new_tuple_field(i))) | 36 | .and_then(|d| d.field(&Name::new_tuple_field(i))) |
37 | .map_or(Ty::Unknown, |field| field_tys[field].clone()) | 37 | .map_or(Ty::Unknown, |field| field_tys[field].clone().subst(&substs)); |
38 | .subst(&substs); | ||
39 | let expected_ty = self.normalize_associated_types_in(expected_ty); | 38 | let expected_ty = self.normalize_associated_types_in(expected_ty); |
40 | self.infer_pat(subpat, &expected_ty, default_bm); | 39 | self.infer_pat(subpat, &expected_ty, default_bm); |
41 | } | 40 | } |
@@ -65,7 +64,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
65 | for subpat in subpats { | 64 | for subpat in subpats { |
66 | let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name)); | 65 | let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name)); |
67 | let expected_ty = | 66 | let expected_ty = |
68 | matching_field.map_or(Ty::Unknown, |field| field_tys[field].clone()).subst(&substs); | 67 | matching_field.map_or(Ty::Unknown, |field| field_tys[field].clone().subst(&substs)); |
69 | let expected_ty = self.normalize_associated_types_in(expected_ty); | 68 | let expected_ty = self.normalize_associated_types_in(expected_ty); |
70 | self.infer_pat(subpat.pat, &expected_ty, default_bm); | 69 | self.infer_pat(subpat.pat, &expected_ty, default_bm); |
71 | } | 70 | } |
@@ -83,6 +82,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
83 | 82 | ||
84 | let is_non_ref_pat = match &body[pat] { | 83 | let is_non_ref_pat = match &body[pat] { |
85 | Pat::Tuple(..) | 84 | Pat::Tuple(..) |
85 | | Pat::Or(..) | ||
86 | | Pat::TupleStruct { .. } | 86 | | Pat::TupleStruct { .. } |
87 | | Pat::Record { .. } | 87 | | Pat::Record { .. } |
88 | | Pat::Range { .. } | 88 | | Pat::Range { .. } |
@@ -127,6 +127,17 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
127 | 127 | ||
128 | Ty::apply(TypeCtor::Tuple { cardinality: args.len() as u16 }, Substs(inner_tys)) | 128 | Ty::apply(TypeCtor::Tuple { cardinality: args.len() as u16 }, Substs(inner_tys)) |
129 | } | 129 | } |
130 | Pat::Or(ref pats) => { | ||
131 | if let Some((first_pat, rest)) = pats.split_first() { | ||
132 | let ty = self.infer_pat(*first_pat, expected, default_bm); | ||
133 | for pat in rest { | ||
134 | self.infer_pat(*pat, expected, default_bm); | ||
135 | } | ||
136 | ty | ||
137 | } else { | ||
138 | Ty::Unknown | ||
139 | } | ||
140 | } | ||
130 | Pat::Ref { pat, mutability } => { | 141 | Pat::Ref { pat, mutability } => { |
131 | let expectation = match expected.as_reference() { | 142 | let expectation = match expected.as_reference() { |
132 | Some((inner_ty, exp_mut)) => { | 143 | Some((inner_ty, exp_mut)) => { |
diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs index 2c1d4831d..686ce7a21 100644 --- a/crates/ra_hir_ty/src/infer/path.rs +++ b/crates/ra_hir_ty/src/infer/path.rs | |||
@@ -9,9 +9,9 @@ use hir_def::{ | |||
9 | }; | 9 | }; |
10 | use hir_expand::name::Name; | 10 | use hir_expand::name::Name; |
11 | 11 | ||
12 | use crate::{db::HirDatabase, method_resolution, Substs, Ty, TypeWalk, ValueTyDefId}; | 12 | use crate::{db::HirDatabase, method_resolution, Substs, Ty, ValueTyDefId}; |
13 | 13 | ||
14 | use super::{ExprOrPatId, InferenceContext, TraitEnvironment, TraitRef}; | 14 | use super::{ExprOrPatId, InferenceContext, TraitRef}; |
15 | 15 | ||
16 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | 16 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { |
17 | pub(super) fn infer_path( | 17 | pub(super) fn infer_path( |
@@ -39,7 +39,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
39 | } | 39 | } |
40 | let ty = self.make_ty(type_ref); | 40 | let ty = self.make_ty(type_ref); |
41 | let remaining_segments_for_ty = path.segments().take(path.segments().len() - 1); | 41 | let remaining_segments_for_ty = path.segments().take(path.segments().len() - 1); |
42 | let ty = Ty::from_type_relative_path(self.db, resolver, ty, remaining_segments_for_ty); | 42 | let ctx = crate::lower::TyLoweringContext::new(self.db, &resolver); |
43 | let ty = Ty::from_type_relative_path(&ctx, ty, remaining_segments_for_ty); | ||
43 | self.resolve_ty_assoc_item( | 44 | self.resolve_ty_assoc_item( |
44 | ty, | 45 | ty, |
45 | &path.segments().last().expect("path had at least one segment").name, | 46 | &path.segments().last().expect("path had at least one segment").name, |
@@ -69,12 +70,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
69 | ValueNs::EnumVariantId(it) => it.into(), | 70 | ValueNs::EnumVariantId(it) => it.into(), |
70 | }; | 71 | }; |
71 | 72 | ||
72 | let mut ty = self.db.value_ty(typable); | 73 | let ty = self.db.value_ty(typable); |
73 | if let Some(self_subst) = self_subst { | 74 | // self_subst is just for the parent |
74 | ty = ty.subst(&self_subst); | 75 | let parent_substs = self_subst.unwrap_or_else(Substs::empty); |
75 | } | 76 | let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); |
76 | let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); | 77 | let substs = Ty::substs_from_path(&ctx, path, typable); |
77 | let ty = ty.subst(&substs); | 78 | let full_substs = Substs::builder(substs.len()) |
79 | .use_parent_substs(&parent_substs) | ||
80 | .fill(substs.0[parent_substs.len()..].iter().cloned()) | ||
81 | .build(); | ||
82 | let ty = ty.subst(&full_substs); | ||
78 | Some(ty) | 83 | Some(ty) |
79 | } | 84 | } |
80 | 85 | ||
@@ -98,13 +103,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
98 | (TypeNs::TraitId(trait_), true) => { | 103 | (TypeNs::TraitId(trait_), true) => { |
99 | let segment = | 104 | let segment = |
100 | remaining_segments.last().expect("there should be at least one segment here"); | 105 | remaining_segments.last().expect("there should be at least one segment here"); |
101 | let trait_ref = TraitRef::from_resolved_path( | 106 | let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); |
102 | self.db, | 107 | let trait_ref = |
103 | &self.resolver, | 108 | TraitRef::from_resolved_path(&ctx, trait_.into(), resolved_segment, None); |
104 | trait_.into(), | ||
105 | resolved_segment, | ||
106 | None, | ||
107 | ); | ||
108 | self.resolve_trait_assoc_item(trait_ref, segment, id) | 109 | self.resolve_trait_assoc_item(trait_ref, segment, id) |
109 | } | 110 | } |
110 | (def, _) => { | 111 | (def, _) => { |
@@ -114,9 +115,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
114 | // as Iterator>::Item::default`) | 115 | // as Iterator>::Item::default`) |
115 | let remaining_segments_for_ty = | 116 | let remaining_segments_for_ty = |
116 | remaining_segments.take(remaining_segments.len() - 1); | 117 | remaining_segments.take(remaining_segments.len() - 1); |
118 | let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); | ||
117 | let ty = Ty::from_partly_resolved_hir_path( | 119 | let ty = Ty::from_partly_resolved_hir_path( |
118 | self.db, | 120 | &ctx, |
119 | &self.resolver, | ||
120 | def, | 121 | def, |
121 | resolved_segment, | 122 | resolved_segment, |
122 | remaining_segments_for_ty, | 123 | remaining_segments_for_ty, |
@@ -173,13 +174,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
173 | AssocItemId::ConstId(c) => ValueNs::ConstId(c), | 174 | AssocItemId::ConstId(c) => ValueNs::ConstId(c), |
174 | AssocItemId::TypeAliasId(_) => unreachable!(), | 175 | AssocItemId::TypeAliasId(_) => unreachable!(), |
175 | }; | 176 | }; |
176 | let substs = Substs::build_for_def(self.db, item) | ||
177 | .use_parent_substs(&trait_ref.substs) | ||
178 | .fill_with_params() | ||
179 | .build(); | ||
180 | 177 | ||
181 | self.write_assoc_resolution(id, item); | 178 | self.write_assoc_resolution(id, item); |
182 | Some((def, Some(substs))) | 179 | Some((def, Some(trait_ref.substs))) |
183 | } | 180 | } |
184 | 181 | ||
185 | fn resolve_ty_assoc_item( | 182 | fn resolve_ty_assoc_item( |
@@ -193,14 +190,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
193 | } | 190 | } |
194 | 191 | ||
195 | let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone()); | 192 | let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone()); |
196 | let env = TraitEnvironment::lower(self.db, &self.resolver); | ||
197 | let krate = self.resolver.krate()?; | 193 | let krate = self.resolver.krate()?; |
198 | let traits_in_scope = self.resolver.traits_in_scope(self.db); | 194 | let traits_in_scope = self.resolver.traits_in_scope(self.db); |
199 | 195 | ||
200 | method_resolution::iterate_method_candidates( | 196 | method_resolution::iterate_method_candidates( |
201 | &canonical_ty.value, | 197 | &canonical_ty.value, |
202 | self.db, | 198 | self.db, |
203 | env, | 199 | self.trait_env.clone(), |
204 | krate, | 200 | krate, |
205 | &traits_in_scope, | 201 | &traits_in_scope, |
206 | Some(name), | 202 | Some(name), |
@@ -219,12 +215,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
219 | .fill(iter::repeat_with(|| self.table.new_type_var())) | 215 | .fill(iter::repeat_with(|| self.table.new_type_var())) |
220 | .build(); | 216 | .build(); |
221 | let impl_self_ty = self.db.impl_self_ty(impl_id).subst(&impl_substs); | 217 | let impl_self_ty = self.db.impl_self_ty(impl_id).subst(&impl_substs); |
222 | let substs = Substs::build_for_def(self.db, item) | ||
223 | .use_parent_substs(&impl_substs) | ||
224 | .fill_with_params() | ||
225 | .build(); | ||
226 | self.unify(&impl_self_ty, &ty); | 218 | self.unify(&impl_self_ty, &ty); |
227 | Some(substs) | 219 | Some(impl_substs) |
228 | } | 220 | } |
229 | AssocContainerId::TraitId(trait_) => { | 221 | AssocContainerId::TraitId(trait_) => { |
230 | // we're picking this method | 222 | // we're picking this method |
@@ -232,15 +224,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
232 | .push(ty.clone()) | 224 | .push(ty.clone()) |
233 | .fill(std::iter::repeat_with(|| self.table.new_type_var())) | 225 | .fill(std::iter::repeat_with(|| self.table.new_type_var())) |
234 | .build(); | 226 | .build(); |
235 | let substs = Substs::build_for_def(self.db, item) | ||
236 | .use_parent_substs(&trait_substs) | ||
237 | .fill_with_params() | ||
238 | .build(); | ||
239 | self.obligations.push(super::Obligation::Trait(TraitRef { | 227 | self.obligations.push(super::Obligation::Trait(TraitRef { |
240 | trait_, | 228 | trait_, |
241 | substs: trait_substs, | 229 | substs: trait_substs.clone(), |
242 | })); | 230 | })); |
243 | Some(substs) | 231 | Some(trait_substs) |
244 | } | 232 | } |
245 | AssocContainerId::ContainerId(_) => None, | 233 | AssocContainerId::ContainerId(_) => None, |
246 | }; | 234 | }; |
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index 08d501ccd..c5fe18c85 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs | |||
@@ -44,8 +44,8 @@ use std::sync::Arc; | |||
44 | use std::{fmt, iter, mem}; | 44 | use std::{fmt, iter, mem}; |
45 | 45 | ||
46 | use hir_def::{ | 46 | use hir_def::{ |
47 | expr::ExprId, type_ref::Mutability, AdtId, AssocContainerId, DefWithBodyId, GenericDefId, | 47 | expr::ExprId, generics::TypeParamProvenance, type_ref::Mutability, AdtId, AssocContainerId, |
48 | HasModule, Lookup, TraitId, TypeAliasId, | 48 | DefWithBodyId, GenericDefId, HasModule, Lookup, TraitId, TypeAliasId, TypeParamId, |
49 | }; | 49 | }; |
50 | use hir_expand::name::Name; | 50 | use hir_expand::name::Name; |
51 | use ra_db::{impl_intern_key, salsa, CrateId}; | 51 | use ra_db::{impl_intern_key, salsa, CrateId}; |
@@ -60,7 +60,9 @@ use display::{HirDisplay, HirFormatter}; | |||
60 | pub use autoderef::autoderef; | 60 | pub use autoderef::autoderef; |
61 | pub use infer::{do_infer_query, InferTy, InferenceResult}; | 61 | pub use infer::{do_infer_query, InferTy, InferenceResult}; |
62 | pub use lower::CallableDef; | 62 | pub use lower::CallableDef; |
63 | pub use lower::{callable_item_sig, TyDefId, ValueTyDefId}; | 63 | pub use lower::{ |
64 | callable_item_sig, ImplTraitLoweringMode, TyDefId, TyLoweringContext, ValueTyDefId, | ||
65 | }; | ||
64 | pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; | 66 | pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; |
65 | 67 | ||
66 | /// A type constructor or type name: this might be something like the primitive | 68 | /// A type constructor or type name: this might be something like the primitive |
@@ -285,22 +287,20 @@ pub enum Ty { | |||
285 | /// trait and all its parameters are fully known. | 287 | /// trait and all its parameters are fully known. |
286 | Projection(ProjectionTy), | 288 | Projection(ProjectionTy), |
287 | 289 | ||
288 | /// A type parameter; for example, `T` in `fn f<T>(x: T) {} | 290 | /// A placeholder for a type parameter; for example, `T` in `fn f<T>(x: T) |
289 | Param { | 291 | /// {}` when we're type-checking the body of that function. In this |
290 | /// The index of the parameter (starting with parameters from the | 292 | /// situation, we know this stands for *some* type, but don't know the exact |
291 | /// surrounding impl, then the current function). | 293 | /// type. |
292 | idx: u32, | 294 | Param(TypeParamId), |
293 | /// The name of the parameter, for displaying. | 295 | |
294 | // FIXME get rid of this | 296 | /// A bound type variable. This is used in various places: when representing |
295 | name: Name, | 297 | /// some polymorphic type like the type of function `fn f<T>`, the type |
296 | }, | 298 | /// parameters get turned into variables; during trait resolution, inference |
297 | 299 | /// variables get turned into bound variables and back; and in `Dyn` the | |
298 | /// A bound type variable. Used during trait resolution to represent Chalk | 300 | /// `Self` type is represented with a bound variable as well. |
299 | /// variables, and in `Dyn` and `Opaque` bounds to represent the `Self` type. | ||
300 | Bound(u32), | 301 | Bound(u32), |
301 | 302 | ||
302 | /// A type variable used during type checking. Not to be confused with a | 303 | /// A type variable used during type checking. |
303 | /// type parameter. | ||
304 | Infer(InferTy), | 304 | Infer(InferTy), |
305 | 305 | ||
306 | /// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust). | 306 | /// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust). |
@@ -364,15 +364,19 @@ impl Substs { | |||
364 | } | 364 | } |
365 | 365 | ||
366 | /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). | 366 | /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). |
367 | pub(crate) fn identity(generic_params: &Generics) -> Substs { | 367 | pub(crate) fn type_params_for_generics(generic_params: &Generics) -> Substs { |
368 | Substs( | 368 | Substs(generic_params.iter().map(|(id, _)| Ty::Param(id)).collect()) |
369 | generic_params.iter().map(|(idx, p)| Ty::Param { idx, name: p.name.clone() }).collect(), | 369 | } |
370 | ) | 370 | |
371 | /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). | ||
372 | pub fn type_params(db: &impl HirDatabase, def: impl Into<GenericDefId>) -> Substs { | ||
373 | let params = generics(db, def.into()); | ||
374 | Substs::type_params_for_generics(¶ms) | ||
371 | } | 375 | } |
372 | 376 | ||
373 | /// Return Substs that replace each parameter by a bound variable. | 377 | /// Return Substs that replace each parameter by a bound variable. |
374 | pub(crate) fn bound_vars(generic_params: &Generics) -> Substs { | 378 | pub(crate) fn bound_vars(generic_params: &Generics) -> Substs { |
375 | Substs(generic_params.iter().map(|(idx, _p)| Ty::Bound(idx)).collect()) | 379 | Substs(generic_params.iter().enumerate().map(|(idx, _)| Ty::Bound(idx as u32)).collect()) |
376 | } | 380 | } |
377 | 381 | ||
378 | pub fn build_for_def(db: &impl HirDatabase, def: impl Into<GenericDefId>) -> SubstsBuilder { | 382 | pub fn build_for_def(db: &impl HirDatabase, def: impl Into<GenericDefId>) -> SubstsBuilder { |
@@ -420,11 +424,6 @@ impl SubstsBuilder { | |||
420 | self.fill((starting_from..).map(Ty::Bound)) | 424 | self.fill((starting_from..).map(Ty::Bound)) |
421 | } | 425 | } |
422 | 426 | ||
423 | pub fn fill_with_params(self) -> Self { | ||
424 | let start = self.vec.len() as u32; | ||
425 | self.fill((start..).map(|idx| Ty::Param { idx, name: Name::missing() })) | ||
426 | } | ||
427 | |||
428 | pub fn fill_with_unknown(self) -> Self { | 427 | pub fn fill_with_unknown(self) -> Self { |
429 | self.fill(iter::repeat(Ty::Unknown)) | 428 | self.fill(iter::repeat(Ty::Unknown)) |
430 | } | 429 | } |
@@ -451,6 +450,32 @@ impl Deref for Substs { | |||
451 | } | 450 | } |
452 | } | 451 | } |
453 | 452 | ||
453 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] | ||
454 | pub struct Binders<T> { | ||
455 | pub num_binders: usize, | ||
456 | pub value: T, | ||
457 | } | ||
458 | |||
459 | impl<T> Binders<T> { | ||
460 | pub fn new(num_binders: usize, value: T) -> Self { | ||
461 | Self { num_binders, value } | ||
462 | } | ||
463 | } | ||
464 | |||
465 | impl<T: TypeWalk> Binders<T> { | ||
466 | /// Substitutes all variables. | ||
467 | pub fn subst(self, subst: &Substs) -> T { | ||
468 | assert_eq!(subst.len(), self.num_binders); | ||
469 | self.value.subst_bound_vars(subst) | ||
470 | } | ||
471 | |||
472 | /// Substitutes just a prefix of the variables (shifting the rest). | ||
473 | pub fn subst_prefix(self, subst: &Substs) -> Binders<T> { | ||
474 | assert!(subst.len() < self.num_binders); | ||
475 | Binders::new(self.num_binders - subst.len(), self.value.subst_bound_vars(subst)) | ||
476 | } | ||
477 | } | ||
478 | |||
454 | /// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. | 479 | /// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. |
455 | /// Name to be bikeshedded: TraitBound? TraitImplements? | 480 | /// Name to be bikeshedded: TraitBound? TraitImplements? |
456 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 481 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
@@ -551,6 +576,9 @@ pub struct FnSig { | |||
551 | params_and_return: Arc<[Ty]>, | 576 | params_and_return: Arc<[Ty]>, |
552 | } | 577 | } |
553 | 578 | ||
579 | /// A polymorphic function signature. | ||
580 | pub type PolyFnSig = Binders<FnSig>; | ||
581 | |||
554 | impl FnSig { | 582 | impl FnSig { |
555 | pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty) -> FnSig { | 583 | pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty) -> FnSig { |
556 | params.push(ret); | 584 | params.push(ret); |
@@ -730,22 +758,7 @@ pub trait TypeWalk { | |||
730 | self | 758 | self |
731 | } | 759 | } |
732 | 760 | ||
733 | /// Replaces type parameters in this type using the given `Substs`. (So e.g. | 761 | /// Substitutes `Ty::Bound` vars with the given substitution. |
734 | /// if `self` is `&[T]`, where type parameter T has index 0, and the | ||
735 | /// `Substs` contain `u32` at index 0, we'll have `&[u32]` afterwards.) | ||
736 | fn subst(self, substs: &Substs) -> Self | ||
737 | where | ||
738 | Self: Sized, | ||
739 | { | ||
740 | self.fold(&mut |ty| match ty { | ||
741 | Ty::Param { idx, name } => { | ||
742 | substs.get(idx as usize).cloned().unwrap_or(Ty::Param { idx, name }) | ||
743 | } | ||
744 | ty => ty, | ||
745 | }) | ||
746 | } | ||
747 | |||
748 | /// Substitutes `Ty::Bound` vars (as opposed to type parameters). | ||
749 | fn subst_bound_vars(mut self, substs: &Substs) -> Self | 762 | fn subst_bound_vars(mut self, substs: &Substs) -> Self |
750 | where | 763 | where |
751 | Self: Sized, | 764 | Self: Sized, |
@@ -755,6 +768,9 @@ pub trait TypeWalk { | |||
755 | &mut Ty::Bound(idx) => { | 768 | &mut Ty::Bound(idx) => { |
756 | if idx as usize >= binders && (idx as usize - binders) < substs.len() { | 769 | if idx as usize >= binders && (idx as usize - binders) < substs.len() { |
757 | *ty = substs.0[idx as usize - binders].clone(); | 770 | *ty = substs.0[idx as usize - binders].clone(); |
771 | } else if idx as usize >= binders + substs.len() { | ||
772 | // shift free binders | ||
773 | *ty = Ty::Bound(idx - substs.len() as u32); | ||
758 | } | 774 | } |
759 | } | 775 | } |
760 | _ => {} | 776 | _ => {} |
@@ -880,7 +896,7 @@ impl HirDisplay for ApplicationTy { | |||
880 | write!(f, ") -> {}", sig.ret().display(f.db))?; | 896 | write!(f, ") -> {}", sig.ret().display(f.db))?; |
881 | } | 897 | } |
882 | TypeCtor::FnDef(def) => { | 898 | TypeCtor::FnDef(def) => { |
883 | let sig = f.db.callable_item_signature(def); | 899 | let sig = f.db.callable_item_signature(def).subst(&self.parameters); |
884 | let name = match def { | 900 | let name = match def { |
885 | CallableDef::FunctionId(ff) => f.db.function_data(ff).name.clone(), | 901 | CallableDef::FunctionId(ff) => f.db.function_data(ff).name.clone(), |
886 | CallableDef::StructId(s) => f.db.struct_data(s).name.clone(), | 902 | CallableDef::StructId(s) => f.db.struct_data(s).name.clone(), |
@@ -896,9 +912,16 @@ impl HirDisplay for ApplicationTy { | |||
896 | } | 912 | } |
897 | } | 913 | } |
898 | if self.parameters.len() > 0 { | 914 | if self.parameters.len() > 0 { |
899 | write!(f, "<")?; | 915 | let generics = generics(f.db, def.into()); |
900 | f.write_joined(&*self.parameters.0, ", ")?; | 916 | let (parent_params, self_param, type_params, _impl_trait_params) = |
901 | write!(f, ">")?; | 917 | generics.provenance_split(); |
918 | let total_len = parent_params + self_param + type_params; | ||
919 | // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self? | ||
920 | if total_len > 0 { | ||
921 | write!(f, "<")?; | ||
922 | f.write_joined(&self.parameters.0[..total_len], ", ")?; | ||
923 | write!(f, ">")?; | ||
924 | } | ||
902 | } | 925 | } |
903 | write!(f, "(")?; | 926 | write!(f, "(")?; |
904 | f.write_joined(sig.params(), ", ")?; | 927 | f.write_joined(sig.params(), ", ")?; |
@@ -1009,7 +1032,24 @@ impl HirDisplay for Ty { | |||
1009 | match self { | 1032 | match self { |
1010 | Ty::Apply(a_ty) => a_ty.hir_fmt(f)?, | 1033 | Ty::Apply(a_ty) => a_ty.hir_fmt(f)?, |
1011 | Ty::Projection(p_ty) => p_ty.hir_fmt(f)?, | 1034 | Ty::Projection(p_ty) => p_ty.hir_fmt(f)?, |
1012 | Ty::Param { name, .. } => write!(f, "{}", name)?, | 1035 | Ty::Param(id) => { |
1036 | let generics = generics(f.db, id.parent); | ||
1037 | let param_data = &generics.params.types[id.local_id]; | ||
1038 | match param_data.provenance { | ||
1039 | TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => { | ||
1040 | write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? | ||
1041 | } | ||
1042 | TypeParamProvenance::ArgumentImplTrait => { | ||
1043 | write!(f, "impl ")?; | ||
1044 | let bounds = f.db.generic_predicates_for_param(*id); | ||
1045 | let substs = Substs::type_params_for_generics(&generics); | ||
1046 | write_bounds_like_dyn_trait( | ||
1047 | &bounds.iter().map(|b| b.clone().subst(&substs)).collect::<Vec<_>>(), | ||
1048 | f, | ||
1049 | )?; | ||
1050 | } | ||
1051 | } | ||
1052 | } | ||
1013 | Ty::Bound(idx) => write!(f, "?{}", idx)?, | 1053 | Ty::Bound(idx) => write!(f, "?{}", idx)?, |
1014 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { | 1054 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { |
1015 | match self { | 1055 | match self { |
@@ -1017,66 +1057,7 @@ impl HirDisplay for Ty { | |||
1017 | Ty::Opaque(_) => write!(f, "impl ")?, | 1057 | Ty::Opaque(_) => write!(f, "impl ")?, |
1018 | _ => unreachable!(), | 1058 | _ => unreachable!(), |
1019 | }; | 1059 | }; |
1020 | // Note: This code is written to produce nice results (i.e. | 1060 | write_bounds_like_dyn_trait(&predicates, f)?; |
1021 | // corresponding to surface Rust) for types that can occur in | ||
1022 | // actual Rust. It will have weird results if the predicates | ||
1023 | // aren't as expected (i.e. self types = $0, projection | ||
1024 | // predicates for a certain trait come after the Implemented | ||
1025 | // predicate for that trait). | ||
1026 | let mut first = true; | ||
1027 | let mut angle_open = false; | ||
1028 | for p in predicates.iter() { | ||
1029 | match p { | ||
1030 | GenericPredicate::Implemented(trait_ref) => { | ||
1031 | if angle_open { | ||
1032 | write!(f, ">")?; | ||
1033 | } | ||
1034 | if !first { | ||
1035 | write!(f, " + ")?; | ||
1036 | } | ||
1037 | // We assume that the self type is $0 (i.e. the | ||
1038 | // existential) here, which is the only thing that's | ||
1039 | // possible in actual Rust, and hence don't print it | ||
1040 | write!(f, "{}", f.db.trait_data(trait_ref.trait_).name.clone())?; | ||
1041 | if trait_ref.substs.len() > 1 { | ||
1042 | write!(f, "<")?; | ||
1043 | f.write_joined(&trait_ref.substs[1..], ", ")?; | ||
1044 | // there might be assoc type bindings, so we leave the angle brackets open | ||
1045 | angle_open = true; | ||
1046 | } | ||
1047 | } | ||
1048 | GenericPredicate::Projection(projection_pred) => { | ||
1049 | // in types in actual Rust, these will always come | ||
1050 | // after the corresponding Implemented predicate | ||
1051 | if angle_open { | ||
1052 | write!(f, ", ")?; | ||
1053 | } else { | ||
1054 | write!(f, "<")?; | ||
1055 | angle_open = true; | ||
1056 | } | ||
1057 | let name = | ||
1058 | f.db.type_alias_data(projection_pred.projection_ty.associated_ty) | ||
1059 | .name | ||
1060 | .clone(); | ||
1061 | write!(f, "{} = ", name)?; | ||
1062 | projection_pred.ty.hir_fmt(f)?; | ||
1063 | } | ||
1064 | GenericPredicate::Error => { | ||
1065 | if angle_open { | ||
1066 | // impl Trait<X, {error}> | ||
1067 | write!(f, ", ")?; | ||
1068 | } else if !first { | ||
1069 | // impl Trait + {error} | ||
1070 | write!(f, " + ")?; | ||
1071 | } | ||
1072 | p.hir_fmt(f)?; | ||
1073 | } | ||
1074 | } | ||
1075 | first = false; | ||
1076 | } | ||
1077 | if angle_open { | ||
1078 | write!(f, ">")?; | ||
1079 | } | ||
1080 | } | 1061 | } |
1081 | Ty::Unknown => write!(f, "{{unknown}}")?, | 1062 | Ty::Unknown => write!(f, "{{unknown}}")?, |
1082 | Ty::Infer(..) => write!(f, "_")?, | 1063 | Ty::Infer(..) => write!(f, "_")?, |
@@ -1085,6 +1066,71 @@ impl HirDisplay for Ty { | |||
1085 | } | 1066 | } |
1086 | } | 1067 | } |
1087 | 1068 | ||
1069 | fn write_bounds_like_dyn_trait( | ||
1070 | predicates: &[GenericPredicate], | ||
1071 | f: &mut HirFormatter<impl HirDatabase>, | ||
1072 | ) -> fmt::Result { | ||
1073 | // Note: This code is written to produce nice results (i.e. | ||
1074 | // corresponding to surface Rust) for types that can occur in | ||
1075 | // actual Rust. It will have weird results if the predicates | ||
1076 | // aren't as expected (i.e. self types = $0, projection | ||
1077 | // predicates for a certain trait come after the Implemented | ||
1078 | // predicate for that trait). | ||
1079 | let mut first = true; | ||
1080 | let mut angle_open = false; | ||
1081 | for p in predicates.iter() { | ||
1082 | match p { | ||
1083 | GenericPredicate::Implemented(trait_ref) => { | ||
1084 | if angle_open { | ||
1085 | write!(f, ">")?; | ||
1086 | } | ||
1087 | if !first { | ||
1088 | write!(f, " + ")?; | ||
1089 | } | ||
1090 | // We assume that the self type is $0 (i.e. the | ||
1091 | // existential) here, which is the only thing that's | ||
1092 | // possible in actual Rust, and hence don't print it | ||
1093 | write!(f, "{}", f.db.trait_data(trait_ref.trait_).name.clone())?; | ||
1094 | if trait_ref.substs.len() > 1 { | ||
1095 | write!(f, "<")?; | ||
1096 | f.write_joined(&trait_ref.substs[1..], ", ")?; | ||
1097 | // there might be assoc type bindings, so we leave the angle brackets open | ||
1098 | angle_open = true; | ||
1099 | } | ||
1100 | } | ||
1101 | GenericPredicate::Projection(projection_pred) => { | ||
1102 | // in types in actual Rust, these will always come | ||
1103 | // after the corresponding Implemented predicate | ||
1104 | if angle_open { | ||
1105 | write!(f, ", ")?; | ||
1106 | } else { | ||
1107 | write!(f, "<")?; | ||
1108 | angle_open = true; | ||
1109 | } | ||
1110 | let name = | ||
1111 | f.db.type_alias_data(projection_pred.projection_ty.associated_ty).name.clone(); | ||
1112 | write!(f, "{} = ", name)?; | ||
1113 | projection_pred.ty.hir_fmt(f)?; | ||
1114 | } | ||
1115 | GenericPredicate::Error => { | ||
1116 | if angle_open { | ||
1117 | // impl Trait<X, {error}> | ||
1118 | write!(f, ", ")?; | ||
1119 | } else if !first { | ||
1120 | // impl Trait + {error} | ||
1121 | write!(f, " + ")?; | ||
1122 | } | ||
1123 | p.hir_fmt(f)?; | ||
1124 | } | ||
1125 | } | ||
1126 | first = false; | ||
1127 | } | ||
1128 | if angle_open { | ||
1129 | write!(f, ">")?; | ||
1130 | } | ||
1131 | Ok(()) | ||
1132 | } | ||
1133 | |||
1088 | impl TraitRef { | 1134 | impl TraitRef { |
1089 | fn hir_fmt_ext(&self, f: &mut HirFormatter<impl HirDatabase>, use_as: bool) -> fmt::Result { | 1135 | fn hir_fmt_ext(&self, f: &mut HirFormatter<impl HirDatabase>, use_as: bool) -> fmt::Result { |
1090 | if f.should_truncate() { | 1136 | if f.should_truncate() { |
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 2c2ecee9c..c68c5852b 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs | |||
@@ -10,12 +10,13 @@ use std::sync::Arc; | |||
10 | 10 | ||
11 | use hir_def::{ | 11 | use hir_def::{ |
12 | builtin_type::BuiltinType, | 12 | builtin_type::BuiltinType, |
13 | generics::WherePredicate, | 13 | generics::{TypeParamProvenance, WherePredicate, WherePredicateTarget}, |
14 | path::{GenericArg, Path, PathSegment, PathSegments}, | 14 | path::{GenericArg, Path, PathSegment, PathSegments}, |
15 | resolver::{HasResolver, Resolver, TypeNs}, | 15 | resolver::{HasResolver, Resolver, TypeNs}, |
16 | type_ref::{TypeBound, TypeRef}, | 16 | type_ref::{TypeBound, TypeRef}, |
17 | AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, | 17 | AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, |
18 | LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId, | 18 | LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, |
19 | VariantId, | ||
19 | }; | 20 | }; |
20 | use ra_arena::map::ArenaMap; | 21 | use ra_arena::map::ArenaMap; |
21 | use ra_db::CrateId; | 22 | use ra_db::CrateId; |
@@ -27,63 +28,158 @@ use crate::{ | |||
27 | all_super_traits, associated_type_by_name_including_super_traits, generics, make_mut_slice, | 28 | all_super_traits, associated_type_by_name_including_super_traits, generics, make_mut_slice, |
28 | variant_data, | 29 | variant_data, |
29 | }, | 30 | }, |
30 | FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, | 31 | Binders, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, ProjectionTy, Substs, |
31 | Ty, TypeCtor, TypeWalk, | 32 | TraitEnvironment, TraitRef, Ty, TypeCtor, |
32 | }; | 33 | }; |
33 | 34 | ||
35 | #[derive(Debug)] | ||
36 | pub struct TyLoweringContext<'a, DB: HirDatabase> { | ||
37 | pub db: &'a DB, | ||
38 | pub resolver: &'a Resolver, | ||
39 | /// Note: Conceptually, it's thinkable that we could be in a location where | ||
40 | /// some type params should be represented as placeholders, and others | ||
41 | /// should be converted to variables. I think in practice, this isn't | ||
42 | /// possible currently, so this should be fine for now. | ||
43 | pub type_param_mode: TypeParamLoweringMode, | ||
44 | pub impl_trait_mode: ImplTraitLoweringMode, | ||
45 | pub impl_trait_counter: std::cell::Cell<u16>, | ||
46 | } | ||
47 | |||
48 | impl<'a, DB: HirDatabase> TyLoweringContext<'a, DB> { | ||
49 | pub fn new(db: &'a DB, resolver: &'a Resolver) -> Self { | ||
50 | let impl_trait_counter = std::cell::Cell::new(0); | ||
51 | let impl_trait_mode = ImplTraitLoweringMode::Disallowed; | ||
52 | let type_param_mode = TypeParamLoweringMode::Placeholder; | ||
53 | Self { db, resolver, impl_trait_mode, impl_trait_counter, type_param_mode } | ||
54 | } | ||
55 | |||
56 | pub fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self { | ||
57 | Self { impl_trait_mode, ..self } | ||
58 | } | ||
59 | |||
60 | pub fn with_type_param_mode(self, type_param_mode: TypeParamLoweringMode) -> Self { | ||
61 | Self { type_param_mode, ..self } | ||
62 | } | ||
63 | } | ||
64 | |||
65 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] | ||
66 | pub enum ImplTraitLoweringMode { | ||
67 | /// `impl Trait` gets lowered into an opaque type that doesn't unify with | ||
68 | /// anything except itself. This is used in places where values flow 'out', | ||
69 | /// i.e. for arguments of the function we're currently checking, and return | ||
70 | /// types of functions we're calling. | ||
71 | Opaque, | ||
72 | /// `impl Trait` gets lowered into a type variable. Used for argument | ||
73 | /// position impl Trait when inside the respective function, since it allows | ||
74 | /// us to support that without Chalk. | ||
75 | Param, | ||
76 | /// `impl Trait` gets lowered into a variable that can unify with some | ||
77 | /// type. This is used in places where values flow 'in', i.e. for arguments | ||
78 | /// of functions we're calling, and the return type of the function we're | ||
79 | /// currently checking. | ||
80 | Variable, | ||
81 | /// `impl Trait` is disallowed and will be an error. | ||
82 | Disallowed, | ||
83 | } | ||
84 | |||
85 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] | ||
86 | pub enum TypeParamLoweringMode { | ||
87 | Placeholder, | ||
88 | Variable, | ||
89 | } | ||
90 | |||
34 | impl Ty { | 91 | impl Ty { |
35 | pub fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { | 92 | pub fn from_hir(ctx: &TyLoweringContext<'_, impl HirDatabase>, type_ref: &TypeRef) -> Self { |
36 | match type_ref { | 93 | match type_ref { |
37 | TypeRef::Never => Ty::simple(TypeCtor::Never), | 94 | TypeRef::Never => Ty::simple(TypeCtor::Never), |
38 | TypeRef::Tuple(inner) => { | 95 | TypeRef::Tuple(inner) => { |
39 | let inner_tys: Arc<[Ty]> = | 96 | let inner_tys: Arc<[Ty]> = inner.iter().map(|tr| Ty::from_hir(ctx, tr)).collect(); |
40 | inner.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect(); | ||
41 | Ty::apply( | 97 | Ty::apply( |
42 | TypeCtor::Tuple { cardinality: inner_tys.len() as u16 }, | 98 | TypeCtor::Tuple { cardinality: inner_tys.len() as u16 }, |
43 | Substs(inner_tys), | 99 | Substs(inner_tys), |
44 | ) | 100 | ) |
45 | } | 101 | } |
46 | TypeRef::Path(path) => Ty::from_hir_path(db, resolver, path), | 102 | TypeRef::Path(path) => Ty::from_hir_path(ctx, path), |
47 | TypeRef::RawPtr(inner, mutability) => { | 103 | TypeRef::RawPtr(inner, mutability) => { |
48 | let inner_ty = Ty::from_hir(db, resolver, inner); | 104 | let inner_ty = Ty::from_hir(ctx, inner); |
49 | Ty::apply_one(TypeCtor::RawPtr(*mutability), inner_ty) | 105 | Ty::apply_one(TypeCtor::RawPtr(*mutability), inner_ty) |
50 | } | 106 | } |
51 | TypeRef::Array(inner) => { | 107 | TypeRef::Array(inner) => { |
52 | let inner_ty = Ty::from_hir(db, resolver, inner); | 108 | let inner_ty = Ty::from_hir(ctx, inner); |
53 | Ty::apply_one(TypeCtor::Array, inner_ty) | 109 | Ty::apply_one(TypeCtor::Array, inner_ty) |
54 | } | 110 | } |
55 | TypeRef::Slice(inner) => { | 111 | TypeRef::Slice(inner) => { |
56 | let inner_ty = Ty::from_hir(db, resolver, inner); | 112 | let inner_ty = Ty::from_hir(ctx, inner); |
57 | Ty::apply_one(TypeCtor::Slice, inner_ty) | 113 | Ty::apply_one(TypeCtor::Slice, inner_ty) |
58 | } | 114 | } |
59 | TypeRef::Reference(inner, mutability) => { | 115 | TypeRef::Reference(inner, mutability) => { |
60 | let inner_ty = Ty::from_hir(db, resolver, inner); | 116 | let inner_ty = Ty::from_hir(ctx, inner); |
61 | Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) | 117 | Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) |
62 | } | 118 | } |
63 | TypeRef::Placeholder => Ty::Unknown, | 119 | TypeRef::Placeholder => Ty::Unknown, |
64 | TypeRef::Fn(params) => { | 120 | TypeRef::Fn(params) => { |
65 | let sig = Substs(params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect()); | 121 | let sig = Substs(params.iter().map(|tr| Ty::from_hir(ctx, tr)).collect()); |
66 | Ty::apply(TypeCtor::FnPtr { num_args: sig.len() as u16 - 1 }, sig) | 122 | Ty::apply(TypeCtor::FnPtr { num_args: sig.len() as u16 - 1 }, sig) |
67 | } | 123 | } |
68 | TypeRef::DynTrait(bounds) => { | 124 | TypeRef::DynTrait(bounds) => { |
69 | let self_ty = Ty::Bound(0); | 125 | let self_ty = Ty::Bound(0); |
70 | let predicates = bounds | 126 | let predicates = bounds |
71 | .iter() | 127 | .iter() |
72 | .flat_map(|b| { | 128 | .flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone())) |
73 | GenericPredicate::from_type_bound(db, resolver, b, self_ty.clone()) | ||
74 | }) | ||
75 | .collect(); | 129 | .collect(); |
76 | Ty::Dyn(predicates) | 130 | Ty::Dyn(predicates) |
77 | } | 131 | } |
78 | TypeRef::ImplTrait(bounds) => { | 132 | TypeRef::ImplTrait(bounds) => { |
79 | let self_ty = Ty::Bound(0); | 133 | match ctx.impl_trait_mode { |
80 | let predicates = bounds | 134 | ImplTraitLoweringMode::Opaque => { |
81 | .iter() | 135 | let self_ty = Ty::Bound(0); |
82 | .flat_map(|b| { | 136 | let predicates = bounds |
83 | GenericPredicate::from_type_bound(db, resolver, b, self_ty.clone()) | 137 | .iter() |
84 | }) | 138 | .flat_map(|b| { |
85 | .collect(); | 139 | GenericPredicate::from_type_bound(ctx, b, self_ty.clone()) |
86 | Ty::Opaque(predicates) | 140 | }) |
141 | .collect(); | ||
142 | Ty::Opaque(predicates) | ||
143 | } | ||
144 | ImplTraitLoweringMode::Param => { | ||
145 | let idx = ctx.impl_trait_counter.get(); | ||
146 | ctx.impl_trait_counter.set(idx + 1); | ||
147 | if let Some(def) = ctx.resolver.generic_def() { | ||
148 | let generics = generics(ctx.db, def); | ||
149 | let param = generics | ||
150 | .iter() | ||
151 | .filter(|(_, data)| { | ||
152 | data.provenance == TypeParamProvenance::ArgumentImplTrait | ||
153 | }) | ||
154 | .nth(idx as usize) | ||
155 | .map_or(Ty::Unknown, |(id, _)| Ty::Param(id)); | ||
156 | param | ||
157 | } else { | ||
158 | Ty::Unknown | ||
159 | } | ||
160 | } | ||
161 | ImplTraitLoweringMode::Variable => { | ||
162 | let idx = ctx.impl_trait_counter.get(); | ||
163 | ctx.impl_trait_counter.set(idx + 1); | ||
164 | let (parent_params, self_params, list_params, _impl_trait_params) = | ||
165 | if let Some(def) = ctx.resolver.generic_def() { | ||
166 | let generics = generics(ctx.db, def); | ||
167 | generics.provenance_split() | ||
168 | } else { | ||
169 | (0, 0, 0, 0) | ||
170 | }; | ||
171 | Ty::Bound( | ||
172 | idx as u32 | ||
173 | + parent_params as u32 | ||
174 | + self_params as u32 | ||
175 | + list_params as u32, | ||
176 | ) | ||
177 | } | ||
178 | ImplTraitLoweringMode::Disallowed => { | ||
179 | // FIXME: report error | ||
180 | Ty::Unknown | ||
181 | } | ||
182 | } | ||
87 | } | 183 | } |
88 | TypeRef::Error => Ty::Unknown, | 184 | TypeRef::Error => Ty::Unknown, |
89 | } | 185 | } |
@@ -93,10 +189,9 @@ impl Ty { | |||
93 | /// lower the self types of the predicates since that could lead to cycles. | 189 | /// lower the self types of the predicates since that could lead to cycles. |
94 | /// So we just check here if the `type_ref` resolves to a generic param, and which. | 190 | /// So we just check here if the `type_ref` resolves to a generic param, and which. |
95 | fn from_hir_only_param( | 191 | fn from_hir_only_param( |
96 | db: &impl HirDatabase, | 192 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
97 | resolver: &Resolver, | ||
98 | type_ref: &TypeRef, | 193 | type_ref: &TypeRef, |
99 | ) -> Option<u32> { | 194 | ) -> Option<TypeParamId> { |
100 | let path = match type_ref { | 195 | let path = match type_ref { |
101 | TypeRef::Path(path) => path, | 196 | TypeRef::Path(path) => path, |
102 | _ => return None, | 197 | _ => return None, |
@@ -107,29 +202,26 @@ impl Ty { | |||
107 | if path.segments().len() > 1 { | 202 | if path.segments().len() > 1 { |
108 | return None; | 203 | return None; |
109 | } | 204 | } |
110 | let resolution = match resolver.resolve_path_in_type_ns(db, path.mod_path()) { | 205 | let resolution = match ctx.resolver.resolve_path_in_type_ns(ctx.db, path.mod_path()) { |
111 | Some((it, None)) => it, | 206 | Some((it, None)) => it, |
112 | _ => return None, | 207 | _ => return None, |
113 | }; | 208 | }; |
114 | if let TypeNs::GenericParam(param_id) = resolution { | 209 | if let TypeNs::GenericParam(param_id) = resolution { |
115 | let generics = generics(db, resolver.generic_def().expect("generics in scope")); | 210 | Some(param_id) |
116 | let idx = generics.param_idx(param_id); | ||
117 | Some(idx) | ||
118 | } else { | 211 | } else { |
119 | None | 212 | None |
120 | } | 213 | } |
121 | } | 214 | } |
122 | 215 | ||
123 | pub(crate) fn from_type_relative_path( | 216 | pub(crate) fn from_type_relative_path( |
124 | db: &impl HirDatabase, | 217 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
125 | resolver: &Resolver, | ||
126 | ty: Ty, | 218 | ty: Ty, |
127 | remaining_segments: PathSegments<'_>, | 219 | remaining_segments: PathSegments<'_>, |
128 | ) -> Ty { | 220 | ) -> Ty { |
129 | if remaining_segments.len() == 1 { | 221 | if remaining_segments.len() == 1 { |
130 | // resolve unselected assoc types | 222 | // resolve unselected assoc types |
131 | let segment = remaining_segments.first().unwrap(); | 223 | let segment = remaining_segments.first().unwrap(); |
132 | Ty::select_associated_type(db, resolver, ty, segment) | 224 | Ty::select_associated_type(ctx, ty, segment) |
133 | } else if remaining_segments.len() > 1 { | 225 | } else if remaining_segments.len() > 1 { |
134 | // FIXME report error (ambiguous associated type) | 226 | // FIXME report error (ambiguous associated type) |
135 | Ty::Unknown | 227 | Ty::Unknown |
@@ -139,20 +231,18 @@ impl Ty { | |||
139 | } | 231 | } |
140 | 232 | ||
141 | pub(crate) fn from_partly_resolved_hir_path( | 233 | pub(crate) fn from_partly_resolved_hir_path( |
142 | db: &impl HirDatabase, | 234 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
143 | resolver: &Resolver, | ||
144 | resolution: TypeNs, | 235 | resolution: TypeNs, |
145 | resolved_segment: PathSegment<'_>, | 236 | resolved_segment: PathSegment<'_>, |
146 | remaining_segments: PathSegments<'_>, | 237 | remaining_segments: PathSegments<'_>, |
147 | ) -> Ty { | 238 | ) -> Ty { |
148 | let ty = match resolution { | 239 | let ty = match resolution { |
149 | TypeNs::TraitId(trait_) => { | 240 | TypeNs::TraitId(trait_) => { |
150 | let trait_ref = | 241 | let trait_ref = TraitRef::from_resolved_path(ctx, trait_, resolved_segment, None); |
151 | TraitRef::from_resolved_path(db, resolver, trait_, resolved_segment, None); | ||
152 | return if remaining_segments.len() == 1 { | 242 | return if remaining_segments.len() == 1 { |
153 | let segment = remaining_segments.first().unwrap(); | 243 | let segment = remaining_segments.first().unwrap(); |
154 | let associated_ty = associated_type_by_name_including_super_traits( | 244 | let associated_ty = associated_type_by_name_including_super_traits( |
155 | db, | 245 | ctx.db, |
156 | trait_ref.trait_, | 246 | trait_ref.trait_, |
157 | &segment.name, | 247 | &segment.name, |
158 | ); | 248 | ); |
@@ -177,37 +267,55 @@ impl Ty { | |||
177 | }; | 267 | }; |
178 | } | 268 | } |
179 | TypeNs::GenericParam(param_id) => { | 269 | TypeNs::GenericParam(param_id) => { |
180 | let generics = generics(db, resolver.generic_def().expect("generics in scope")); | 270 | let generics = |
181 | let idx = generics.param_idx(param_id); | 271 | generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope")); |
182 | // FIXME: maybe return name in resolution? | 272 | match ctx.type_param_mode { |
183 | let name = generics.param_name(param_id); | 273 | TypeParamLoweringMode::Placeholder => Ty::Param(param_id), |
184 | Ty::Param { idx, name } | 274 | TypeParamLoweringMode::Variable => { |
275 | let idx = generics.param_idx(param_id).expect("matching generics"); | ||
276 | Ty::Bound(idx) | ||
277 | } | ||
278 | } | ||
185 | } | 279 | } |
186 | TypeNs::SelfType(impl_id) => db.impl_self_ty(impl_id).clone(), | 280 | TypeNs::SelfType(impl_id) => { |
187 | TypeNs::AdtSelfType(adt) => db.ty(adt.into()), | 281 | let generics = generics(ctx.db, impl_id.into()); |
188 | 282 | let substs = match ctx.type_param_mode { | |
189 | TypeNs::AdtId(it) => Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()), | 283 | TypeParamLoweringMode::Placeholder => { |
190 | TypeNs::BuiltinType(it) => { | 284 | Substs::type_params_for_generics(&generics) |
191 | Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()) | 285 | } |
286 | TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), | ||
287 | }; | ||
288 | ctx.db.impl_self_ty(impl_id).subst(&substs) | ||
192 | } | 289 | } |
193 | TypeNs::TypeAliasId(it) => { | 290 | TypeNs::AdtSelfType(adt) => { |
194 | Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()) | 291 | let generics = generics(ctx.db, adt.into()); |
292 | let substs = match ctx.type_param_mode { | ||
293 | TypeParamLoweringMode::Placeholder => { | ||
294 | Substs::type_params_for_generics(&generics) | ||
295 | } | ||
296 | TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), | ||
297 | }; | ||
298 | ctx.db.ty(adt.into()).subst(&substs) | ||
195 | } | 299 | } |
300 | |||
301 | TypeNs::AdtId(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), | ||
302 | TypeNs::BuiltinType(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), | ||
303 | TypeNs::TypeAliasId(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), | ||
196 | // FIXME: report error | 304 | // FIXME: report error |
197 | TypeNs::EnumVariantId(_) => return Ty::Unknown, | 305 | TypeNs::EnumVariantId(_) => return Ty::Unknown, |
198 | }; | 306 | }; |
199 | 307 | ||
200 | Ty::from_type_relative_path(db, resolver, ty, remaining_segments) | 308 | Ty::from_type_relative_path(ctx, ty, remaining_segments) |
201 | } | 309 | } |
202 | 310 | ||
203 | pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty { | 311 | pub(crate) fn from_hir_path(ctx: &TyLoweringContext<'_, impl HirDatabase>, path: &Path) -> Ty { |
204 | // Resolve the path (in type namespace) | 312 | // Resolve the path (in type namespace) |
205 | if let Some(type_ref) = path.type_anchor() { | 313 | if let Some(type_ref) = path.type_anchor() { |
206 | let ty = Ty::from_hir(db, resolver, &type_ref); | 314 | let ty = Ty::from_hir(ctx, &type_ref); |
207 | return Ty::from_type_relative_path(db, resolver, ty, path.segments()); | 315 | return Ty::from_type_relative_path(ctx, ty, path.segments()); |
208 | } | 316 | } |
209 | let (resolution, remaining_index) = | 317 | let (resolution, remaining_index) = |
210 | match resolver.resolve_path_in_type_ns(db, path.mod_path()) { | 318 | match ctx.resolver.resolve_path_in_type_ns(ctx.db, path.mod_path()) { |
211 | Some(it) => it, | 319 | Some(it) => it, |
212 | None => return Ty::Unknown, | 320 | None => return Ty::Unknown, |
213 | }; | 321 | }; |
@@ -218,39 +326,44 @@ impl Ty { | |||
218 | ), | 326 | ), |
219 | Some(i) => (path.segments().get(i - 1).unwrap(), path.segments().skip(i)), | 327 | Some(i) => (path.segments().get(i - 1).unwrap(), path.segments().skip(i)), |
220 | }; | 328 | }; |
221 | Ty::from_partly_resolved_hir_path( | 329 | Ty::from_partly_resolved_hir_path(ctx, resolution, resolved_segment, remaining_segments) |
222 | db, | ||
223 | resolver, | ||
224 | resolution, | ||
225 | resolved_segment, | ||
226 | remaining_segments, | ||
227 | ) | ||
228 | } | 330 | } |
229 | 331 | ||
230 | fn select_associated_type( | 332 | fn select_associated_type( |
231 | db: &impl HirDatabase, | 333 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
232 | resolver: &Resolver, | ||
233 | self_ty: Ty, | 334 | self_ty: Ty, |
234 | segment: PathSegment<'_>, | 335 | segment: PathSegment<'_>, |
235 | ) -> Ty { | 336 | ) -> Ty { |
236 | let param_idx = match self_ty { | 337 | let def = match ctx.resolver.generic_def() { |
237 | Ty::Param { idx, .. } => idx, | ||
238 | _ => return Ty::Unknown, // Error: Ambiguous associated type | ||
239 | }; | ||
240 | let def = match resolver.generic_def() { | ||
241 | Some(def) => def, | 338 | Some(def) => def, |
242 | None => return Ty::Unknown, // this can't actually happen | 339 | None => return Ty::Unknown, // this can't actually happen |
243 | }; | 340 | }; |
244 | let predicates = db.generic_predicates_for_param(def.into(), param_idx); | 341 | let param_id = match self_ty { |
245 | let traits_from_env = predicates.iter().filter_map(|pred| match pred { | 342 | Ty::Param(id) if ctx.type_param_mode == TypeParamLoweringMode::Placeholder => id, |
246 | GenericPredicate::Implemented(tr) if tr.self_ty() == &self_ty => Some(tr.trait_), | 343 | Ty::Bound(idx) if ctx.type_param_mode == TypeParamLoweringMode::Variable => { |
344 | let generics = generics(ctx.db, def); | ||
345 | let param_id = if let Some((id, _)) = generics.iter().nth(idx as usize) { | ||
346 | id | ||
347 | } else { | ||
348 | return Ty::Unknown; | ||
349 | }; | ||
350 | param_id | ||
351 | } | ||
352 | _ => return Ty::Unknown, // Error: Ambiguous associated type | ||
353 | }; | ||
354 | let predicates = ctx.db.generic_predicates_for_param(param_id); | ||
355 | let traits_from_env = predicates.iter().filter_map(|pred| match &pred.value { | ||
356 | GenericPredicate::Implemented(tr) => Some(tr.trait_), | ||
247 | _ => None, | 357 | _ => None, |
248 | }); | 358 | }); |
249 | let traits = traits_from_env.flat_map(|t| all_super_traits(db, t)); | 359 | let traits = traits_from_env.flat_map(|t| all_super_traits(ctx.db, t)); |
250 | for t in traits { | 360 | for t in traits { |
251 | if let Some(associated_ty) = db.trait_data(t).associated_type_by_name(&segment.name) { | 361 | if let Some(associated_ty) = ctx.db.trait_data(t).associated_type_by_name(&segment.name) |
252 | let substs = | 362 | { |
253 | Substs::build_for_def(db, t).push(self_ty.clone()).fill_with_unknown().build(); | 363 | let substs = Substs::build_for_def(ctx.db, t) |
364 | .push(self_ty.clone()) | ||
365 | .fill_with_unknown() | ||
366 | .build(); | ||
254 | // FIXME handle type parameters on the segment | 367 | // FIXME handle type parameters on the segment |
255 | return Ty::Projection(ProjectionTy { associated_ty, parameters: substs }); | 368 | return Ty::Projection(ProjectionTy { associated_ty, parameters: substs }); |
256 | } | 369 | } |
@@ -259,8 +372,7 @@ impl Ty { | |||
259 | } | 372 | } |
260 | 373 | ||
261 | fn from_hir_path_inner( | 374 | fn from_hir_path_inner( |
262 | db: &impl HirDatabase, | 375 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
263 | resolver: &Resolver, | ||
264 | segment: PathSegment<'_>, | 376 | segment: PathSegment<'_>, |
265 | typable: TyDefId, | 377 | typable: TyDefId, |
266 | ) -> Ty { | 378 | ) -> Ty { |
@@ -269,15 +381,14 @@ impl Ty { | |||
269 | TyDefId::AdtId(it) => Some(it.into()), | 381 | TyDefId::AdtId(it) => Some(it.into()), |
270 | TyDefId::TypeAliasId(it) => Some(it.into()), | 382 | TyDefId::TypeAliasId(it) => Some(it.into()), |
271 | }; | 383 | }; |
272 | let substs = substs_from_path_segment(db, resolver, segment, generic_def, false); | 384 | let substs = substs_from_path_segment(ctx, segment, generic_def, false); |
273 | db.ty(typable).subst(&substs) | 385 | ctx.db.ty(typable).subst(&substs) |
274 | } | 386 | } |
275 | 387 | ||
276 | /// Collect generic arguments from a path into a `Substs`. See also | 388 | /// Collect generic arguments from a path into a `Substs`. See also |
277 | /// `create_substs_for_ast_path` and `def_to_ty` in rustc. | 389 | /// `create_substs_for_ast_path` and `def_to_ty` in rustc. |
278 | pub(super) fn substs_from_path( | 390 | pub(super) fn substs_from_path( |
279 | db: &impl HirDatabase, | 391 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
280 | resolver: &Resolver, | ||
281 | path: &Path, | 392 | path: &Path, |
282 | // Note that we don't call `db.value_type(resolved)` here, | 393 | // Note that we don't call `db.value_type(resolved)` here, |
283 | // `ValueTyDefId` is just a convenient way to pass generics and | 394 | // `ValueTyDefId` is just a convenient way to pass generics and |
@@ -305,52 +416,49 @@ impl Ty { | |||
305 | (segment, Some(var.parent.into())) | 416 | (segment, Some(var.parent.into())) |
306 | } | 417 | } |
307 | }; | 418 | }; |
308 | substs_from_path_segment(db, resolver, segment, generic_def, false) | 419 | substs_from_path_segment(ctx, segment, generic_def, false) |
309 | } | 420 | } |
310 | } | 421 | } |
311 | 422 | ||
312 | pub(super) fn substs_from_path_segment( | 423 | pub(super) fn substs_from_path_segment( |
313 | db: &impl HirDatabase, | 424 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
314 | resolver: &Resolver, | ||
315 | segment: PathSegment<'_>, | 425 | segment: PathSegment<'_>, |
316 | def_generic: Option<GenericDefId>, | 426 | def_generic: Option<GenericDefId>, |
317 | add_self_param: bool, | 427 | _add_self_param: bool, |
318 | ) -> Substs { | 428 | ) -> Substs { |
319 | let mut substs = Vec::new(); | 429 | let mut substs = Vec::new(); |
320 | let def_generics = def_generic.map(|def| generics(db, def.into())); | 430 | let def_generics = def_generic.map(|def| generics(ctx.db, def.into())); |
321 | 431 | ||
322 | let (total_len, parent_len, child_len) = def_generics.map_or((0, 0, 0), |g| g.len_split()); | 432 | let (parent_params, self_params, type_params, impl_trait_params) = |
323 | substs.extend(iter::repeat(Ty::Unknown).take(parent_len)); | 433 | def_generics.map_or((0, 0, 0, 0), |g| g.provenance_split()); |
324 | if add_self_param { | 434 | substs.extend(iter::repeat(Ty::Unknown).take(parent_params)); |
325 | // FIXME this add_self_param argument is kind of a hack: Traits have the | ||
326 | // Self type as an implicit first type parameter, but it can't be | ||
327 | // actually provided in the type arguments | ||
328 | // (well, actually sometimes it can, in the form of type-relative paths: `<Foo as Default>::default()`) | ||
329 | substs.push(Ty::Unknown); | ||
330 | } | ||
331 | if let Some(generic_args) = &segment.args_and_bindings { | 435 | if let Some(generic_args) = &segment.args_and_bindings { |
436 | if !generic_args.has_self_type { | ||
437 | substs.extend(iter::repeat(Ty::Unknown).take(self_params)); | ||
438 | } | ||
439 | let expected_num = | ||
440 | if generic_args.has_self_type { self_params + type_params } else { type_params }; | ||
441 | let skip = if generic_args.has_self_type && self_params == 0 { 1 } else { 0 }; | ||
332 | // if args are provided, it should be all of them, but we can't rely on that | 442 | // if args are provided, it should be all of them, but we can't rely on that |
333 | let self_param_correction = if add_self_param { 1 } else { 0 }; | 443 | for arg in generic_args.args.iter().skip(skip).take(expected_num) { |
334 | let child_len = child_len - self_param_correction; | ||
335 | for arg in generic_args.args.iter().take(child_len) { | ||
336 | match arg { | 444 | match arg { |
337 | GenericArg::Type(type_ref) => { | 445 | GenericArg::Type(type_ref) => { |
338 | let ty = Ty::from_hir(db, resolver, type_ref); | 446 | let ty = Ty::from_hir(ctx, type_ref); |
339 | substs.push(ty); | 447 | substs.push(ty); |
340 | } | 448 | } |
341 | } | 449 | } |
342 | } | 450 | } |
343 | } | 451 | } |
452 | let total_len = parent_params + self_params + type_params + impl_trait_params; | ||
344 | // add placeholders for args that were not provided | 453 | // add placeholders for args that were not provided |
345 | let supplied_params = substs.len(); | 454 | for _ in substs.len()..total_len { |
346 | for _ in supplied_params..total_len { | ||
347 | substs.push(Ty::Unknown); | 455 | substs.push(Ty::Unknown); |
348 | } | 456 | } |
349 | assert_eq!(substs.len(), total_len); | 457 | assert_eq!(substs.len(), total_len); |
350 | 458 | ||
351 | // handle defaults | 459 | // handle defaults |
352 | if let Some(def_generic) = def_generic { | 460 | if let Some(def_generic) = def_generic { |
353 | let default_substs = db.generic_defaults(def_generic.into()); | 461 | let default_substs = ctx.db.generic_defaults(def_generic.into()); |
354 | assert_eq!(substs.len(), default_substs.len()); | 462 | assert_eq!(substs.len(), default_substs.len()); |
355 | 463 | ||
356 | for (i, default_ty) in default_substs.iter().enumerate() { | 464 | for (i, default_ty) in default_substs.iter().enumerate() { |
@@ -365,27 +473,25 @@ pub(super) fn substs_from_path_segment( | |||
365 | 473 | ||
366 | impl TraitRef { | 474 | impl TraitRef { |
367 | fn from_path( | 475 | fn from_path( |
368 | db: &impl HirDatabase, | 476 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
369 | resolver: &Resolver, | ||
370 | path: &Path, | 477 | path: &Path, |
371 | explicit_self_ty: Option<Ty>, | 478 | explicit_self_ty: Option<Ty>, |
372 | ) -> Option<Self> { | 479 | ) -> Option<Self> { |
373 | let resolved = match resolver.resolve_path_in_type_ns_fully(db, path.mod_path())? { | 480 | let resolved = match ctx.resolver.resolve_path_in_type_ns_fully(ctx.db, path.mod_path())? { |
374 | TypeNs::TraitId(tr) => tr, | 481 | TypeNs::TraitId(tr) => tr, |
375 | _ => return None, | 482 | _ => return None, |
376 | }; | 483 | }; |
377 | let segment = path.segments().last().expect("path should have at least one segment"); | 484 | let segment = path.segments().last().expect("path should have at least one segment"); |
378 | Some(TraitRef::from_resolved_path(db, resolver, resolved.into(), segment, explicit_self_ty)) | 485 | Some(TraitRef::from_resolved_path(ctx, resolved.into(), segment, explicit_self_ty)) |
379 | } | 486 | } |
380 | 487 | ||
381 | pub(crate) fn from_resolved_path( | 488 | pub(crate) fn from_resolved_path( |
382 | db: &impl HirDatabase, | 489 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
383 | resolver: &Resolver, | ||
384 | resolved: TraitId, | 490 | resolved: TraitId, |
385 | segment: PathSegment<'_>, | 491 | segment: PathSegment<'_>, |
386 | explicit_self_ty: Option<Ty>, | 492 | explicit_self_ty: Option<Ty>, |
387 | ) -> Self { | 493 | ) -> Self { |
388 | let mut substs = TraitRef::substs_from_path(db, resolver, segment, resolved); | 494 | let mut substs = TraitRef::substs_from_path(ctx, segment, resolved); |
389 | if let Some(self_ty) = explicit_self_ty { | 495 | if let Some(self_ty) = explicit_self_ty { |
390 | make_mut_slice(&mut substs.0)[0] = self_ty; | 496 | make_mut_slice(&mut substs.0)[0] = self_ty; |
391 | } | 497 | } |
@@ -393,8 +499,7 @@ impl TraitRef { | |||
393 | } | 499 | } |
394 | 500 | ||
395 | fn from_hir( | 501 | fn from_hir( |
396 | db: &impl HirDatabase, | 502 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
397 | resolver: &Resolver, | ||
398 | type_ref: &TypeRef, | 503 | type_ref: &TypeRef, |
399 | explicit_self_ty: Option<Ty>, | 504 | explicit_self_ty: Option<Ty>, |
400 | ) -> Option<Self> { | 505 | ) -> Option<Self> { |
@@ -402,28 +507,26 @@ impl TraitRef { | |||
402 | TypeRef::Path(path) => path, | 507 | TypeRef::Path(path) => path, |
403 | _ => return None, | 508 | _ => return None, |
404 | }; | 509 | }; |
405 | TraitRef::from_path(db, resolver, path, explicit_self_ty) | 510 | TraitRef::from_path(ctx, path, explicit_self_ty) |
406 | } | 511 | } |
407 | 512 | ||
408 | fn substs_from_path( | 513 | fn substs_from_path( |
409 | db: &impl HirDatabase, | 514 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
410 | resolver: &Resolver, | ||
411 | segment: PathSegment<'_>, | 515 | segment: PathSegment<'_>, |
412 | resolved: TraitId, | 516 | resolved: TraitId, |
413 | ) -> Substs { | 517 | ) -> Substs { |
414 | let has_self_param = | 518 | let has_self_param = |
415 | segment.args_and_bindings.as_ref().map(|a| a.has_self_type).unwrap_or(false); | 519 | segment.args_and_bindings.as_ref().map(|a| a.has_self_type).unwrap_or(false); |
416 | substs_from_path_segment(db, resolver, segment, Some(resolved.into()), !has_self_param) | 520 | substs_from_path_segment(ctx, segment, Some(resolved.into()), !has_self_param) |
417 | } | 521 | } |
418 | 522 | ||
419 | pub(crate) fn from_type_bound( | 523 | pub(crate) fn from_type_bound( |
420 | db: &impl HirDatabase, | 524 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
421 | resolver: &Resolver, | ||
422 | bound: &TypeBound, | 525 | bound: &TypeBound, |
423 | self_ty: Ty, | 526 | self_ty: Ty, |
424 | ) -> Option<TraitRef> { | 527 | ) -> Option<TraitRef> { |
425 | match bound { | 528 | match bound { |
426 | TypeBound::Path(path) => TraitRef::from_path(db, resolver, path, Some(self_ty)), | 529 | TypeBound::Path(path) => TraitRef::from_path(ctx, path, Some(self_ty)), |
427 | TypeBound::Error => None, | 530 | TypeBound::Error => None, |
428 | } | 531 | } |
429 | } | 532 | } |
@@ -431,33 +534,44 @@ impl TraitRef { | |||
431 | 534 | ||
432 | impl GenericPredicate { | 535 | impl GenericPredicate { |
433 | pub(crate) fn from_where_predicate<'a>( | 536 | pub(crate) fn from_where_predicate<'a>( |
434 | db: &'a impl HirDatabase, | 537 | ctx: &'a TyLoweringContext<'a, impl HirDatabase>, |
435 | resolver: &'a Resolver, | ||
436 | where_predicate: &'a WherePredicate, | 538 | where_predicate: &'a WherePredicate, |
437 | ) -> impl Iterator<Item = GenericPredicate> + 'a { | 539 | ) -> impl Iterator<Item = GenericPredicate> + 'a { |
438 | let self_ty = Ty::from_hir(db, resolver, &where_predicate.type_ref); | 540 | let self_ty = match &where_predicate.target { |
439 | GenericPredicate::from_type_bound(db, resolver, &where_predicate.bound, self_ty) | 541 | WherePredicateTarget::TypeRef(type_ref) => Ty::from_hir(ctx, type_ref), |
542 | WherePredicateTarget::TypeParam(param_id) => { | ||
543 | let generic_def = ctx.resolver.generic_def().expect("generics in scope"); | ||
544 | let generics = generics(ctx.db, generic_def); | ||
545 | let param_id = hir_def::TypeParamId { parent: generic_def, local_id: *param_id }; | ||
546 | match ctx.type_param_mode { | ||
547 | TypeParamLoweringMode::Placeholder => Ty::Param(param_id), | ||
548 | TypeParamLoweringMode::Variable => { | ||
549 | let idx = generics.param_idx(param_id).expect("matching generics"); | ||
550 | Ty::Bound(idx) | ||
551 | } | ||
552 | } | ||
553 | } | ||
554 | }; | ||
555 | GenericPredicate::from_type_bound(ctx, &where_predicate.bound, self_ty) | ||
440 | } | 556 | } |
441 | 557 | ||
442 | pub(crate) fn from_type_bound<'a>( | 558 | pub(crate) fn from_type_bound<'a>( |
443 | db: &'a impl HirDatabase, | 559 | ctx: &'a TyLoweringContext<'a, impl HirDatabase>, |
444 | resolver: &'a Resolver, | ||
445 | bound: &'a TypeBound, | 560 | bound: &'a TypeBound, |
446 | self_ty: Ty, | 561 | self_ty: Ty, |
447 | ) -> impl Iterator<Item = GenericPredicate> + 'a { | 562 | ) -> impl Iterator<Item = GenericPredicate> + 'a { |
448 | let trait_ref = TraitRef::from_type_bound(db, &resolver, bound, self_ty); | 563 | let trait_ref = TraitRef::from_type_bound(ctx, bound, self_ty); |
449 | iter::once(trait_ref.clone().map_or(GenericPredicate::Error, GenericPredicate::Implemented)) | 564 | iter::once(trait_ref.clone().map_or(GenericPredicate::Error, GenericPredicate::Implemented)) |
450 | .chain( | 565 | .chain( |
451 | trait_ref.into_iter().flat_map(move |tr| { | 566 | trait_ref |
452 | assoc_type_bindings_from_type_bound(db, resolver, bound, tr) | 567 | .into_iter() |
453 | }), | 568 | .flat_map(move |tr| assoc_type_bindings_from_type_bound(ctx, bound, tr)), |
454 | ) | 569 | ) |
455 | } | 570 | } |
456 | } | 571 | } |
457 | 572 | ||
458 | fn assoc_type_bindings_from_type_bound<'a>( | 573 | fn assoc_type_bindings_from_type_bound<'a>( |
459 | db: &'a impl HirDatabase, | 574 | ctx: &'a TyLoweringContext<'a, impl HirDatabase>, |
460 | resolver: &'a Resolver, | ||
461 | bound: &'a TypeBound, | 575 | bound: &'a TypeBound, |
462 | trait_ref: TraitRef, | 576 | trait_ref: TraitRef, |
463 | ) -> impl Iterator<Item = GenericPredicate> + 'a { | 577 | ) -> impl Iterator<Item = GenericPredicate> + 'a { |
@@ -471,21 +585,21 @@ fn assoc_type_bindings_from_type_bound<'a>( | |||
471 | .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) | 585 | .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) |
472 | .map(move |(name, type_ref)| { | 586 | .map(move |(name, type_ref)| { |
473 | let associated_ty = | 587 | let associated_ty = |
474 | associated_type_by_name_including_super_traits(db, trait_ref.trait_, &name); | 588 | associated_type_by_name_including_super_traits(ctx.db, trait_ref.trait_, &name); |
475 | let associated_ty = match associated_ty { | 589 | let associated_ty = match associated_ty { |
476 | None => return GenericPredicate::Error, | 590 | None => return GenericPredicate::Error, |
477 | Some(t) => t, | 591 | Some(t) => t, |
478 | }; | 592 | }; |
479 | let projection_ty = | 593 | let projection_ty = |
480 | ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() }; | 594 | ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() }; |
481 | let ty = Ty::from_hir(db, resolver, type_ref); | 595 | let ty = Ty::from_hir(ctx, type_ref); |
482 | let projection_predicate = ProjectionPredicate { projection_ty, ty }; | 596 | let projection_predicate = ProjectionPredicate { projection_ty, ty }; |
483 | GenericPredicate::Projection(projection_predicate) | 597 | GenericPredicate::Projection(projection_predicate) |
484 | }) | 598 | }) |
485 | } | 599 | } |
486 | 600 | ||
487 | /// Build the signature of a callable item (function, struct or enum variant). | 601 | /// Build the signature of a callable item (function, struct or enum variant). |
488 | pub fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> FnSig { | 602 | pub fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> PolyFnSig { |
489 | match def { | 603 | match def { |
490 | CallableDef::FunctionId(f) => fn_sig_for_fn(db, f), | 604 | CallableDef::FunctionId(f) => fn_sig_for_fn(db, f), |
491 | CallableDef::StructId(s) => fn_sig_for_struct_constructor(db, s), | 605 | CallableDef::StructId(s) => fn_sig_for_struct_constructor(db, s), |
@@ -497,16 +611,19 @@ pub fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> FnSig { | |||
497 | pub(crate) fn field_types_query( | 611 | pub(crate) fn field_types_query( |
498 | db: &impl HirDatabase, | 612 | db: &impl HirDatabase, |
499 | variant_id: VariantId, | 613 | variant_id: VariantId, |
500 | ) -> Arc<ArenaMap<LocalStructFieldId, Ty>> { | 614 | ) -> Arc<ArenaMap<LocalStructFieldId, Binders<Ty>>> { |
501 | let var_data = variant_data(db, variant_id); | 615 | let var_data = variant_data(db, variant_id); |
502 | let resolver = match variant_id { | 616 | let (resolver, def): (_, GenericDefId) = match variant_id { |
503 | VariantId::StructId(it) => it.resolver(db), | 617 | VariantId::StructId(it) => (it.resolver(db), it.into()), |
504 | VariantId::UnionId(it) => it.resolver(db), | 618 | VariantId::UnionId(it) => (it.resolver(db), it.into()), |
505 | VariantId::EnumVariantId(it) => it.parent.resolver(db), | 619 | VariantId::EnumVariantId(it) => (it.parent.resolver(db), it.parent.into()), |
506 | }; | 620 | }; |
621 | let generics = generics(db, def); | ||
507 | let mut res = ArenaMap::default(); | 622 | let mut res = ArenaMap::default(); |
623 | let ctx = | ||
624 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | ||
508 | for (field_id, field_data) in var_data.fields().iter() { | 625 | for (field_id, field_data) in var_data.fields().iter() { |
509 | res.insert(field_id, Ty::from_hir(db, &resolver, &field_data.type_ref)) | 626 | res.insert(field_id, Binders::new(generics.len(), Ty::from_hir(&ctx, &field_data.type_ref))) |
510 | } | 627 | } |
511 | Arc::new(res) | 628 | Arc::new(res) |
512 | } | 629 | } |
@@ -521,32 +638,43 @@ pub(crate) fn field_types_query( | |||
521 | /// these are fine: `T: Foo<U::Item>, U: Foo<()>`. | 638 | /// these are fine: `T: Foo<U::Item>, U: Foo<()>`. |
522 | pub(crate) fn generic_predicates_for_param_query( | 639 | pub(crate) fn generic_predicates_for_param_query( |
523 | db: &impl HirDatabase, | 640 | db: &impl HirDatabase, |
524 | def: GenericDefId, | 641 | param_id: TypeParamId, |
525 | param_idx: u32, | 642 | ) -> Arc<[Binders<GenericPredicate>]> { |
526 | ) -> Arc<[GenericPredicate]> { | 643 | let resolver = param_id.parent.resolver(db); |
527 | let resolver = def.resolver(db); | 644 | let ctx = |
645 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | ||
646 | let generics = generics(db, param_id.parent); | ||
528 | resolver | 647 | resolver |
529 | .where_predicates_in_scope() | 648 | .where_predicates_in_scope() |
530 | // we have to filter out all other predicates *first*, before attempting to lower them | 649 | // we have to filter out all other predicates *first*, before attempting to lower them |
531 | .filter(|pred| Ty::from_hir_only_param(db, &resolver, &pred.type_ref) == Some(param_idx)) | 650 | .filter(|pred| match &pred.target { |
532 | .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) | 651 | WherePredicateTarget::TypeRef(type_ref) => { |
652 | Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id) | ||
653 | } | ||
654 | WherePredicateTarget::TypeParam(local_id) => *local_id == param_id.local_id, | ||
655 | }) | ||
656 | .flat_map(|pred| { | ||
657 | GenericPredicate::from_where_predicate(&ctx, pred) | ||
658 | .map(|p| Binders::new(generics.len(), p)) | ||
659 | }) | ||
533 | .collect() | 660 | .collect() |
534 | } | 661 | } |
535 | 662 | ||
536 | pub(crate) fn generic_predicates_for_param_recover( | 663 | pub(crate) fn generic_predicates_for_param_recover( |
537 | _db: &impl HirDatabase, | 664 | _db: &impl HirDatabase, |
538 | _cycle: &[String], | 665 | _cycle: &[String], |
539 | _def: &GenericDefId, | 666 | _param_id: &TypeParamId, |
540 | _param_idx: &u32, | 667 | ) -> Arc<[Binders<GenericPredicate>]> { |
541 | ) -> Arc<[GenericPredicate]> { | ||
542 | Arc::new([]) | 668 | Arc::new([]) |
543 | } | 669 | } |
544 | 670 | ||
545 | impl TraitEnvironment { | 671 | impl TraitEnvironment { |
546 | pub fn lower(db: &impl HirDatabase, resolver: &Resolver) -> Arc<TraitEnvironment> { | 672 | pub fn lower(db: &impl HirDatabase, resolver: &Resolver) -> Arc<TraitEnvironment> { |
673 | let ctx = TyLoweringContext::new(db, &resolver) | ||
674 | .with_type_param_mode(TypeParamLoweringMode::Placeholder); | ||
547 | let predicates = resolver | 675 | let predicates = resolver |
548 | .where_predicates_in_scope() | 676 | .where_predicates_in_scope() |
549 | .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) | 677 | .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) |
550 | .collect::<Vec<_>>(); | 678 | .collect::<Vec<_>>(); |
551 | 679 | ||
552 | Arc::new(TraitEnvironment { predicates }) | 680 | Arc::new(TraitEnvironment { predicates }) |
@@ -557,57 +685,74 @@ impl TraitEnvironment { | |||
557 | pub(crate) fn generic_predicates_query( | 685 | pub(crate) fn generic_predicates_query( |
558 | db: &impl HirDatabase, | 686 | db: &impl HirDatabase, |
559 | def: GenericDefId, | 687 | def: GenericDefId, |
560 | ) -> Arc<[GenericPredicate]> { | 688 | ) -> Arc<[Binders<GenericPredicate>]> { |
561 | let resolver = def.resolver(db); | 689 | let resolver = def.resolver(db); |
690 | let ctx = | ||
691 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | ||
692 | let generics = generics(db, def); | ||
562 | resolver | 693 | resolver |
563 | .where_predicates_in_scope() | 694 | .where_predicates_in_scope() |
564 | .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) | 695 | .flat_map(|pred| { |
696 | GenericPredicate::from_where_predicate(&ctx, pred) | ||
697 | .map(|p| Binders::new(generics.len(), p)) | ||
698 | }) | ||
565 | .collect() | 699 | .collect() |
566 | } | 700 | } |
567 | 701 | ||
568 | /// Resolve the default type params from generics | 702 | /// Resolve the default type params from generics |
569 | pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDefId) -> Substs { | 703 | pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDefId) -> Substs { |
570 | let resolver = def.resolver(db); | 704 | let resolver = def.resolver(db); |
705 | let ctx = TyLoweringContext::new(db, &resolver); | ||
571 | let generic_params = generics(db, def.into()); | 706 | let generic_params = generics(db, def.into()); |
572 | 707 | ||
573 | let defaults = generic_params | 708 | let defaults = generic_params |
574 | .iter() | 709 | .iter() |
575 | .map(|(_idx, p)| p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(db, &resolver, t))) | 710 | .map(|(_idx, p)| p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(&ctx, t))) |
576 | .collect(); | 711 | .collect(); |
577 | 712 | ||
578 | Substs(defaults) | 713 | Substs(defaults) |
579 | } | 714 | } |
580 | 715 | ||
581 | fn fn_sig_for_fn(db: &impl HirDatabase, def: FunctionId) -> FnSig { | 716 | fn fn_sig_for_fn(db: &impl HirDatabase, def: FunctionId) -> PolyFnSig { |
582 | let data = db.function_data(def); | 717 | let data = db.function_data(def); |
583 | let resolver = def.resolver(db); | 718 | let resolver = def.resolver(db); |
584 | let params = data.params.iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>(); | 719 | let ctx_params = TyLoweringContext::new(db, &resolver) |
585 | let ret = Ty::from_hir(db, &resolver, &data.ret_type); | 720 | .with_impl_trait_mode(ImplTraitLoweringMode::Variable) |
586 | FnSig::from_params_and_return(params, ret) | 721 | .with_type_param_mode(TypeParamLoweringMode::Variable); |
722 | let params = data.params.iter().map(|tr| Ty::from_hir(&ctx_params, tr)).collect::<Vec<_>>(); | ||
723 | let ctx_ret = ctx_params.with_impl_trait_mode(ImplTraitLoweringMode::Opaque); | ||
724 | let ret = Ty::from_hir(&ctx_ret, &data.ret_type); | ||
725 | let generics = generics(db, def.into()); | ||
726 | let num_binders = generics.len(); | ||
727 | Binders::new(num_binders, FnSig::from_params_and_return(params, ret)) | ||
587 | } | 728 | } |
588 | 729 | ||
589 | /// Build the declared type of a function. This should not need to look at the | 730 | /// Build the declared type of a function. This should not need to look at the |
590 | /// function body. | 731 | /// function body. |
591 | fn type_for_fn(db: &impl HirDatabase, def: FunctionId) -> Ty { | 732 | fn type_for_fn(db: &impl HirDatabase, def: FunctionId) -> Binders<Ty> { |
592 | let generics = generics(db, def.into()); | 733 | let generics = generics(db, def.into()); |
593 | let substs = Substs::identity(&generics); | 734 | let substs = Substs::bound_vars(&generics); |
594 | Ty::apply(TypeCtor::FnDef(def.into()), substs) | 735 | Binders::new(substs.len(), Ty::apply(TypeCtor::FnDef(def.into()), substs)) |
595 | } | 736 | } |
596 | 737 | ||
597 | /// Build the declared type of a const. | 738 | /// Build the declared type of a const. |
598 | fn type_for_const(db: &impl HirDatabase, def: ConstId) -> Ty { | 739 | fn type_for_const(db: &impl HirDatabase, def: ConstId) -> Binders<Ty> { |
599 | let data = db.const_data(def); | 740 | let data = db.const_data(def); |
741 | let generics = generics(db, def.into()); | ||
600 | let resolver = def.resolver(db); | 742 | let resolver = def.resolver(db); |
743 | let ctx = | ||
744 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | ||
601 | 745 | ||
602 | Ty::from_hir(db, &resolver, &data.type_ref) | 746 | Binders::new(generics.len(), Ty::from_hir(&ctx, &data.type_ref)) |
603 | } | 747 | } |
604 | 748 | ||
605 | /// Build the declared type of a static. | 749 | /// Build the declared type of a static. |
606 | fn type_for_static(db: &impl HirDatabase, def: StaticId) -> Ty { | 750 | fn type_for_static(db: &impl HirDatabase, def: StaticId) -> Binders<Ty> { |
607 | let data = db.static_data(def); | 751 | let data = db.static_data(def); |
608 | let resolver = def.resolver(db); | 752 | let resolver = def.resolver(db); |
753 | let ctx = TyLoweringContext::new(db, &resolver); | ||
609 | 754 | ||
610 | Ty::from_hir(db, &resolver, &data.type_ref) | 755 | Binders::new(0, Ty::from_hir(&ctx, &data.type_ref)) |
611 | } | 756 | } |
612 | 757 | ||
613 | /// Build the declared type of a static. | 758 | /// Build the declared type of a static. |
@@ -621,68 +766,69 @@ fn type_for_builtin(def: BuiltinType) -> Ty { | |||
621 | }) | 766 | }) |
622 | } | 767 | } |
623 | 768 | ||
624 | fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> FnSig { | 769 | fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> PolyFnSig { |
625 | let struct_data = db.struct_data(def.into()); | 770 | let struct_data = db.struct_data(def.into()); |
626 | let fields = struct_data.variant_data.fields(); | 771 | let fields = struct_data.variant_data.fields(); |
627 | let resolver = def.resolver(db); | 772 | let resolver = def.resolver(db); |
628 | let params = fields | 773 | let ctx = |
629 | .iter() | 774 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); |
630 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) | 775 | let params = |
631 | .collect::<Vec<_>>(); | 776 | fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>(); |
632 | let ret = type_for_adt(db, def.into()); | 777 | let ret = type_for_adt(db, def.into()); |
633 | FnSig::from_params_and_return(params, ret) | 778 | Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value)) |
634 | } | 779 | } |
635 | 780 | ||
636 | /// Build the type of a tuple struct constructor. | 781 | /// Build the type of a tuple struct constructor. |
637 | fn type_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> Ty { | 782 | fn type_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> Binders<Ty> { |
638 | let struct_data = db.struct_data(def.into()); | 783 | let struct_data = db.struct_data(def.into()); |
639 | if struct_data.variant_data.is_unit() { | 784 | if struct_data.variant_data.is_unit() { |
640 | return type_for_adt(db, def.into()); // Unit struct | 785 | return type_for_adt(db, def.into()); // Unit struct |
641 | } | 786 | } |
642 | let generics = generics(db, def.into()); | 787 | let generics = generics(db, def.into()); |
643 | let substs = Substs::identity(&generics); | 788 | let substs = Substs::bound_vars(&generics); |
644 | Ty::apply(TypeCtor::FnDef(def.into()), substs) | 789 | Binders::new(substs.len(), Ty::apply(TypeCtor::FnDef(def.into()), substs)) |
645 | } | 790 | } |
646 | 791 | ||
647 | fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> FnSig { | 792 | fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> PolyFnSig { |
648 | let enum_data = db.enum_data(def.parent); | 793 | let enum_data = db.enum_data(def.parent); |
649 | let var_data = &enum_data.variants[def.local_id]; | 794 | let var_data = &enum_data.variants[def.local_id]; |
650 | let fields = var_data.variant_data.fields(); | 795 | let fields = var_data.variant_data.fields(); |
651 | let resolver = def.parent.resolver(db); | 796 | let resolver = def.parent.resolver(db); |
652 | let params = fields | 797 | let ctx = |
653 | .iter() | 798 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); |
654 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) | 799 | let params = |
655 | .collect::<Vec<_>>(); | 800 | fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>(); |
656 | let generics = generics(db, def.parent.into()); | 801 | let ret = type_for_adt(db, def.parent.into()); |
657 | let substs = Substs::identity(&generics); | 802 | Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value)) |
658 | let ret = type_for_adt(db, def.parent.into()).subst(&substs); | ||
659 | FnSig::from_params_and_return(params, ret) | ||
660 | } | 803 | } |
661 | 804 | ||
662 | /// Build the type of a tuple enum variant constructor. | 805 | /// Build the type of a tuple enum variant constructor. |
663 | fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> Ty { | 806 | fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> Binders<Ty> { |
664 | let enum_data = db.enum_data(def.parent); | 807 | let enum_data = db.enum_data(def.parent); |
665 | let var_data = &enum_data.variants[def.local_id].variant_data; | 808 | let var_data = &enum_data.variants[def.local_id].variant_data; |
666 | if var_data.is_unit() { | 809 | if var_data.is_unit() { |
667 | return type_for_adt(db, def.parent.into()); // Unit variant | 810 | return type_for_adt(db, def.parent.into()); // Unit variant |
668 | } | 811 | } |
669 | let generics = generics(db, def.parent.into()); | 812 | let generics = generics(db, def.parent.into()); |
670 | let substs = Substs::identity(&generics); | 813 | let substs = Substs::bound_vars(&generics); |
671 | Ty::apply(TypeCtor::FnDef(EnumVariantId::from(def).into()), substs) | 814 | Binders::new(substs.len(), Ty::apply(TypeCtor::FnDef(EnumVariantId::from(def).into()), substs)) |
672 | } | 815 | } |
673 | 816 | ||
674 | fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Ty { | 817 | fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Binders<Ty> { |
675 | let generics = generics(db, adt.into()); | 818 | let generics = generics(db, adt.into()); |
676 | Ty::apply(TypeCtor::Adt(adt), Substs::identity(&generics)) | 819 | let substs = Substs::bound_vars(&generics); |
820 | Binders::new(substs.len(), Ty::apply(TypeCtor::Adt(adt), substs)) | ||
677 | } | 821 | } |
678 | 822 | ||
679 | fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Ty { | 823 | fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Binders<Ty> { |
680 | let generics = generics(db, t.into()); | 824 | let generics = generics(db, t.into()); |
681 | let resolver = t.resolver(db); | 825 | let resolver = t.resolver(db); |
826 | let ctx = | ||
827 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | ||
682 | let type_ref = &db.type_alias_data(t).type_ref; | 828 | let type_ref = &db.type_alias_data(t).type_ref; |
683 | let substs = Substs::identity(&generics); | 829 | let substs = Substs::bound_vars(&generics); |
684 | let inner = Ty::from_hir(db, &resolver, type_ref.as_ref().unwrap_or(&TypeRef::Error)); | 830 | let inner = Ty::from_hir(&ctx, type_ref.as_ref().unwrap_or(&TypeRef::Error)); |
685 | inner.subst(&substs) | 831 | Binders::new(substs.len(), inner) |
686 | } | 832 | } |
687 | 833 | ||
688 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | 834 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
@@ -736,19 +882,24 @@ impl_froms!(ValueTyDefId: FunctionId, StructId, EnumVariantId, ConstId, StaticId | |||
736 | /// `struct Foo(usize)`, we have two types: The type of the struct itself, and | 882 | /// `struct Foo(usize)`, we have two types: The type of the struct itself, and |
737 | /// the constructor function `(usize) -> Foo` which lives in the values | 883 | /// the constructor function `(usize) -> Foo` which lives in the values |
738 | /// namespace. | 884 | /// namespace. |
739 | pub(crate) fn ty_query(db: &impl HirDatabase, def: TyDefId) -> Ty { | 885 | pub(crate) fn ty_query(db: &impl HirDatabase, def: TyDefId) -> Binders<Ty> { |
740 | match def { | 886 | match def { |
741 | TyDefId::BuiltinType(it) => type_for_builtin(it), | 887 | TyDefId::BuiltinType(it) => Binders::new(0, type_for_builtin(it)), |
742 | TyDefId::AdtId(it) => type_for_adt(db, it), | 888 | TyDefId::AdtId(it) => type_for_adt(db, it), |
743 | TyDefId::TypeAliasId(it) => type_for_type_alias(db, it), | 889 | TyDefId::TypeAliasId(it) => type_for_type_alias(db, it), |
744 | } | 890 | } |
745 | } | 891 | } |
746 | 892 | ||
747 | pub(crate) fn ty_recover(_db: &impl HirDatabase, _cycle: &[String], _def: &TyDefId) -> Ty { | 893 | pub(crate) fn ty_recover(db: &impl HirDatabase, _cycle: &[String], def: &TyDefId) -> Binders<Ty> { |
748 | Ty::Unknown | 894 | let num_binders = match *def { |
895 | TyDefId::BuiltinType(_) => 0, | ||
896 | TyDefId::AdtId(it) => generics(db, it.into()).len(), | ||
897 | TyDefId::TypeAliasId(it) => generics(db, it.into()).len(), | ||
898 | }; | ||
899 | Binders::new(num_binders, Ty::Unknown) | ||
749 | } | 900 | } |
750 | 901 | ||
751 | pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty { | 902 | pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Binders<Ty> { |
752 | match def { | 903 | match def { |
753 | ValueTyDefId::FunctionId(it) => type_for_fn(db, it), | 904 | ValueTyDefId::FunctionId(it) => type_for_fn(db, it), |
754 | ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it), | 905 | ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it), |
@@ -758,24 +909,36 @@ pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty { | |||
758 | } | 909 | } |
759 | } | 910 | } |
760 | 911 | ||
761 | pub(crate) fn impl_self_ty_query(db: &impl HirDatabase, impl_id: ImplId) -> Ty { | 912 | pub(crate) fn impl_self_ty_query(db: &impl HirDatabase, impl_id: ImplId) -> Binders<Ty> { |
762 | let impl_data = db.impl_data(impl_id); | 913 | let impl_data = db.impl_data(impl_id); |
763 | let resolver = impl_id.resolver(db); | 914 | let resolver = impl_id.resolver(db); |
764 | Ty::from_hir(db, &resolver, &impl_data.target_type) | 915 | let generics = generics(db, impl_id.into()); |
916 | let ctx = | ||
917 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | ||
918 | Binders::new(generics.len(), Ty::from_hir(&ctx, &impl_data.target_type)) | ||
765 | } | 919 | } |
766 | 920 | ||
767 | pub(crate) fn impl_self_ty_recover( | 921 | pub(crate) fn impl_self_ty_recover( |
768 | _db: &impl HirDatabase, | 922 | db: &impl HirDatabase, |
769 | _cycle: &[String], | 923 | _cycle: &[String], |
770 | _impl_id: &ImplId, | 924 | impl_id: &ImplId, |
771 | ) -> Ty { | 925 | ) -> Binders<Ty> { |
772 | Ty::Unknown | 926 | let generics = generics(db, (*impl_id).into()); |
927 | Binders::new(generics.len(), Ty::Unknown) | ||
773 | } | 928 | } |
774 | 929 | ||
775 | pub(crate) fn impl_trait_query(db: &impl HirDatabase, impl_id: ImplId) -> Option<TraitRef> { | 930 | pub(crate) fn impl_trait_query( |
931 | db: &impl HirDatabase, | ||
932 | impl_id: ImplId, | ||
933 | ) -> Option<Binders<TraitRef>> { | ||
776 | let impl_data = db.impl_data(impl_id); | 934 | let impl_data = db.impl_data(impl_id); |
777 | let resolver = impl_id.resolver(db); | 935 | let resolver = impl_id.resolver(db); |
936 | let ctx = | ||
937 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | ||
778 | let self_ty = db.impl_self_ty(impl_id); | 938 | let self_ty = db.impl_self_ty(impl_id); |
779 | let target_trait = impl_data.target_trait.as_ref()?; | 939 | let target_trait = impl_data.target_trait.as_ref()?; |
780 | TraitRef::from_hir(db, &resolver, target_trait, Some(self_ty.clone())) | 940 | Some(Binders::new( |
941 | self_ty.num_binders, | ||
942 | TraitRef::from_hir(&ctx, target_trait, Some(self_ty.value.clone()))?, | ||
943 | )) | ||
781 | } | 944 | } |
diff --git a/crates/ra_hir_ty/src/marks.rs b/crates/ra_hir_ty/src/marks.rs index fe74acf11..0f754eb9c 100644 --- a/crates/ra_hir_ty/src/marks.rs +++ b/crates/ra_hir_ty/src/marks.rs | |||
@@ -6,5 +6,4 @@ test_utils::marks!( | |||
6 | type_var_resolves_to_int_var | 6 | type_var_resolves_to_int_var |
7 | match_ergonomics_ref | 7 | match_ergonomics_ref |
8 | coerce_merge_fail_fallback | 8 | coerce_merge_fail_fallback |
9 | insert_vars_for_impl_trait | ||
10 | ); | 9 | ); |
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index 5bacbbd7c..5283bff28 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs | |||
@@ -61,11 +61,11 @@ impl CrateImplBlocks { | |||
61 | for impl_id in module_data.scope.impls() { | 61 | for impl_id in module_data.scope.impls() { |
62 | match db.impl_trait(impl_id) { | 62 | match db.impl_trait(impl_id) { |
63 | Some(tr) => { | 63 | Some(tr) => { |
64 | res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id); | 64 | res.impls_by_trait.entry(tr.value.trait_).or_default().push(impl_id); |
65 | } | 65 | } |
66 | None => { | 66 | None => { |
67 | let self_ty = db.impl_self_ty(impl_id); | 67 | let self_ty = db.impl_self_ty(impl_id); |
68 | if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty) { | 68 | if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty.value) { |
69 | res.impls.entry(self_ty_fp).or_default().push(impl_id); | 69 | res.impls.entry(self_ty_fp).or_default().push(impl_id); |
70 | } | 70 | } |
71 | } | 71 | } |
@@ -496,7 +496,7 @@ fn transform_receiver_ty( | |||
496 | AssocContainerId::ContainerId(_) => unreachable!(), | 496 | AssocContainerId::ContainerId(_) => unreachable!(), |
497 | }; | 497 | }; |
498 | let sig = db.callable_item_signature(function_id.into()); | 498 | let sig = db.callable_item_signature(function_id.into()); |
499 | Some(sig.params()[0].clone().subst(&substs)) | 499 | Some(sig.value.params()[0].clone().subst_bound_vars(&substs)) |
500 | } | 500 | } |
501 | 501 | ||
502 | pub fn implements_trait( | 502 | pub fn implements_trait( |
diff --git a/crates/ra_hir_ty/src/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs index 76a1b46c0..fc5ef36a5 100644 --- a/crates/ra_hir_ty/src/tests/coercion.rs +++ b/crates/ra_hir_ty/src/tests/coercion.rs | |||
@@ -75,7 +75,7 @@ fn test2() { | |||
75 | [124; 131) 'loop {}': ! | 75 | [124; 131) 'loop {}': ! |
76 | [129; 131) '{}': () | 76 | [129; 131) '{}': () |
77 | [160; 173) '{ gen() }': *mut [U] | 77 | [160; 173) '{ gen() }': *mut [U] |
78 | [166; 169) 'gen': fn gen<U>() -> *mut [T; _] | 78 | [166; 169) 'gen': fn gen<U>() -> *mut [U; _] |
79 | [166; 171) 'gen()': *mut [U; _] | 79 | [166; 171) 'gen()': *mut [U; _] |
80 | [186; 420) '{ ...rr); }': () | 80 | [186; 420) '{ ...rr); }': () |
81 | [196; 199) 'arr': &[u8; _] | 81 | [196; 199) 'arr': &[u8; _] |
@@ -85,14 +85,14 @@ fn test2() { | |||
85 | [227; 228) 'a': &[u8] | 85 | [227; 228) 'a': &[u8] |
86 | [237; 240) 'arr': &[u8; _] | 86 | [237; 240) 'arr': &[u8; _] |
87 | [250; 251) 'b': u8 | 87 | [250; 251) 'b': u8 |
88 | [254; 255) 'f': fn f<u8>(&[T]) -> T | 88 | [254; 255) 'f': fn f<u8>(&[u8]) -> u8 |
89 | [254; 260) 'f(arr)': u8 | 89 | [254; 260) 'f(arr)': u8 |
90 | [256; 259) 'arr': &[u8; _] | 90 | [256; 259) 'arr': &[u8; _] |
91 | [270; 271) 'c': &[u8] | 91 | [270; 271) 'c': &[u8] |
92 | [280; 287) '{ arr }': &[u8] | 92 | [280; 287) '{ arr }': &[u8] |
93 | [282; 285) 'arr': &[u8; _] | 93 | [282; 285) 'arr': &[u8; _] |
94 | [297; 298) 'd': u8 | 94 | [297; 298) 'd': u8 |
95 | [301; 302) 'g': fn g<u8>(S<&[T]>) -> T | 95 | [301; 302) 'g': fn g<u8>(S<&[u8]>) -> u8 |
96 | [301; 316) 'g(S { a: arr })': u8 | 96 | [301; 316) 'g(S { a: arr })': u8 |
97 | [303; 315) 'S { a: arr }': S<&[u8]> | 97 | [303; 315) 'S { a: arr }': S<&[u8]> |
98 | [310; 313) 'arr': &[u8; _] | 98 | [310; 313) 'arr': &[u8; _] |
@@ -164,15 +164,15 @@ fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) { | |||
164 | [400; 401) 'c': C<[u8; _]> | 164 | [400; 401) 'c': C<[u8; _]> |
165 | [415; 481) '{ ...(c); }': () | 165 | [415; 481) '{ ...(c); }': () |
166 | [425; 426) 'd': A<[{unknown}]> | 166 | [425; 426) 'd': A<[{unknown}]> |
167 | [429; 433) 'foo1': fn foo1<{unknown}>(A<[T]>) -> A<[T]> | 167 | [429; 433) 'foo1': fn foo1<{unknown}>(A<[{unknown}]>) -> A<[{unknown}]> |
168 | [429; 436) 'foo1(a)': A<[{unknown}]> | 168 | [429; 436) 'foo1(a)': A<[{unknown}]> |
169 | [434; 435) 'a': A<[u8; _]> | 169 | [434; 435) 'a': A<[u8; _]> |
170 | [446; 447) 'e': B<[u8]> | 170 | [446; 447) 'e': B<[u8]> |
171 | [450; 454) 'foo2': fn foo2<u8>(B<[T]>) -> B<[T]> | 171 | [450; 454) 'foo2': fn foo2<u8>(B<[u8]>) -> B<[u8]> |
172 | [450; 457) 'foo2(b)': B<[u8]> | 172 | [450; 457) 'foo2(b)': B<[u8]> |
173 | [455; 456) 'b': B<[u8; _]> | 173 | [455; 456) 'b': B<[u8; _]> |
174 | [467; 468) 'f': C<[u8]> | 174 | [467; 468) 'f': C<[u8]> |
175 | [471; 475) 'foo3': fn foo3<u8>(C<[T]>) -> C<[T]> | 175 | [471; 475) 'foo3': fn foo3<u8>(C<[u8]>) -> C<[u8]> |
176 | [471; 478) 'foo3(c)': C<[u8]> | 176 | [471; 478) 'foo3(c)': C<[u8]> |
177 | [476; 477) 'c': C<[u8; _]> | 177 | [476; 477) 'c': C<[u8; _]> |
178 | "### | 178 | "### |
@@ -202,7 +202,7 @@ fn test() { | |||
202 | [64; 123) 'if tru... }': &[i32] | 202 | [64; 123) 'if tru... }': &[i32] |
203 | [67; 71) 'true': bool | 203 | [67; 71) 'true': bool |
204 | [72; 97) '{ ... }': &[i32] | 204 | [72; 97) '{ ... }': &[i32] |
205 | [82; 85) 'foo': fn foo<i32>(&[T]) -> &[T] | 205 | [82; 85) 'foo': fn foo<i32>(&[i32]) -> &[i32] |
206 | [82; 91) 'foo(&[1])': &[i32] | 206 | [82; 91) 'foo(&[1])': &[i32] |
207 | [86; 90) '&[1]': &[i32; _] | 207 | [86; 90) '&[1]': &[i32; _] |
208 | [87; 90) '[1]': [i32; _] | 208 | [87; 90) '[1]': [i32; _] |
@@ -242,7 +242,7 @@ fn test() { | |||
242 | [83; 86) '[1]': [i32; _] | 242 | [83; 86) '[1]': [i32; _] |
243 | [84; 85) '1': i32 | 243 | [84; 85) '1': i32 |
244 | [98; 123) '{ ... }': &[i32] | 244 | [98; 123) '{ ... }': &[i32] |
245 | [108; 111) 'foo': fn foo<i32>(&[T]) -> &[T] | 245 | [108; 111) 'foo': fn foo<i32>(&[i32]) -> &[i32] |
246 | [108; 117) 'foo(&[1])': &[i32] | 246 | [108; 117) 'foo(&[1])': &[i32] |
247 | [112; 116) '&[1]': &[i32; _] | 247 | [112; 116) '&[1]': &[i32; _] |
248 | [113; 116) '[1]': [i32; _] | 248 | [113; 116) '[1]': [i32; _] |
@@ -275,7 +275,7 @@ 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 | [93; 96) 'foo': fn foo<i32>(&[T]) -> &[T] | 278 | [93; 96) 'foo': fn foo<i32>(&[i32]) -> &[i32] |
279 | [93; 102) 'foo(&[2])': &[i32] | 279 | [93; 102) 'foo(&[2])': &[i32] |
280 | [97; 101) '&[2]': &[i32; _] | 280 | [97; 101) '&[2]': &[i32; _] |
281 | [98; 101) '[2]': [i32; _] | 281 | [98; 101) '[2]': [i32; _] |
@@ -320,7 +320,7 @@ fn test(i: i32) { | |||
320 | [94; 97) '[1]': [i32; _] | 320 | [94; 97) '[1]': [i32; _] |
321 | [95; 96) '1': i32 | 321 | [95; 96) '1': i32 |
322 | [107; 108) '2': i32 | 322 | [107; 108) '2': i32 |
323 | [112; 115) 'foo': fn foo<i32>(&[T]) -> &[T] | 323 | [112; 115) 'foo': fn foo<i32>(&[i32]) -> &[i32] |
324 | [112; 121) 'foo(&[2])': &[i32] | 324 | [112; 121) 'foo(&[2])': &[i32] |
325 | [116; 120) '&[2]': &[i32; _] | 325 | [116; 120) '&[2]': &[i32; _] |
326 | [117; 120) '[2]': [i32; _] | 326 | [117; 120) '[2]': [i32; _] |
@@ -438,16 +438,16 @@ fn test() { | |||
438 | [43; 45) '*x': T | 438 | [43; 45) '*x': T |
439 | [44; 45) 'x': &T | 439 | [44; 45) 'x': &T |
440 | [58; 127) '{ ...oo); }': () | 440 | [58; 127) '{ ...oo); }': () |
441 | [64; 73) 'takes_ref': fn takes_ref<Foo>(&T) -> T | 441 | [64; 73) 'takes_ref': fn takes_ref<Foo>(&Foo) -> Foo |
442 | [64; 79) 'takes_ref(&Foo)': Foo | 442 | [64; 79) 'takes_ref(&Foo)': Foo |
443 | [74; 78) '&Foo': &Foo | 443 | [74; 78) '&Foo': &Foo |
444 | [75; 78) 'Foo': Foo | 444 | [75; 78) 'Foo': Foo |
445 | [85; 94) 'takes_ref': fn takes_ref<&Foo>(&T) -> T | 445 | [85; 94) 'takes_ref': fn takes_ref<&Foo>(&&Foo) -> &Foo |
446 | [85; 101) 'takes_...&&Foo)': &Foo | 446 | [85; 101) 'takes_...&&Foo)': &Foo |
447 | [95; 100) '&&Foo': &&Foo | 447 | [95; 100) '&&Foo': &&Foo |
448 | [96; 100) '&Foo': &Foo | 448 | [96; 100) '&Foo': &Foo |
449 | [97; 100) 'Foo': Foo | 449 | [97; 100) 'Foo': Foo |
450 | [107; 116) 'takes_ref': fn takes_ref<&&Foo>(&T) -> T | 450 | [107; 116) 'takes_ref': fn takes_ref<&&Foo>(&&&Foo) -> &&Foo |
451 | [107; 124) 'takes_...&&Foo)': &&Foo | 451 | [107; 124) 'takes_...&&Foo)': &&Foo |
452 | [117; 123) '&&&Foo': &&&Foo | 452 | [117; 123) '&&&Foo': &&&Foo |
453 | [118; 123) '&&Foo': &&Foo | 453 | [118; 123) '&&Foo': &&Foo |
diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs index ce9a06fde..1722563aa 100644 --- a/crates/ra_hir_ty/src/tests/method_resolution.rs +++ b/crates/ra_hir_ty/src/tests/method_resolution.rs | |||
@@ -27,7 +27,7 @@ fn test() { | |||
27 | [66; 73) 'loop {}': ! | 27 | [66; 73) 'loop {}': ! |
28 | [71; 73) '{}': () | 28 | [71; 73) '{}': () |
29 | [133; 160) '{ ...o"); }': () | 29 | [133; 160) '{ ...o"); }': () |
30 | [139; 149) '<[_]>::foo': fn foo<u8>(&[T]) -> T | 30 | [139; 149) '<[_]>::foo': fn foo<u8>(&[u8]) -> u8 |
31 | [139; 157) '<[_]>:..."foo")': u8 | 31 | [139; 157) '<[_]>:..."foo")': u8 |
32 | [150; 156) 'b"foo"': &[u8] | 32 | [150; 156) 'b"foo"': &[u8] |
33 | "### | 33 | "### |
@@ -175,7 +175,7 @@ fn test() { | |||
175 | [98; 101) 'val': T | 175 | [98; 101) 'val': T |
176 | [123; 155) '{ ...32); }': () | 176 | [123; 155) '{ ...32); }': () |
177 | [133; 134) 'a': Gen<u32> | 177 | [133; 134) 'a': Gen<u32> |
178 | [137; 146) 'Gen::make': fn make<u32>(T) -> Gen<T> | 178 | [137; 146) 'Gen::make': fn make<u32>(u32) -> Gen<u32> |
179 | [137; 152) 'Gen::make(0u32)': Gen<u32> | 179 | [137; 152) 'Gen::make(0u32)': Gen<u32> |
180 | [147; 151) '0u32': u32 | 180 | [147; 151) '0u32': u32 |
181 | "### | 181 | "### |
@@ -206,7 +206,7 @@ fn test() { | |||
206 | [95; 98) '{ }': () | 206 | [95; 98) '{ }': () |
207 | [118; 146) '{ ...e(); }': () | 207 | [118; 146) '{ ...e(); }': () |
208 | [128; 129) 'a': Gen<u32> | 208 | [128; 129) 'a': Gen<u32> |
209 | [132; 141) 'Gen::make': fn make<u32>() -> Gen<T> | 209 | [132; 141) 'Gen::make': fn make<u32>() -> Gen<u32> |
210 | [132; 143) 'Gen::make()': Gen<u32> | 210 | [132; 143) 'Gen::make()': Gen<u32> |
211 | "### | 211 | "### |
212 | ); | 212 | ); |
@@ -260,7 +260,7 @@ fn test() { | |||
260 | [91; 94) '{ }': () | 260 | [91; 94) '{ }': () |
261 | [114; 149) '{ ...e(); }': () | 261 | [114; 149) '{ ...e(); }': () |
262 | [124; 125) 'a': Gen<u32> | 262 | [124; 125) 'a': Gen<u32> |
263 | [128; 144) 'Gen::<...::make': fn make<u32>() -> Gen<T> | 263 | [128; 144) 'Gen::<...::make': fn make<u32>() -> Gen<u32> |
264 | [128; 146) 'Gen::<...make()': Gen<u32> | 264 | [128; 146) 'Gen::<...make()': Gen<u32> |
265 | "### | 265 | "### |
266 | ); | 266 | ); |
@@ -291,7 +291,7 @@ fn test() { | |||
291 | [117; 120) '{ }': () | 291 | [117; 120) '{ }': () |
292 | [140; 180) '{ ...e(); }': () | 292 | [140; 180) '{ ...e(); }': () |
293 | [150; 151) 'a': Gen<u32, u64> | 293 | [150; 151) 'a': Gen<u32, u64> |
294 | [154; 175) 'Gen::<...::make': fn make<u64>() -> Gen<u32, T> | 294 | [154; 175) 'Gen::<...::make': fn make<u64>() -> Gen<u32, u64> |
295 | [154; 177) 'Gen::<...make()': Gen<u32, u64> | 295 | [154; 177) 'Gen::<...make()': Gen<u32, u64> |
296 | "### | 296 | "### |
297 | ); | 297 | ); |
@@ -475,7 +475,7 @@ fn test() { | |||
475 | @r###" | 475 | @r###" |
476 | [33; 37) 'self': &Self | 476 | [33; 37) 'self': &Self |
477 | [102; 127) '{ ...d(); }': () | 477 | [102; 127) '{ ...d(); }': () |
478 | [108; 109) 'S': S<u32>(T) -> S<T> | 478 | [108; 109) 'S': S<u32>(u32) -> S<u32> |
479 | [108; 115) 'S(1u32)': S<u32> | 479 | [108; 115) 'S(1u32)': S<u32> |
480 | [108; 124) 'S(1u32...thod()': u32 | 480 | [108; 124) 'S(1u32...thod()': u32 |
481 | [110; 114) '1u32': u32 | 481 | [110; 114) '1u32': u32 |
@@ -501,13 +501,13 @@ fn test() { | |||
501 | @r###" | 501 | @r###" |
502 | [87; 193) '{ ...t(); }': () | 502 | [87; 193) '{ ...t(); }': () |
503 | [97; 99) 's1': S | 503 | [97; 99) 's1': S |
504 | [105; 121) 'Defaul...efault': fn default<S>() -> Self | 504 | [105; 121) 'Defaul...efault': fn default<S>() -> S |
505 | [105; 123) 'Defaul...ault()': S | 505 | [105; 123) 'Defaul...ault()': S |
506 | [133; 135) 's2': S | 506 | [133; 135) 's2': S |
507 | [138; 148) 'S::default': fn default<S>() -> Self | 507 | [138; 148) 'S::default': fn default<S>() -> S |
508 | [138; 150) 'S::default()': S | 508 | [138; 150) 'S::default()': S |
509 | [160; 162) 's3': S | 509 | [160; 162) 's3': S |
510 | [165; 188) '<S as ...efault': fn default<S>() -> Self | 510 | [165; 188) '<S as ...efault': fn default<S>() -> S |
511 | [165; 190) '<S as ...ault()': S | 511 | [165; 190) '<S as ...ault()': S |
512 | "### | 512 | "### |
513 | ); | 513 | ); |
@@ -533,13 +533,13 @@ fn test() { | |||
533 | @r###" | 533 | @r###" |
534 | [127; 211) '{ ...e(); }': () | 534 | [127; 211) '{ ...e(); }': () |
535 | [137; 138) 'a': u32 | 535 | [137; 138) 'a': u32 |
536 | [141; 148) 'S::make': fn make<S, u32>() -> T | 536 | [141; 148) 'S::make': fn make<S, u32>() -> u32 |
537 | [141; 150) 'S::make()': u32 | 537 | [141; 150) 'S::make()': u32 |
538 | [160; 161) 'b': u64 | 538 | [160; 161) 'b': u64 |
539 | [164; 178) 'G::<u64>::make': fn make<G<u64>, u64>() -> T | 539 | [164; 178) 'G::<u64>::make': fn make<G<u64>, u64>() -> u64 |
540 | [164; 180) 'G::<u6...make()': u64 | 540 | [164; 180) 'G::<u6...make()': u64 |
541 | [190; 191) 'c': f64 | 541 | [190; 191) 'c': f64 |
542 | [199; 206) 'G::make': fn make<G<f64>, f64>() -> T | 542 | [199; 206) 'G::make': fn make<G<f64>, f64>() -> f64 |
543 | [199; 208) 'G::make()': f64 | 543 | [199; 208) 'G::make()': f64 |
544 | "### | 544 | "### |
545 | ); | 545 | ); |
@@ -567,19 +567,19 @@ fn test() { | |||
567 | @r###" | 567 | @r###" |
568 | [135; 313) '{ ...e(); }': () | 568 | [135; 313) '{ ...e(); }': () |
569 | [145; 146) 'a': (u32, i64) | 569 | [145; 146) 'a': (u32, i64) |
570 | [149; 163) 'S::make::<i64>': fn make<S, u32, i64>() -> (T, U) | 570 | [149; 163) 'S::make::<i64>': fn make<S, u32, i64>() -> (u32, i64) |
571 | [149; 165) 'S::mak...i64>()': (u32, i64) | 571 | [149; 165) 'S::mak...i64>()': (u32, i64) |
572 | [175; 176) 'b': (u32, i64) | 572 | [175; 176) 'b': (u32, i64) |
573 | [189; 196) 'S::make': fn make<S, u32, i64>() -> (T, U) | 573 | [189; 196) 'S::make': fn make<S, u32, i64>() -> (u32, i64) |
574 | [189; 198) 'S::make()': (u32, i64) | 574 | [189; 198) 'S::make()': (u32, i64) |
575 | [208; 209) 'c': (u32, i64) | 575 | [208; 209) 'c': (u32, i64) |
576 | [212; 233) 'G::<u3...:<i64>': fn make<G<u32>, u32, i64>() -> (T, U) | 576 | [212; 233) 'G::<u3...:<i64>': fn make<G<u32>, u32, i64>() -> (u32, i64) |
577 | [212; 235) 'G::<u3...i64>()': (u32, i64) | 577 | [212; 235) 'G::<u3...i64>()': (u32, i64) |
578 | [245; 246) 'd': (u32, i64) | 578 | [245; 246) 'd': (u32, i64) |
579 | [259; 273) 'G::make::<i64>': fn make<G<u32>, u32, i64>() -> (T, U) | 579 | [259; 273) 'G::make::<i64>': fn make<G<u32>, u32, i64>() -> (u32, i64) |
580 | [259; 275) 'G::mak...i64>()': (u32, i64) | 580 | [259; 275) 'G::mak...i64>()': (u32, i64) |
581 | [285; 286) 'e': (u32, i64) | 581 | [285; 286) 'e': (u32, i64) |
582 | [301; 308) 'G::make': fn make<G<u32>, u32, i64>() -> (T, U) | 582 | [301; 308) 'G::make': fn make<G<u32>, u32, i64>() -> (u32, i64) |
583 | [301; 310) 'G::make()': (u32, i64) | 583 | [301; 310) 'G::make()': (u32, i64) |
584 | "### | 584 | "### |
585 | ); | 585 | ); |
@@ -601,7 +601,7 @@ fn test() { | |||
601 | @r###" | 601 | @r###" |
602 | [101; 127) '{ ...e(); }': () | 602 | [101; 127) '{ ...e(); }': () |
603 | [111; 112) 'a': (S<i32>, i64) | 603 | [111; 112) 'a': (S<i32>, i64) |
604 | [115; 122) 'S::make': fn make<S<i32>, i64>() -> (Self, T) | 604 | [115; 122) 'S::make': fn make<S<i32>, i64>() -> (S<i32>, i64) |
605 | [115; 124) 'S::make()': (S<i32>, i64) | 605 | [115; 124) 'S::make()': (S<i32>, i64) |
606 | "### | 606 | "### |
607 | ); | 607 | ); |
@@ -625,10 +625,10 @@ fn test() { | |||
625 | @r###" | 625 | @r###" |
626 | [131; 203) '{ ...e(); }': () | 626 | [131; 203) '{ ...e(); }': () |
627 | [141; 142) 'a': (S<u64>, i64) | 627 | [141; 142) 'a': (S<u64>, i64) |
628 | [158; 165) 'S::make': fn make<S<u64>, i64>() -> (Self, T) | 628 | [158; 165) 'S::make': fn make<S<u64>, i64>() -> (S<u64>, i64) |
629 | [158; 167) 'S::make()': (S<u64>, i64) | 629 | [158; 167) 'S::make()': (S<u64>, i64) |
630 | [177; 178) 'b': (S<u32>, i32) | 630 | [177; 178) 'b': (S<u32>, i32) |
631 | [191; 198) 'S::make': fn make<S<u32>, i32>() -> (Self, T) | 631 | [191; 198) 'S::make': fn make<S<u32>, i32>() -> (S<u32>, i32) |
632 | [191; 200) 'S::make()': (S<u32>, i32) | 632 | [191; 200) 'S::make()': (S<u32>, i32) |
633 | "### | 633 | "### |
634 | ); | 634 | ); |
@@ -651,10 +651,10 @@ fn test() { | |||
651 | @r###" | 651 | @r###" |
652 | [107; 211) '{ ...>(); }': () | 652 | [107; 211) '{ ...>(); }': () |
653 | [117; 118) 'a': (S<u64>, i64, u8) | 653 | [117; 118) 'a': (S<u64>, i64, u8) |
654 | [121; 150) '<S as ...::<u8>': fn make<S<u64>, i64, u8>() -> (Self, T, U) | 654 | [121; 150) '<S as ...::<u8>': fn make<S<u64>, i64, u8>() -> (S<u64>, i64, u8) |
655 | [121; 152) '<S as ...<u8>()': (S<u64>, i64, u8) | 655 | [121; 152) '<S as ...<u8>()': (S<u64>, i64, u8) |
656 | [162; 163) 'b': (S<u64>, i64, u8) | 656 | [162; 163) 'b': (S<u64>, i64, u8) |
657 | [182; 206) 'Trait:...::<u8>': fn make<S<u64>, i64, u8>() -> (Self, T, U) | 657 | [182; 206) 'Trait:...::<u8>': fn make<S<u64>, i64, u8>() -> (S<u64>, i64, u8) |
658 | [182; 208) 'Trait:...<u8>()': (S<u64>, i64, u8) | 658 | [182; 208) 'Trait:...<u8>()': (S<u64>, i64, u8) |
659 | "### | 659 | "### |
660 | ); | 660 | ); |
@@ -697,7 +697,7 @@ fn test<U, T: Trait<U>>(t: T) { | |||
697 | [71; 72) 't': T | 697 | [71; 72) 't': T |
698 | [77; 96) '{ ...d(); }': () | 698 | [77; 96) '{ ...d(); }': () |
699 | [83; 84) 't': T | 699 | [83; 84) 't': T |
700 | [83; 93) 't.method()': [missing name] | 700 | [83; 93) 't.method()': U |
701 | "### | 701 | "### |
702 | ); | 702 | ); |
703 | } | 703 | } |
@@ -728,7 +728,7 @@ fn test() { | |||
728 | [157; 158) 'S': S | 728 | [157; 158) 'S': S |
729 | [157; 165) 'S.into()': u64 | 729 | [157; 165) 'S.into()': u64 |
730 | [175; 176) 'z': u64 | 730 | [175; 176) 'z': u64 |
731 | [179; 196) 'Into::...::into': fn into<S, u64>(Self) -> T | 731 | [179; 196) 'Into::...::into': fn into<S, u64>(S) -> u64 |
732 | [179; 199) 'Into::...nto(S)': u64 | 732 | [179; 199) 'Into::...nto(S)': u64 |
733 | [197; 198) 'S': S | 733 | [197; 198) 'S': S |
734 | "### | 734 | "### |
diff --git a/crates/ra_hir_ty/src/tests/never_type.rs b/crates/ra_hir_ty/src/tests/never_type.rs index c202f545a..a77209480 100644 --- a/crates/ra_hir_ty/src/tests/never_type.rs +++ b/crates/ra_hir_ty/src/tests/never_type.rs | |||
@@ -101,6 +101,7 @@ fn test() { | |||
101 | ); | 101 | ); |
102 | assert_eq!(t, "Option<i32>"); | 102 | assert_eq!(t, "Option<i32>"); |
103 | } | 103 | } |
104 | |||
104 | #[test] | 105 | #[test] |
105 | fn never_type_can_be_reinferred3() { | 106 | fn never_type_can_be_reinferred3() { |
106 | let t = type_at( | 107 | let t = type_at( |
@@ -138,6 +139,22 @@ fn test(a: Void) { | |||
138 | } | 139 | } |
139 | 140 | ||
140 | #[test] | 141 | #[test] |
142 | fn match_unknown_arm() { | ||
143 | let t = type_at( | ||
144 | r#" | ||
145 | //- /main.rs | ||
146 | fn test(a: Option) { | ||
147 | let t = match 0 { | ||
148 | _ => unknown, | ||
149 | }; | ||
150 | t<|>; | ||