aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_assists/src/assist_ctx.rs109
-rw-r--r--crates/ra_assists/src/doc_tests.rs2
-rw-r--r--crates/ra_assists/src/doc_tests/generated.rs32
-rw-r--r--crates/ra_assists/src/handlers/add_new.rs14
-rw-r--r--crates/ra_assists/src/handlers/auto_import.rs99
-rw-r--r--crates/ra_assists/src/handlers/fill_match_arms.rs6
-rw-r--r--crates/ra_assists/src/handlers/merge_match_arms.rs8
-rw-r--r--crates/ra_assists/src/handlers/move_guard.rs6
-rw-r--r--crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs (renamed from crates/ra_assists/src/handlers/add_import.rs)114
-rw-r--r--crates/ra_assists/src/lib.rs70
-rw-r--r--crates/ra_hir/src/code_model.rs28
-rw-r--r--crates/ra_hir/src/lib.rs3
-rw-r--r--crates/ra_hir/src/source_analyzer.rs8
-rw-r--r--crates/ra_hir_def/src/body/lower.rs15
-rw-r--r--crates/ra_hir_def/src/body/scope.rs6
-rw-r--r--crates/ra_hir_def/src/expr.rs5
-rw-r--r--crates/ra_hir_def/src/generics.rs73
-rw-r--r--crates/ra_hir_def/src/resolver.rs10
-rw-r--r--crates/ra_hir_def/src/type_ref.rs42
-rw-r--r--crates/ra_hir_expand/src/name.rs7
-rw-r--r--crates/ra_hir_ty/src/db.rs34
-rw-r--r--crates/ra_hir_ty/src/infer.rs66
-rw-r--r--crates/ra_hir_ty/src/infer/coerce.rs18
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs34
-rw-r--r--crates/ra_hir_ty/src/infer/pat.rs19
-rw-r--r--crates/ra_hir_ty/src/infer/path.rs60
-rw-r--r--crates/ra_hir_ty/src/lib.rs262
-rw-r--r--crates/ra_hir_ty/src/lower.rs577
-rw-r--r--crates/ra_hir_ty/src/marks.rs1
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs6
-rw-r--r--crates/ra_hir_ty/src/tests/coercion.rs26
-rw-r--r--crates/ra_hir_ty/src/tests/method_resolution.rs48
-rw-r--r--crates/ra_hir_ty/src/tests/never_type.rs17
-rw-r--r--crates/ra_hir_ty/src/tests/patterns.rs4
-rw-r--r--crates/ra_hir_ty/src/tests/regression.rs2
-rw-r--r--crates/ra_hir_ty/src/tests/simple.rs42
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs312
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs33
-rw-r--r--crates/ra_hir_ty/src/utils.rs91
-rw-r--r--crates/ra_ide/src/assists.rs24
-rw-r--r--crates/ra_ide/src/completion/complete_scope.rs136
-rw-r--r--crates/ra_ide/src/inlay_hints.rs5
-rw-r--r--crates/ra_ide/src/join_lines.rs85
-rw-r--r--crates/ra_ide/src/references.rs74
-rw-r--r--crates/ra_ide/src/references/rename.rs19
-rw-r--r--crates/ra_lsp_server/src/lib.rs8
-rw-r--r--crates/ra_lsp_server/src/main.rs17
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs79
-rw-r--r--crates/ra_parser/src/grammar/expressions/atom.rs4
-rw-r--r--crates/ra_parser/src/grammar/params.rs4
-rw-r--r--crates/ra_parser/src/grammar/patterns.rs67
-rw-r--r--crates/ra_parser/src/syntax_kind/generated.rs4
-rw-r--r--crates/ra_project_model/src/sysroot.rs3
-rw-r--r--crates/ra_syntax/Cargo.toml2
-rw-r--r--crates/ra_syntax/src/ast/generated.rs83
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0030_cond.txt86
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.txt38
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.rs3
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.txt62
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0156_or_pattern.rs8
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0156_or_pattern.txt112
-rw-r--r--crates/ra_text_edit/src/lib.rs4
-rw-r--r--crates/ra_text_edit/src/text_edit.rs6
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.
2use either::Either;
3use hir::{InFile, SourceAnalyzer, SourceBinder}; 2use hir::{InFile, SourceAnalyzer, SourceBinder};
4use ra_db::{FileRange, SourceDatabase}; 3use ra_db::{FileRange, SourceDatabase};
5use ra_fmt::{leading_indent, reindent}; 4use ra_fmt::{leading_indent, reindent};
@@ -11,12 +10,36 @@ use ra_syntax::{
11}; 10};
12use ra_text_edit::TextEditBuilder; 11use ra_text_edit::TextEditBuilder;
13 12
14use crate::{AssistAction, AssistId, AssistLabel, ResolvedAssist}; 13use crate::{AssistAction, AssistId, AssistLabel, GroupLabel, ResolvedAssist};
15 14
16#[derive(Clone, Debug)] 15#[derive(Clone, Debug)]
17pub(crate) enum Assist { 16pub(crate) struct Assist(pub(crate) Vec<AssistInfo>);
18 Unresolved { label: AssistLabel }, 17
19 Resolved { assist: ResolvedAssist }, 18#[derive(Clone, Debug)]
19pub(crate) struct AssistInfo {
20 pub(crate) label: AssistLabel,
21 pub(crate) group_label: Option<GroupLabel>,
22 pub(crate) action: Option<AssistAction>,
23}
24
25impl 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
22pub(crate) type AssistHandler = fn(AssistCtx) -> Option<Assist>; 45pub(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
158pub(crate) struct AssistGroup<'a> {
159 ctx: AssistCtx<'a>,
160 group_name: String,
161 assists: Vec<AssistInfo>,
162}
163
164impl<'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)]
159pub(crate) struct ActionBuilder { 193pub(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
166impl ActionBuilder { 199impl 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
3use super::check; 3use super::check;
4 4
@@ -161,21 +161,6 @@ impl Trait<u32> for () {
161} 161}
162 162
163#[test] 163#[test]
164fn doctest_add_import() {
165 check(
166 "add_import",
167 r#####"
168fn process(map: std::collections::<|>HashMap<String, String>) {}
169"#####,
170 r#####"
171use std::collections::HashMap;
172
173fn process(map: HashMap<String, String>) {}
174"#####,
175 )
176}
177
178#[test]
179fn doctest_add_new() { 164fn 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]
580fn doctest_replace_qualified_name_with_use() {
581 check(
582 "replace_qualified_name_with_use",
583 r#####"
584fn process(map: std::collections::<|>HashMap<String, String>) {}
585"#####,
586 r#####"
587use std::collections::HashMap;
588
589fn process(map: HashMap<String, String>) {}
590"#####,
591 )
592}
593
594#[test]
595fn doctest_split_import() { 595fn 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 @@
1use format_buf::format; 1use format_buf::format;
2use hir::InFile; 2use hir::{Adt, InFile};
3use join_to_string::join; 3use join_to_string::join;
4use ra_syntax::{ 4use 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 @@
1use hir::ModPath;
2use ra_ide_db::imports_locator::ImportsLocator; 1use ra_ide_db::imports_locator::ImportsLocator;
3use ra_syntax::{ 2use ra_syntax::ast::{self, AstNode};
4 ast::{self, AstNode},
5 SyntaxNode,
6};
7 3
8use crate::{ 4use 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};
12use std::collections::BTreeSet; 8use 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// ```
33pub(crate) fn auto_import(ctx: AssistCtx) -> Option<Assist> { 29pub(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,
78fn 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)]
86mod tests { 85mod 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
77fn is_trivial(arm: &ast::MatchArm) -> bool { 77fn 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
84fn resolve_enum_def( 84fn 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
98fn contains_placeholder(a: &ast::MatchArm) -> bool { 98fn 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
105fn next_arm(arm: &ast::MatchArm) -> Option<ast::MatchArm> { 105fn 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// ```
91pub(crate) fn move_arm_cond_to_match_guard(ctx: AssistCtx) -> Option<Assist> { 91pub(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.
18pub fn auto_import_text_edit( 18pub 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// ```
53pub(crate) fn add_import(ctx: AssistCtx) -> Option<Assist> { 53pub(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
80fn collect_path_segments_raw( 84fn 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
110fn fmt_segments(segments: &[SmolStr]) -> String {
111 let mut buf = String::new();
112 fmt_segments_raw(segments, &mut buf);
113 buf
114}
115
116fn fmt_segments_raw(segments: &[SmolStr], buf: &mut String) { 114fn 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
561fn apply_auto_import( 559fn 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 "
610std::fmt::Debug<|> 608std::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 "
624std::fmt::Debug<|> 622std::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 "
645fn main() { 643fn 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 "
666std::fmt<|>::Debug 664std::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 "
681use stdx; 679use 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 "
701impl std::fmt::Debug<|> for Foo { 699impl 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 "
735use std::fmt; 733use 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 "
754use std::fmt; 752use 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 "
773use std::fmt::Debug; 771use 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 "
792use std::fmt::{Debug, nested::{Display}}; 790use 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 "
811use std::fmt::{Debug, nested::{self, Display}}; 809use 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 "
830use std::fmt::{Debug, nested::{Display}}; 828use 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 "
849use std::fmt::Debug; 847use 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 "
868use std::fmt::nested::Debug; 866use 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 "
887use crate::{ 885use 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 "
910use std::fmt as foo; 908use 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 "
929impl foo<|> for Foo { 927impl 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 "
940use std::fmt<|>; 938use 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 "
950mod foo { 948mod 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;
12mod utils; 12mod utils;
13pub mod ast_transform; 13pub mod ast_transform;
14 14
15use std::cmp::Ordering;
16
17use either::Either;
18use ra_db::FileRange; 15use ra_db::FileRange;
19use ra_ide_db::RootDatabase; 16use ra_ide_db::RootDatabase;
20use ra_syntax::{TextRange, TextUnit}; 17use ra_syntax::{TextRange, TextUnit};
21use ra_text_edit::TextEdit; 18use ra_text_edit::TextEdit;
22 19
23pub(crate) use crate::assist_ctx::{Assist, AssistCtx, AssistHandler}; 20pub(crate) use crate::assist_ctx::{Assist, AssistCtx, AssistHandler};
24pub use crate::handlers::add_import::auto_import_text_edit; 21pub 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)]
36pub struct GroupLabel(pub String);
37
38impl AssistLabel { 38impl 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)]
47pub struct AssistAction { 47pub 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)]
56pub struct ResolvedAssist { 55pub 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
61impl 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
104fn 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
113mod handlers { 91mod 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};
17use hir_expand::{ 17use hir_expand::{
18 diagnostics::DiagnosticSink, 18 diagnostics::DiagnosticSink,
@@ -21,7 +21,7 @@ use hir_expand::{
21}; 21};
22use hir_ty::{ 22use 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};
26use ra_db::{CrateId, Edition, FileId}; 26use ra_db::{CrateId, Edition, FileId};
27use ra_prof::profile; 27use 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 {
755impl TypeParam { 761impl 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};
60pub use hir_expand::{ 60pub 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};
64pub use hir_ty::{display::HirDisplay, CallableDef}; 63pub 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)]
204pub struct MatchArm { 204pub 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)]
29pub struct TypeParamData { 29pub 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)]
36pub 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)]
47pub struct WherePredicate { 55pub 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)]
61pub enum WherePredicateTarget {
62 TypeRef(TypeRef),
63 /// For desugared where predicates that can directly refer to a type param.
64 TypeParam(LocalTypeParamId),
65}
66
52type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::TraitDef, ast::TypeParam>>; 67type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::TraitDef, ast::TypeParam>>;
53 68
54impl GenericParams { 69impl 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) = &param.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
129pub(crate) fn type_bounds_from_ast(type_bounds_opt: Option<ast::TypeBoundList>) -> Vec<TypeBound> { 171pub(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 @@
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::{ 5use hir_def::{
6 db::DefDatabase, DefWithBodyId, GenericDefId, ImplId, LocalStructFieldId, TraitId, VariantId, 6 db::DefDatabase, DefWithBodyId, GenericDefId, ImplId, LocalStructFieldId, TraitId, TypeParamId,
7 VariantId,
7}; 8};
8use ra_arena::map::ArenaMap; 9use ra_arena::map::ArenaMap;
9use ra_db::{salsa, CrateId}; 10use ra_db::{impl_intern_key, salsa, CrateId};
10use ra_prof::profile; 11use ra_prof::profile;
11 12
12use crate::{ 13use 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> {
117fn hir_database_is_object_safe() { 119fn 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)]
124pub struct GlobalTypeParamId(salsa::InternId);
125impl_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};
34use ra_arena::map::ArenaMap; 34use ra_arena::map::ArenaMap;
35use ra_prof::profile; 35use ra_prof::profile;
36use ra_syntax::SmolStr; 36use ra_syntax::SmolStr;
37use test_utils::tested_by;
38 37
39use super::{ 38use 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};
45use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic}; 44use crate::{
45 db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode,
46};
46 47
47pub(crate) use unify::unify; 48pub(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};
13use hir_expand::name::{name, Name}; 13use hir_expand::name::Name;
14use ra_syntax::ast::RangeOp; 14use ra_syntax::ast::RangeOp;
15 15
16use crate::{ 16use 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
26use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; 26use 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;
12use test_utils::tested_by; 12use test_utils::tested_by;
13 13
14use super::{BindingMode, InferenceContext}; 14use super::{BindingMode, InferenceContext};
15use crate::{db::HirDatabase, utils::variant_data, Substs, Ty, TypeCtor, TypeWalk}; 15use crate::{db::HirDatabase, utils::variant_data, Substs, Ty, TypeCtor};
16 16
17impl<'a, D: HirDatabase> InferenceContext<'a, D> { 17impl<'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};
10use hir_expand::name::Name; 10use hir_expand::name::Name;
11 11
12use crate::{db::HirDatabase, method_resolution, Substs, Ty, TypeWalk, ValueTyDefId}; 12use crate::{db::HirDatabase, method_resolution, Substs, Ty, ValueTyDefId};
13 13
14use super::{ExprOrPatId, InferenceContext, TraitEnvironment, TraitRef}; 14use super::{ExprOrPatId, InferenceContext, TraitRef};
15 15
16impl<'a, D: HirDatabase> InferenceContext<'a, D> { 16impl<'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;
44use std::{fmt, iter, mem}; 44use std::{fmt, iter, mem};
45 45
46use hir_def::{ 46use 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};
50use hir_expand::name::Name; 50use hir_expand::name::Name;
51use ra_db::{impl_intern_key, salsa, CrateId}; 51use ra_db::{impl_intern_key, salsa, CrateId};
@@ -60,7 +60,9 @@ use display::{HirDisplay, HirFormatter};
60pub use autoderef::autoderef; 60pub use autoderef::autoderef;
61pub use infer::{do_infer_query, InferTy, InferenceResult}; 61pub use infer::{do_infer_query, InferTy, InferenceResult};
62pub use lower::CallableDef; 62pub use lower::CallableDef;
63pub use lower::{callable_item_sig, TyDefId, ValueTyDefId}; 63pub use lower::{
64 callable_item_sig, ImplTraitLoweringMode, TyDefId, TyLoweringContext, ValueTyDefId,
65};
64pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; 66pub 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(&params)
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)]
454pub struct Binders<T> {
455 pub num_binders: usize,
456 pub value: T,
457}
458
459impl<T> Binders<T> {
460 pub fn new(num_binders: usize, value: T) -> Self {
461 Self { num_binders, value }
462 }
463}
464
465impl<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.
580pub type PolyFnSig = Binders<FnSig>;
581
554impl FnSig { 582impl 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
1069fn 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
1088impl TraitRef { 1134impl 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
11use hir_def::{ 11use 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};
20use ra_arena::map::ArenaMap; 21use ra_arena::map::ArenaMap;
21use ra_db::CrateId; 22use 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)]
36pub 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
48impl<'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)]
66pub 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)]
86pub enum TypeParamLoweringMode {
87 Placeholder,
88 Variable,
89}
90
34impl Ty { 91impl 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
312pub(super) fn substs_from_path_segment( 423pub(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
366impl TraitRef { 474impl 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
432impl GenericPredicate { 535impl 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
458fn assoc_type_bindings_from_type_bound<'a>( 573fn 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).
488pub fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> FnSig { 602pub 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 {
497pub(crate) fn field_types_query( 611pub(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<()>`.
522pub(crate) fn generic_predicates_for_param_query( 639pub(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
536pub(crate) fn generic_predicates_for_param_recover( 663pub(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
545impl TraitEnvironment { 671impl 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 {
557pub(crate) fn generic_predicates_query( 685pub(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
569pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDefId) -> Substs { 703pub(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
581fn fn_sig_for_fn(db: &impl HirDatabase, def: FunctionId) -> FnSig { 716fn 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.
591fn type_for_fn(db: &impl HirDatabase, def: FunctionId) -> Ty { 732fn 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.
598fn type_for_const(db: &impl HirDatabase, def: ConstId) -> Ty { 739fn 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.
606fn type_for_static(db: &impl HirDatabase, def: StaticId) -> Ty { 750fn 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
624fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> FnSig { 769fn 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.
637fn type_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> Ty { 782fn 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
647fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> FnSig { 792fn 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.
663fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> Ty { 806fn 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
674fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Ty { 817fn 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
679fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Ty { 823fn 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.
739pub(crate) fn ty_query(db: &impl HirDatabase, def: TyDefId) -> Ty { 885pub(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
747pub(crate) fn ty_recover(_db: &impl HirDatabase, _cycle: &[String], _def: &TyDefId) -> Ty { 893pub(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
751pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty { 902pub(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
761pub(crate) fn impl_self_ty_query(db: &impl HirDatabase, impl_id: ImplId) -> Ty { 912pub(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
767pub(crate) fn impl_self_ty_recover( 921pub(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
775pub(crate) fn impl_trait_query(db: &impl HirDatabase, impl_id: ImplId) -> Option<TraitRef> { 930pub(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
502pub fn implements_trait( 502pub 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]
105fn never_type_can_be_reinferred3() { 106fn 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]
142fn match_unknown_arm() {
143 let t = type_at(
144 r#"
145//- /main.rs
146fn test(a: Option) {
147 let t = match 0 {
148 _ => unknown,
149 };
150 t<|>;
151}
152"#,
153 );
154 assert_eq!(t, "{unknown}");
155}
156
157#[test]
141fn if_never() { 158fn if_never() {
142 let t = type_at( 159 let t = type_at(
143 r#" 160 r#"
diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs
index cb3890b42..e25d6dbc4 100644
--- a/crates/ra_hir_ty/src/tests/patterns.rs
+++ b/crates/ra_hir_ty/src/tests/patterns.rs
@@ -96,13 +96,13 @@ fn test() {
96 [38; 42) 'A(n)': A<i32> 96 [38; 42) 'A(n)': A<i32>
97 [40; 41) 'n': &i32 97 [40; 41) 'n': &i32
98 [45; 50) '&A(1)': &A<i32> 98 [45; 50) '&A(1)': &A<i32>
99 [46; 47) 'A': A<i32>(T) -> A<T> 99 [46; 47) 'A': A<i32>(i32) -> A<i32>
100 [46; 50) 'A(1)': A<i32> 100 [46; 50) 'A(1)': A<i32>
101 [48; 49) '1': i32 101 [48; 49) '1': i32
102 [60; 64) 'A(n)': A<i32> 102 [60; 64) 'A(n)': A<i32>
103 [62; 63) 'n': &mut i32 103 [62; 63) 'n': &mut i32
104 [67; 76) '&mut A(1)': &mut A<i32> 104 [67; 76) '&mut A(1)': &mut A<i32>
105 [72; 73) 'A': A<i32>(T) -> A<T> 105 [72; 73) 'A': A<i32>(i32) -> A<i32>
106 [72; 76) 'A(1)': A<i32> 106 [72; 76) 'A(1)': A<i32>
107 [74; 75) '1': i32 107 [74; 75) '1': i32
108 "### 108 "###
diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs
index 02bab6dbe..14c8ed3a9 100644
--- a/crates/ra_hir_ty/src/tests/regression.rs
+++ b/crates/ra_hir_ty/src/tests/regression.rs
@@ -346,7 +346,7 @@ pub fn main_loop() {
346 @r###" 346 @r###"
347 [144; 146) '{}': () 347 [144; 146) '{}': ()
348 [169; 198) '{ ...t(); }': () 348 [169; 198) '{ ...t(); }': ()
349 [175; 193) 'FxHash...efault': fn default<{unknown}, FxHasher>() -> HashSet<T, H> 349 [175; 193) 'FxHash...efault': fn default<{unknown}, FxHasher>() -> HashSet<{unknown}, FxHasher>
350 [175; 195) 'FxHash...ault()': HashSet<{unknown}, FxHasher> 350 [175; 195) 'FxHash...ault()': HashSet<{unknown}, FxHasher>
351 "### 351 "###
352 ); 352 );
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs
index fdab9c187..3803f5938 100644
--- a/crates/ra_hir_ty/src/tests/simple.rs
+++ b/crates/ra_hir_ty/src/tests/simple.rs
@@ -754,15 +754,15 @@ fn test() {
754 [289; 295) 'self.0': T 754 [289; 295) 'self.0': T
755 [315; 353) '{ ...))); }': () 755 [315; 353) '{ ...))); }': ()
756 [325; 326) 't': &i32 756 [325; 326) 't': &i32
757 [329; 335) 'A::foo': fn foo<i32>(&A<T>) -> &T 757 [329; 335) 'A::foo': fn foo<i32>(&A<i32>) -> &i32
758 [329; 350) 'A::foo...42))))': &i32 758 [329; 350) 'A::foo...42))))': &i32
759 [336; 349) '&&B(B(A(42)))': &&B<B<A<i32>>> 759 [336; 349) '&&B(B(A(42)))': &&B<B<A<i32>>>
760 [337; 349) '&B(B(A(42)))': &B<B<A<i32>>> 760 [337; 349) '&B(B(A(42)))': &B<B<A<i32>>>
761 [338; 339) 'B': B<B<A<i32>>>(T) -> B<T> 761 [338; 339) 'B': B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>>
762 [338; 349) 'B(B(A(42)))': B<B<A<i32>>> 762 [338; 349) 'B(B(A(42)))': B<B<A<i32>>>
763 [340; 341) 'B': B<A<i32>>(T) -> B<T> 763 [340; 341) 'B': B<A<i32>>(A<i32>) -> B<A<i32>>
764 [340; 348) 'B(A(42))': B<A<i32>> 764 [340; 348) 'B(A(42))': B<A<i32>>
765 [342; 343) 'A': A<i32>(T) -> A<T> 765 [342; 343) 'A': A<i32>(i32) -> A<i32>
766 [342; 347) 'A(42)': A<i32> 766 [342; 347) 'A(42)': A<i32>
767 [344; 346) '42': i32 767 [344; 346) '42': i32
768 "### 768 "###
@@ -817,16 +817,16 @@ fn test(a: A<i32>) {
817 [326; 327) 'a': A<i32> 817 [326; 327) 'a': A<i32>
818 [337; 383) '{ ...))); }': () 818 [337; 383) '{ ...))); }': ()
819 [347; 348) 't': &i32 819 [347; 348) 't': &i32
820 [351; 352) 'A': A<i32>(*mut T) -> A<T> 820 [351; 352) 'A': A<i32>(*mut i32) -> A<i32>
821 [351; 365) 'A(0 as *mut _)': A<i32> 821 [351; 365) 'A(0 as *mut _)': A<i32>
822 [351; 380) 'A(0 as...B(a)))': &i32 822 [351; 380) 'A(0 as...B(a)))': &i32
823 [353; 354) '0': i32 823 [353; 354) '0': i32
824 [353; 364) '0 as *mut _': *mut i32 824 [353; 364) '0 as *mut _': *mut i32
825 [370; 379) '&&B(B(a))': &&B<B<A<i32>>> 825 [370; 379) '&&B(B(a))': &&B<B<A<i32>>>
826 [371; 379) '&B(B(a))': &B<B<A<i32>>> 826 [371; 379) '&B(B(a))': &B<B<A<i32>>>
827 [372; 373) 'B': B<B<A<i32>>>(T) -> B<T> 827 [372; 373) 'B': B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>>
828 [372; 379) 'B(B(a))': B<B<A<i32>>> 828 [372; 379) 'B(B(a))': B<B<A<i32>>>
829 [374; 375) 'B': B<A<i32>>(T) -> B<T> 829 [374; 375) 'B': B<A<i32>>(A<i32>) -> B<A<i32>>
830 [374; 378) 'B(a)': B<A<i32>> 830 [374; 378) 'B(a)': B<A<i32>>
831 [376; 377) 'a': A<i32> 831 [376; 377) 'a': A<i32>
832 "### 832 "###
@@ -1169,16 +1169,16 @@ fn test() {
1169"#), 1169"#),
1170 @r###" 1170 @r###"
1171 [76; 184) '{ ...one; }': () 1171 [76; 184) '{ ...one; }': ()
1172 [82; 83) 'A': A<i32>(T) -> A<T> 1172 [82; 83) 'A': A<i32>(i32) -> A<i32>
1173 [82; 87) 'A(42)': A<i32> 1173 [82; 87) 'A(42)': A<i32>
1174 [84; 86) '42': i32 1174 [84; 86) '42': i32
1175 [93; 94) 'A': A<u128>(T) -> A<T> 1175 [93; 94) 'A': A<u128>(u128) -> A<u128>
1176 [93; 102) 'A(42u128)': A<u128> 1176 [93; 102) 'A(42u128)': A<u128>
1177 [95; 101) '42u128': u128 1177 [95; 101) '42u128': u128
1178 [108; 112) 'Some': Some<&str>(T) -> Option<T> 1178 [108; 112) 'Some': Some<&str>(&str) -> Option<&str>
1179 [108; 117) 'Some("x")': Option<&str> 1179 [108; 117) 'Some("x")': Option<&str>
1180 [113; 116) '"x"': &str 1180 [113; 116) '"x"': &str
1181 [123; 135) 'Option::Some': Some<&str>(T) -> Option<T> 1181 [123; 135) 'Option::Some': Some<&str>(&str) -> Option<&str>
1182 [123; 140) 'Option...e("x")': Option<&str> 1182 [123; 140) 'Option...e("x")': Option<&str>
1183 [136; 139) '"x"': &str 1183 [136; 139) '"x"': &str
1184 [146; 150) 'None': Option<{unknown}> 1184 [146; 150) 'None': Option<{unknown}>
@@ -1205,14 +1205,14 @@ fn test() {
1205 [21; 26) '{ t }': T 1205 [21; 26) '{ t }': T
1206 [23; 24) 't': T 1206 [23; 24) 't': T
1207 [38; 98) '{ ...(1); }': () 1207 [38; 98) '{ ...(1); }': ()
1208 [44; 46) 'id': fn id<u32>(T) -> T 1208 [44; 46) 'id': fn id<u32>(u32) -> u32
1209 [44; 52) 'id(1u32)': u32 1209 [44; 52) 'id(1u32)': u32
1210 [47; 51) '1u32': u32 1210 [47; 51) '1u32': u32
1211 [58; 68) 'id::<i128>': fn id<i128>(T) -> T 1211 [58; 68) 'id::<i128>': fn id<i128>(i128) -> i128
1212 [58; 71) 'id::<i128>(1)': i128 1212 [58; 71) 'id::<i128>(1)': i128
1213 [69; 70) '1': i128 1213 [69; 70) '1': i128
1214 [81; 82) 'x': u64 1214 [81; 82) 'x': u64
1215 [90; 92) 'id': fn id<u64>(T) -> T 1215 [90; 92) 'id': fn id<u64>(u64) -> u64
1216 [90; 95) 'id(1)': u64 1216 [90; 95) 'id(1)': u64
1217 [93; 94) '1': u64 1217 [93; 94) '1': u64
1218 "### 1218 "###
@@ -1220,7 +1220,7 @@ fn test() {
1220} 1220}
1221 1221
1222#[test] 1222#[test]
1223fn infer_impl_generics() { 1223fn infer_impl_generics_basic() {
1224 assert_snapshot!( 1224 assert_snapshot!(
1225 infer(r#" 1225 infer(r#"
1226struct A<T1, T2> { 1226struct A<T1, T2> {
@@ -1349,16 +1349,16 @@ fn test() -> i128 {
1349 [146; 147) 'x': i128 1349 [146; 147) 'x': i128
1350 [150; 151) '1': i128 1350 [150; 151) '1': i128
1351 [162; 163) 'y': i128 1351 [162; 163) 'y': i128
1352 [166; 168) 'id': fn id<i128>(T) -> T 1352 [166; 168) 'id': fn id<i128>(i128) -> i128
1353 [166; 171) 'id(x)': i128 1353 [166; 171) 'id(x)': i128
1354 [169; 170) 'x': i128 1354 [169; 170) 'x': i128
1355 [182; 183) 'a': A<i128> 1355 [182; 183) 'a': A<i128>
1356 [186; 200) 'A { x: id(y) }': A<i128> 1356 [186; 200) 'A { x: id(y) }': A<i128>
1357 [193; 195) 'id': fn id<i128>(T) -> T 1357 [193; 195) 'id': fn id<i128>(i128) -> i128
1358 [193; 198) 'id(y)': i128 1358 [193; 198) 'id(y)': i128
1359 [196; 197) 'y': i128 1359 [196; 197) 'y': i128
1360 [211; 212) 'z': i128 1360 [211; 212) 'z': i128
1361 [215; 217) 'id': fn id<i128>(T) -> T 1361 [215; 217) 'id': fn id<i128>(i128) -> i128
1362 [215; 222) 'id(a.x)': i128 1362 [215; 222) 'id(a.x)': i128
1363 [218; 219) 'a': A<i128> 1363 [218; 219) 'a': A<i128>
1364 [218; 221) 'a.x': i128 1364 [218; 221) 'a.x': i128
@@ -1502,14 +1502,14 @@ fn test() {
1502 [78; 158) '{ ...(1); }': () 1502 [78; 158) '{ ...(1); }': ()
1503 [88; 89) 'y': u32 1503 [88; 89) 'y': u32
1504 [92; 97) '10u32': u32 1504 [92; 97) '10u32': u32
1505 [103; 105) 'id': fn id<u32>(T) -> T 1505 [103; 105) 'id': fn id<u32>(u32) -> u32
1506 [103; 108) 'id(y)': u32 1506 [103; 108) 'id(y)': u32
1507 [106; 107) 'y': u32 1507 [106; 107) 'y': u32
1508 [118; 119) 'x': bool 1508 [118; 119) 'x': bool
1509 [128; 133) 'clone': fn clone<bool>(&T) -> T 1509 [128; 133) 'clone': fn clone<bool>(&bool) -> bool
1510 [128; 136) 'clone(z)': bool 1510 [128; 136) 'clone(z)': bool
1511 [134; 135) 'z': &bool 1511 [134; 135) 'z': &bool
1512 [142; 152) 'id::<i128>': fn id<i128>(T) -> T 1512 [142; 152) 'id::<i128>': fn id<i128>(i128) -> i128
1513 [142; 155) 'id::<i128>(1)': i128 1513 [142; 155) 'id::<i128>(1)': i128
1514 [153; 154) '1': i128 1514 [153; 154) '1': i128
1515 "### 1515 "###
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index a6ac18f86..17611ddbf 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -1,7 +1,6 @@
1use insta::assert_snapshot; 1use insta::assert_snapshot;
2 2
3use ra_db::fixture::WithFixture; 3use ra_db::fixture::WithFixture;
4use test_utils::covers;
5 4
6use super::{infer, infer_with_mismatches, type_at, type_at_pos}; 5use super::{infer, infer_with_mismatches, type_at, type_at_pos};
7use crate::test_db::TestDB; 6use crate::test_db::TestDB;
@@ -261,10 +260,10 @@ fn test() {
261 [92; 94) '{}': () 260 [92; 94) '{}': ()
262 [105; 144) '{ ...(s); }': () 261 [105; 144) '{ ...(s); }': ()
263 [115; 116) 's': S<u32> 262 [115; 116) 's': S<u32>
264 [119; 120) 'S': S<u32>(T) -> S<T> 263 [119; 120) 'S': S<u32>(u32) -> S<u32>
265 [119; 129) 'S(unknown)': S<u32> 264 [119; 129) 'S(unknown)': S<u32>
266 [121; 128) 'unknown': u32 265 [121; 128) 'unknown': u32
267 [135; 138) 'foo': fn foo<S<u32>>(T) -> () 266 [135; 138) 'foo': fn foo<S<u32>>(S<u32>) -> ()
268 [135; 141) 'foo(s)': () 267 [135; 141) 'foo(s)': ()
269 [139; 140) 's': S<u32> 268 [139; 140) 's': S<u32>
270 "### 269 "###
@@ -289,11 +288,11 @@ fn test() {
289 [98; 100) '{}': () 288 [98; 100) '{}': ()
290 [111; 163) '{ ...(s); }': () 289 [111; 163) '{ ...(s); }': ()
291 [121; 122) 's': S<u32> 290 [121; 122) 's': S<u32>
292 [125; 126) 'S': S<u32>(T) -> S<T> 291 [125; 126) 'S': S<u32>(u32) -> S<u32>
293 [125; 135) 'S(unknown)': S<u32> 292 [125; 135) 'S(unknown)': S<u32>
294 [127; 134) 'unknown': u32 293 [127; 134) 'unknown': u32
295 [145; 146) 'x': u32 294 [145; 146) 'x': u32
296 [154; 157) 'foo': fn foo<u32, S<u32>>(T) -> U 295 [154; 157) 'foo': fn foo<u32, S<u32>>(S<u32>) -> u32
297 [154; 160) 'foo(s)': u32 296 [154; 160) 'foo(s)': u32
298 [158; 159) 's': S<u32> 297 [158; 159) 's': S<u32>
299 "### 298 "###
@@ -358,15 +357,15 @@ fn test() {
358 [221; 223) '{}': () 357 [221; 223) '{}': ()
359 [234; 300) '{ ...(S); }': () 358 [234; 300) '{ ...(S); }': ()
360 [244; 245) 'x': u32 359 [244; 245) 'x': u32
361 [248; 252) 'foo1': fn foo1<S>(T) -> <T as Iterable>::Item 360 [248; 252) 'foo1': fn foo1<S>(S) -> <S as Iterable>::Item
362 [248; 255) 'foo1(S)': u32 361 [248; 255) 'foo1(S)': u32
363 [253; 254) 'S': S 362 [253; 254) 'S': S
364 [265; 266) 'y': u32 363 [265; 266) 'y': u32
365 [269; 273) 'foo2': fn foo2<S>(T) -> <T as Iterable>::Item 364 [269; 273) 'foo2': fn foo2<S>(S) -> <S as Iterable>::Item
366 [269; 276) 'foo2(S)': u32 365 [269; 276) 'foo2(S)': u32
367 [274; 275) 'S': S 366 [274; 275) 'S': S
368 [286; 287) 'z': u32 367 [286; 287) 'z': u32
369 [290; 294) 'foo3': fn foo3<S>(T) -> <T as Iterable>::Item 368 [290; 294) 'foo3': fn foo3<S>(S) -> <S as Iterable>::Item
370 [290; 297) 'foo3(S)': u32 369 [290; 297) 'foo3(S)': u32
371 [295; 296) 'S': S 370 [295; 296) 'S': S
372 "### 371 "###
@@ -822,8 +821,7 @@ fn test<T: ApplyL>() {
822"#, 821"#,
823 ); 822 );
824 // inside the generic function, the associated type gets normalized to a placeholder `ApplL::Out<T>` [https://rust-lang.github.io/rustc-guide/traits/associated-types.html#placeholder-associated-types]. 823 // inside the generic function, the associated type gets normalized to a placeholder `ApplL::Out<T>` [https://rust-lang.github.io/rustc-guide/traits/associated-types.html#placeholder-associated-types].
825 // FIXME: fix type parameter names going missing when going through Chalk 824 assert_eq!(t, "ApplyL::Out<T>");
826 assert_eq!(t, "ApplyL::Out<[missing name]>");
827} 825}
828 826
829#[test] 827#[test]
@@ -850,6 +848,197 @@ fn test<T: ApplyL>(t: T) {
850} 848}
851 849
852#[test] 850#[test]
851fn argument_impl_trait() {
852 assert_snapshot!(
853 infer_with_mismatches(r#"
854trait Trait<T> {
855 fn foo(&self) -> T;
856 fn foo2(&self) -> i64;
857}
858fn bar(x: impl Trait<u16>) {}
859struct S<T>(T);
860impl<T> Trait<T> for S<T> {}
861
862fn test(x: impl Trait<u64>, y: &impl Trait<u32>) {
863 x;
864 y;
865 let z = S(1);
866 bar(z);
867 x.foo();
868 y.foo();
869 z.foo();
870 x.foo2();
871 y.foo2();
872 z.foo2();
873}
874"#, true),
875 @r###"
876 [30; 34) 'self': &Self
877 [55; 59) 'self': &Self
878 [78; 79) 'x': impl Trait<u16>
879 [98; 100) '{}': ()
880 [155; 156) 'x': impl Trait<u64>
881 [175; 176) 'y': &impl Trait<u32>
882 [196; 324) '{ ...2(); }': ()
883 [202; 203) 'x': impl Trait<u64>
884 [209; 210) 'y': &impl Trait<u32>
885 [220; 221) 'z': S<u16>
886 [224; 225) 'S': S<u16>(u16) -> S<u16>
887 [224; 228) 'S(1)': S<u16>
888 [226; 227) '1': u16
889 [234; 237) 'bar': fn bar(S<u16>) -> ()
890 [234; 240) 'bar(z)': ()
891 [238; 239) 'z': S<u16>
892 [246; 247) 'x': impl Trait<u64>
893 [246; 253) 'x.foo()': u64
894 [259; 260) 'y': &impl Trait<u32>
895 [259; 266) 'y.foo()': u32
896 [272; 273) 'z': S<u16>
897 [272; 279) 'z.foo()': u16
898 [285; 286) 'x': impl Trait<u64>
899 [285; 293) 'x.foo2()': i64
900 [299; 300) 'y': &impl Trait<u32>
901 [299; 307) 'y.foo2()': i64
902 [313; 314) 'z': S<u16>
903 [313; 321) 'z.foo2()': i64
904 "###
905 );
906}
907
908#[test]
909fn argument_impl_trait_type_args_1() {
910 assert_snapshot!(
911 infer_with_mismatches(r#"
912trait Trait {}
913trait Foo {
914 // this function has an implicit Self param, an explicit type param,
915 // and an implicit impl Trait param!
916 fn bar<T>(x: impl Trait) -> T { loop {} }
917}
918fn foo<T>(x: impl Trait) -> T { loop {} }
919struct S;
920impl Trait for S {}
921struct F;
922impl Foo for F {}
923
924fn test() {
925 Foo::bar(S);
926 <F as Foo>::bar(S);
927 F::bar(S);
928 Foo::bar::<u32>(S);
929 <F as Foo>::bar::<u32>(S);
930
931 foo(S);
932 foo::<u32>(S);
933 foo::<u32, i32>(S); // we should ignore the extraneous i32
934}
935"#, true),
936 @r###"
937 [156; 157) 'x': impl Trait
938 [176; 187) '{ loop {} }': T
939 [178; 185) 'loop {}': !
940 [183; 185) '{}': ()
941 [200; 201) 'x': impl Trait
942 [220; 231) '{ loop {} }': T
943 [222; 229) 'loop {}': !
944 [227; 229) '{}': ()
945 [301; 510) '{ ... i32 }': ()
946 [307; 315) 'Foo::bar': fn bar<{unknown}, {unknown}>(S) -> {unknown}
947 [307; 318) 'Foo::bar(S)': {unknown}
948 [316; 317) 'S': S
949 [324; 339) '<F as Foo>::bar': fn bar<F, {unknown}>(S) -> {unknown}
950 [324; 342) '<F as ...bar(S)': {unknown}
951 [340; 341) 'S': S
952 [348; 354) 'F::bar': fn bar<F, {unknown}>(S) -> {unknown}
953 [348; 357) 'F::bar(S)': {unknown}
954 [355; 356) 'S': S
955 [363; 378) 'Foo::bar::<u32>': fn bar<{unknown}, u32>(S) -> u32
956 [363; 381) 'Foo::b...32>(S)': u32
957 [379; 380) 'S': S
958 [387; 409) '<F as ...:<u32>': fn bar<F, u32>(S) -> u32
959 [387; 412) '<F as ...32>(S)': u32
960 [410; 411) 'S': S
961 [419; 422) 'foo': fn foo<{unknown}>(S) -> {unknown}
962 [419; 425) 'foo(S)': {unknown}
963 [423; 424) 'S': S
964 [431; 441) 'foo::<u32>': fn foo<u32>(S) -> u32
965 [431; 444) 'foo::<u32>(S)': u32
966 [442; 443) 'S': S
967 [450; 465) 'foo::<u32, i32>': fn foo<u32>(S) -> u32
968 [450; 468) 'foo::<...32>(S)': u32
969 [466; 467) 'S': S
970 "###
971 );
972}
973
974#[test]
975fn argument_impl_trait_type_args_2() {
976 assert_snapshot!(
977 infer_with_mismatches(r#"
978trait Trait {}
979struct S;
980impl Trait for S {}
981struct F<T>;
982impl<T> F<T> {
983 fn foo<U>(self, x: impl Trait) -> (T, U) { loop {} }
984}
985
986fn test() {
987 F.foo(S);
988 F::<u32>.foo(S);
989 F::<u32>.foo::<i32>(S);
990 F::<u32>.foo::<i32, u32>(S); // extraneous argument should be ignored
991}
992"#, true),
993 @r###"
994 [88; 92) 'self': F<T>
995 [94; 95) 'x': impl Trait
996 [119; 130) '{ loop {} }': (T, U)
997 [121; 128) 'loop {}': !
998 [126; 128) '{}': ()
999 [144; 284) '{ ...ored }': ()
1000 [150; 151) 'F': F<{unknown}>
1001 [150; 158) 'F.foo(S)': ({unknown}, {unknown})
1002 [156; 157) 'S': S
1003 [164; 172) 'F::<u32>': F<u32>
1004 [164; 179) 'F::<u32>.foo(S)': (u32, {unknown})
1005 [177; 178) 'S': S
1006 [185; 193) 'F::<u32>': F<u32>
1007 [185; 207) 'F::<u3...32>(S)': (u32, i32)
1008 [205; 206) 'S': S
1009 [213; 221) 'F::<u32>': F<u32>
1010 [213; 240) 'F::<u3...32>(S)': (u32, i32)
1011 [238; 239) 'S': S
1012 "###
1013 );
1014}
1015
1016#[test]
1017fn argument_impl_trait_to_fn_pointer() {
1018 assert_snapshot!(
1019 infer_with_mismatches(r#"
1020trait Trait {}
1021fn foo(x: impl Trait) { loop {} }
1022struct S;
1023impl Trait for S {}
1024
1025fn test() {
1026 let f: fn(S) -> () = foo;
1027}
1028"#, true),
1029 @r###"
1030 [23; 24) 'x': impl Trait
1031 [38; 49) '{ loop {} }': ()
1032 [40; 47) 'loop {}': !
1033 [45; 47) '{}': ()
1034 [91; 124) '{ ...foo; }': ()
1035 [101; 102) 'f': fn(S) -> ()
1036 [118; 121) 'foo': fn foo(S) -> ()
1037 "###
1038 );
1039}
1040
1041#[test]
853#[ignore] 1042#[ignore]
854fn impl_trait() { 1043fn impl_trait() {
855 assert_snapshot!( 1044 assert_snapshot!(
@@ -994,29 +1183,17 @@ fn weird_bounds() {
994 assert_snapshot!( 1183 assert_snapshot!(
995 infer(r#" 1184 infer(r#"
996trait Trait {} 1185trait Trait {}
997fn test() { 1186fn test(a: impl Trait + 'lifetime, b: impl 'lifetime, c: impl (Trait), d: impl ('lifetime), e: impl ?Sized, f: impl Trait + ?Sized) {
998 let a: impl Trait + 'lifetime = foo;
999 let b: impl 'lifetime = foo;
1000 let b: impl (Trait) = foo;
1001 let b: impl ('lifetime) = foo;
1002 let d: impl ?Sized = foo;
1003 let e: impl Trait + ?Sized = foo;
1004} 1187}
1005"#), 1188"#),
1006 @r###" 1189 @r###"
1007 [26; 237) '{ ...foo; }': () 1190 [24; 25) 'a': impl Trait + {error}
1008 [36; 37) 'a': impl Trait + {error} 1191 [51; 52) 'b': impl {error}
1009 [64; 67) 'foo': impl Trait + {error} 1192 [70; 71) 'c': impl Trait
1010 [77; 78) 'b': impl {error} 1193 [87; 88) 'd': impl {error}
1011 [97; 100) 'foo': impl {error} 1194 [108; 109) 'e': impl {error}
1012 [110; 111) 'b': impl Trait 1195 [124; 125) 'f': impl Trait + {error}
1013 [128; 131) 'foo': impl Trait 1196 [148; 151) '{ }': ()
1014 [141; 142) 'b': impl {error}
1015 [163; 166) 'foo': impl {error}
1016 [176; 177) 'd': impl {error}
1017 [193; 196) 'foo': impl {error}
1018 [206; 207) 'e': impl Trait + {error}
1019 [231; 234) 'foo': impl Trait + {error}
1020 "### 1197 "###
1021 ); 1198 );
1022} 1199}
@@ -1078,26 +1255,26 @@ fn test<T: Trait<Type = u32>>(x: T, y: impl Trait<Type = i64>) {
1078 [296; 299) 'get': fn get<T>(T) -> <T as Trait>::Type 1255 [296; 299) 'get': fn get<T>(T) -> <T as Trait>::Type
1079 [296; 302) 'get(x)': {unknown} 1256 [296; 302) 'get(x)': {unknown}
1080 [300; 301) 'x': T 1257 [300; 301) 'x': T
1081 [308; 312) 'get2': fn get2<{unknown}, T>(T) -> U 1258 [308; 312) 'get2': fn get2<{unknown}, T>(T) -> {unknown}
1082 [308; 315) 'get2(x)': {unknown} 1259 [308; 315) 'get2(x)': {unknown}
1083 [313; 314) 'x': T 1260 [313; 314) 'x': T
1084 [321; 324) 'get': fn get<impl Trait<Type = i64>>(T) -> <T as Trait>::Type 1261 [321; 324) 'get': fn get<impl Trait<Type = i64>>(impl Trait<Type = i64>) -> <impl Trait<Type = i64> as Trait>::Type
1085 [321; 327) 'get(y)': {unknown} 1262 [321; 327) 'get(y)': {unknown}
1086 [325; 326) 'y': impl Trait<Type = i64> 1263 [325; 326) 'y': impl Trait<Type = i64>
1087 [333; 337) 'get2': fn get2<{unknown}, impl Trait<Type = i64>>(T) -> U 1264 [333; 337) 'get2': fn get2<{unknown}, impl Trait<Type = i64>>(impl Trait<Type = i64>) -> {unknown}
1088 [333; 340) 'get2(y)': {unknown} 1265 [333; 340) 'get2(y)': {unknown}
1089 [338; 339) 'y': impl Trait<Type = i64> 1266 [338; 339) 'y': impl Trait<Type = i64>
1090 [346; 349) 'get': fn get<S<u64>>(T) -> <T as Trait>::Type 1267 [346; 349) 'get': fn get<S<u64>>(S<u64>) -> <S<u64> as Trait>::Type
1091 [346; 357) 'get(set(S))': u64 1268 [346; 357) 'get(set(S))': u64
1092 [350; 353) 'set': fn set<S<u64>>(T) -> T 1269 [350; 353) 'set': fn set<S<u64>>(S<u64>) -> S<u64>
1093 [350; 356) 'set(S)': S<u64> 1270 [350; 356) 'set(S)': S<u64>
1094 [354; 355) 'S': S<u64> 1271 [354; 355) 'S': S<u64>
1095 [363; 367) 'get2': fn get2<u64, S<u64>>(T) -> U 1272 [363; 367) 'get2': fn get2<u64, S<u64>>(S<u64>) -> u64
1096 [363; 375) 'get2(set(S))': u64 1273 [363; 375) 'get2(set(S))': u64
1097 [368; 371) 'set': fn set<S<u64>>(T) -> T 1274 [368; 371) 'set': fn set<S<u64>>(S<u64>) -> S<u64>
1098 [368; 374) 'set(S)': S<u64> 1275 [368; 374) 'set(S)': S<u64>
1099 [372; 373) 'S': S<u64> 1276 [372; 373) 'S': S<u64>
1100 [381; 385) 'get2': fn get2<str, S<str>>(T) -> U 1277 [381; 385) 'get2': fn get2<str, S<str>>(S<str>) -> str
1101 [381; 395) 'get2(S::<str>)': str 1278 [381; 395) 'get2(S::<str>)': str
1102 [386; 394) 'S::<str>': S<str> 1279 [386; 394) 'S::<str>': S<str>
1103 "### 1280 "###
@@ -1225,6 +1402,32 @@ fn test<T: Trait1, U: Trait2>(x: T, y: U) {
1225} 1402}
1226 1403
1227#[test] 1404#[test]
1405fn super_trait_impl_trait_method_resolution() {
1406 assert_snapshot!(
1407 infer(r#"
1408mod foo {
1409 trait SuperTrait {
1410 fn foo(&self) -> u32 {}
1411 }
1412}
1413trait Trait1: foo::SuperTrait {}
1414
1415fn test(x: &impl Trait1) {
1416 x.foo();
1417}
1418"#),
1419 @r###"
1420 [50; 54) 'self': &Self
1421 [63; 65) '{}': ()
1422 [116; 117) 'x': &impl Trait1
1423 [133; 149) '{ ...o(); }': ()
1424 [139; 140) 'x': &impl Trait1
1425 [139; 146) 'x.foo()': u32
1426 "###
1427 );
1428}
1429
1430#[test]
1228fn super_trait_cycle() { 1431fn super_trait_cycle() {
1229 // This just needs to not crash 1432 // This just needs to not crash
1230 assert_snapshot!( 1433 assert_snapshot!(
@@ -1270,9 +1473,9 @@ fn test() {
1270 [157; 160) '{t}': T 1473 [157; 160) '{t}': T
1271 [158; 159) 't': T 1474 [158; 159) 't': T
1272 [259; 280) '{ ...S)); }': () 1475 [259; 280) '{ ...S)); }': ()
1273 [265; 269) 'get2': fn get2<u64, S<u64>>(T) -> U 1476 [265; 269) 'get2': fn get2<u64, S<u64>>(S<u64>) -> u64
1274 [265; 277) 'get2(set(S))': u64 1477 [265; 277) 'get2(set(S))': u64
1275 [270; 273) 'set': fn set<S<u64>>(T) -> T 1478 [270; 273) 'set': fn set<S<u64>>(S<u64>) -> S<u64>
1276 [270; 276) 'set(S)': S<u64> 1479 [270; 276) 'set(S)': S<u64>
1277 [274; 275) 'S': S<u64> 1480 [274; 275) 'S': S<u64>
1278 "### 1481 "###
@@ -1334,7 +1537,7 @@ fn test() {
1334 [173; 175) '{}': () 1537 [173; 175) '{}': ()
1335 [189; 308) '{ ... 1); }': () 1538 [189; 308) '{ ... 1); }': ()
1336 [199; 200) 'x': Option<u32> 1539 [199; 200) 'x': Option<u32>
1337 [203; 215) 'Option::Some': Some<u32>(T) -> Option<T> 1540 [203; 215) 'Option::Some': Some<u32>(u32) -> Option<u32>
1338 [203; 221) 'Option...(1u32)': Option<u32> 1541 [203; 221) 'Option...(1u32)': Option<u32>
1339 [216; 220) '1u32': u32 1542 [216; 220) '1u32': u32
1340 [227; 228) 'x': Option<u32> 1543 [227; 228) 'x': Option<u32>
@@ -1444,7 +1647,7 @@ fn test() {
1444 [340; 342) '{}': () 1647 [340; 342) '{}': ()
1445 [356; 515) '{ ... S); }': () 1648 [356; 515) '{ ... S); }': ()
1446 [366; 368) 'x1': u64 1649 [366; 368) 'x1': u64
1447 [371; 375) 'foo1': fn foo1<S, u64, |S| -> u64>(T, F) -> U 1650 [371; 375) 'foo1': fn foo1<S, u64, |S| -> u64>(S, |S| -> u64) -> u64
1448 [371; 394) 'foo1(S...hod())': u64 1651 [371; 394) 'foo1(S...hod())': u64
1449 [376; 377) 'S': S 1652 [376; 377) 'S': S
1450 [379; 393) '|s| s.method()': |S| -> u64 1653 [379; 393) '|s| s.method()': |S| -> u64
@@ -1452,7 +1655,7 @@ fn test() {
1452 [383; 384) 's': S 1655 [383; 384) 's': S
1453 [383; 393) 's.method()': u64 1656 [383; 393) 's.method()': u64
1454 [404; 406) 'x2': u64 1657 [404; 406) 'x2': u64
1455 [409; 413) 'foo2': fn foo2<S, u64, |S| -> u64>(F, T) -> U 1658 [409; 413) 'foo2': fn foo2<S, u64, |S| -> u64>(|S| -> u64, S) -> u64
1456 [409; 432) 'foo2(|...(), S)': u64 1659 [409; 432) 'foo2(|...(), S)': u64
1457 [414; 428) '|s| s.method()': |S| -> u64 1660 [414; 428) '|s| s.method()': |S| -> u64
1458 [415; 416) 's': S 1661 [415; 416) 's': S
@@ -1605,7 +1808,6 @@ fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> {
1605 1808
1606#[test] 1809#[test]
1607fn unify_impl_trait() { 1810fn unify_impl_trait() {
1608 covers!(insert_vars_for_impl_trait);
1609 assert_snapshot!( 1811 assert_snapshot!(
1610 infer_with_mismatches(r#" 1812 infer_with_mismatches(r#"
1611trait Trait<T> {} 1813trait Trait<T> {}
@@ -1637,26 +1839,26 @@ fn test() -> impl Trait<i32> {
1637 [172; 183) '{ loop {} }': T 1839 [172; 183) '{ loop {} }': T
1638 [174; 181) 'loop {}': ! 1840 [174; 181) 'loop {}': !
1639 [179; 181) '{}': () 1841 [179; 181) '{}': ()
1640 [214; 310) '{ ...t()) }': S<i32> 1842 [214; 310) '{ ...t()) }': S<{unknown}>
1641 [224; 226) 's1': S<u32> 1843 [224; 226) 's1': S<u32>
1642 [229; 230) 'S': S<u32>(T) -> S<T> 1844 [229; 230) 'S': S<u32>(u32) -> S<u32>
1643 [229; 241) 'S(default())': S<u32> 1845 [229; 241) 'S(default())': S<u32>
1644 [231; 238) 'default': fn default<u32>() -> T 1846 [231; 238) 'default': fn default<u32>() -> u32
1645 [231; 240) 'default()': u32 1847 [231; 240) 'default()': u32
1646 [247; 250) 'foo': fn foo(impl Trait<u32>) -> () 1848 [247; 250) 'foo': fn foo(S<u32>) -> ()
1647 [247; 254) 'foo(s1)': () 1849 [247; 254) 'foo(s1)': ()
1648 [251; 253) 's1': S<u32> 1850 [251; 253) 's1': S<u32>
1649 [264; 265) 'x': i32 1851 [264; 265) 'x': i32
1650 [273; 276) 'bar': fn bar<i32>(impl Trait<T>) -> T 1852 [273; 276) 'bar': fn bar<i32>(S<i32>) -> i32
1651 [273; 290) 'bar(S(...lt()))': i32 1853 [273; 290) 'bar(S(...lt()))': i32
1652 [277; 278) 'S': S<i32>(T) -> S<T> 1854 [277; 278) 'S': S<i32>(i32) -> S<i32>
1653 [277; 289) 'S(default())': S<i32> 1855 [277; 289) 'S(default())': S<i32>
1654 [279; 286) 'default': fn default<i32>() -> T 1856 [279; 286) 'default': fn default<i32>() -> i32
1655 [279; 288) 'default()': i32 1857 [279; 288) 'default()': i32
1656 [296; 297) 'S': S<i32>(T) -> S<T> 1858 [296; 297) 'S': S<{unknown}>({unknown}) -> S<{unknown}>
1657 [296; 308) 'S(default())': S<i32> 1859 [296; 308) 'S(default())': S<{unknown}>
1658 [298; 305) 'default': fn default<i32>() -> T 1860 [298; 305) 'default': fn default<{unknown}>() -> {unknown}
1659 [298; 307) 'default()': i32 1861 [298; 307) 'default()': {unknown}
1660 "### 1862 "###
1661 ); 1863 );
1662} 1864}
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs
index fe9cb556c..4974c565b 100644
--- a/crates/ra_hir_ty/src/traits/chalk.rs
+++ b/crates/ra_hir_ty/src/traits/chalk.rs
@@ -14,7 +14,7 @@ use ra_db::{
14use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; 14use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation};
15use crate::{ 15use crate::{
16 db::HirDatabase, display::HirDisplay, utils::generics, ApplicationTy, GenericPredicate, 16 db::HirDatabase, display::HirDisplay, utils::generics, ApplicationTy, GenericPredicate,
17 ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, 17 ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
18}; 18};
19 19
20#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] 20#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
@@ -142,9 +142,13 @@ impl ToChalk for Ty {
142 let substitution = proj_ty.parameters.to_chalk(db); 142 let substitution = proj_ty.parameters.to_chalk(db);
143 chalk_ir::AliasTy { associated_ty_id, substitution }.cast().intern() 143 chalk_ir::AliasTy { associated_ty_id, substitution }.cast().intern()
144 } 144 }
145 Ty::Param { idx, .. } => { 145 Ty::Param(id) => {
146 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize } 146 let interned_id = db.intern_type_param_id(id);
147 .to_ty::<TypeFamily>() 147 PlaceholderIndex {
148 ui: UniverseIndex::ROOT,
149 idx: interned_id.as_intern_id().as_usize(),
150 }
151 .to_ty::<TypeFamily>()
148 } 152 }
149 Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(), 153 Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(),
150 Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), 154 Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"),
@@ -177,7 +181,10 @@ impl ToChalk for Ty {
177 }, 181 },
178 chalk_ir::TyData::Placeholder(idx) => { 182 chalk_ir::TyData::Placeholder(idx) => {
179 assert_eq!(idx.ui, UniverseIndex::ROOT); 183 assert_eq!(idx.ui, UniverseIndex::ROOT);
180 Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() } 184 let interned_id = crate::db::GlobalTypeParamId::from_intern_id(
185 crate::salsa::InternId::from(idx.idx),
186 );
187 Ty::Param(db.lookup_intern_type_param_id(interned_id))
181 } 188 }
182 chalk_ir::TyData::Alias(proj) => { 189 chalk_ir::TyData::Alias(proj) => {
183 let associated_ty = from_chalk(db, proj.associated_ty_id); 190 let associated_ty = from_chalk(db, proj.associated_ty_id);
@@ -520,7 +527,7 @@ fn convert_where_clauses(
520 let generic_predicates = db.generic_predicates(def); 527 let generic_predicates = db.generic_predicates(def);
521 let mut result = Vec::with_capacity(generic_predicates.len()); 528 let mut result = Vec::with_capacity(generic_predicates.len());
522 for pred in generic_predicates.iter() { 529 for pred in generic_predicates.iter() {
523 if pred.is_error() { 530 if pred.value.is_error() {
524 // skip errored predicates completely 531 // skip errored predicates completely
525 continue; 532 continue;
526 } 533 }
@@ -709,12 +716,12 @@ fn impl_block_datum(
709 let trait_ref = db 716 let trait_ref = db
710 .impl_trait(impl_id) 717 .impl_trait(impl_id)
711 // ImplIds for impls where the trait ref can't be resolved should never reach Chalk 718 // ImplIds for impls where the trait ref can't be resolved should never reach Chalk
712 .expect("invalid impl passed to Chalk"); 719 .expect("invalid impl passed to Chalk")
720 .value;
713 let impl_data = db.impl_data(impl_id); 721 let impl_data = db.impl_data(impl_id);
714 722
715 let generic_params = generics(db, impl_id.into()); 723 let generic_params = generics(db, impl_id.into());
716 let bound_vars = Substs::bound_vars(&generic_params); 724 let bound_vars = Substs::bound_vars(&generic_params);
717 let trait_ref = trait_ref.subst(&bound_vars);
718 let trait_ = trait_ref.trait_; 725 let trait_ = trait_ref.trait_;
719 let impl_type = if impl_id.lookup(db).container.module(db).krate == krate { 726 let impl_type = if impl_id.lookup(db).container.module(db).krate == krate {
720 chalk_rust_ir::ImplType::Local 727 chalk_rust_ir::ImplType::Local
@@ -789,20 +796,18 @@ fn type_alias_associated_ty_value(
789 _ => panic!("assoc ty value should be in impl"), 796 _ => panic!("assoc ty value should be in impl"),
790 }; 797 };
791 798
792 let trait_ref = db.impl_trait(impl_id).expect("assoc ty value should not exist"); // we don't return any assoc ty values if the impl'd trait can't be resolved 799 let trait_ref = db.impl_trait(impl_id).expect("assoc ty value should not exist").value; // we don't return any assoc ty values if the impl'd trait can't be resolved
793 800
794 let assoc_ty = db 801 let assoc_ty = db
795 .trait_data(trait_ref.trait_) 802 .trait_data(trait_ref.trait_)
796 .associated_type_by_name(&type_alias_data.name) 803 .associated_type_by_name(&type_alias_data.name)
797 .expect("assoc ty value should not exist"); // validated when building the impl data as well 804 .expect("assoc ty value should not exist"); // validated when building the impl data as well
798 let generic_params = generics(db, impl_id.into()); 805 let ty = db.ty(type_alias.into());
799 let bound_vars = Substs::bound_vars(&generic_params); 806 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.value.to_chalk(db) };
800 let ty = db.ty(type_alias.into()).subst(&bound_vars);
801 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) };
802 let value = chalk_rust_ir::AssociatedTyValue { 807 let value = chalk_rust_ir::AssociatedTyValue {
803 impl_id: Impl::ImplBlock(impl_id.into()).to_chalk(db), 808 impl_id: Impl::ImplBlock(impl_id.into()).to_chalk(db),
804 associated_ty_id: assoc_ty.to_chalk(db), 809 associated_ty_id: assoc_ty.to_chalk(db),
805 value: make_binders(value_bound, bound_vars.len()), 810 value: make_binders(value_bound, ty.num_binders),
806 }; 811 };
807 Arc::new(value) 812 Arc::new(value)
808} 813}
diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs
index 0b1806a84..508ae9046 100644
--- a/crates/ra_hir_ty/src/utils.rs
+++ b/crates/ra_hir_ty/src/utils.rs
@@ -2,10 +2,11 @@
2//! query, but can't be computed directly from `*Data` (ie, which need a `db`). 2//! query, but can't be computed directly from `*Data` (ie, which need a `db`).
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::generics::WherePredicateTarget;
5use hir_def::{ 6use hir_def::{
6 adt::VariantData, 7 adt::VariantData,
7 db::DefDatabase, 8 db::DefDatabase,
8 generics::{GenericParams, TypeParamData}, 9 generics::{GenericParams, TypeParamData, TypeParamProvenance},
9 path::Path, 10 path::Path,
10 resolver::{HasResolver, TypeNs}, 11 resolver::{HasResolver, TypeNs},
11 type_ref::TypeRef, 12 type_ref::TypeRef,
@@ -19,11 +20,18 @@ fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> {
19 // lifetime problems, but since there usually shouldn't be more than a 20 // lifetime problems, but since there usually shouldn't be more than a
20 // few direct traits this should be fine (we could even use some kind of 21 // few direct traits this should be fine (we could even use some kind of
21 // SmallVec if performance is a concern) 22 // SmallVec if performance is a concern)
22 db.generic_params(trait_.into()) 23 let generic_params = db.generic_params(trait_.into());
24 let trait_self = generic_params.find_trait_self_param();
25 generic_params
23 .where_predicates 26 .where_predicates
24 .iter() 27 .iter()
25 .filter_map(|pred| match &pred.type_ref { 28 .filter_map(|pred| match &pred.target {
26 TypeRef::Path(p) if p == &Path::from(name![Self]) => pred.bound.as_path(), 29 WherePredicateTarget::TypeRef(TypeRef::Path(p)) if p == &Path::from(name![Self]) => {
30 pred.bound.as_path()
31 }
32 WherePredicateTarget::TypeParam(local_id) if Some(*local_id) == trait_self => {
33 pred.bound.as_path()
34 }
27 _ => None, 35 _ => None,
28 }) 36 })
29 .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path.mod_path()) { 37 .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path.mod_path()) {
@@ -95,41 +103,77 @@ pub(crate) struct Generics {
95} 103}
96 104
97impl Generics { 105impl Generics {
98 pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = (u32, &'a TypeParamData)> + 'a { 106 pub(crate) fn iter<'a>(
107 &'a self,
108 ) -> impl Iterator<Item = (TypeParamId, &'a TypeParamData)> + 'a {
99 self.parent_generics 109 self.parent_generics
100 .as_ref() 110 .as_ref()
101 .into_iter() 111 .into_iter()
102 .flat_map(|it| it.params.types.iter()) 112 .flat_map(|it| {
103 .chain(self.params.types.iter()) 113 it.params
104 .enumerate() 114 .types
105 .map(|(i, (_local_id, p))| (i as u32, p)) 115 .iter()
116 .map(move |(local_id, p)| (TypeParamId { parent: it.def, local_id }, p))
117 })
118 .chain(
119 self.params
120 .types
121 .iter()
122 .map(move |(local_id, p)| (TypeParamId { parent: self.def, local_id }, p)),
123 )
106 } 124 }
107 125
108 pub(crate) fn iter_parent<'a>(&'a self) -> impl Iterator<Item = (u32, &'a TypeParamData)> + 'a { 126 pub(crate) fn iter_parent<'a>(
109 self.parent_generics 127 &'a self,
110 .as_ref() 128 ) -> impl Iterator<Item = (TypeParamId, &'a TypeParamData)> + 'a {
111 .into_iter() 129 self.parent_generics.as_ref().into_iter().flat_map(|it| {
112 .flat_map(|it| it.params.types.iter()) 130 it.params
113 .enumerate() 131 .types
114 .map(|(i, (_local_id, p))| (i as u32, p)) 132 .iter()
133 .map(move |(local_id, p)| (TypeParamId { parent: it.def, local_id }, p))
134 })
115 } 135 }
116 136
117 pub(crate) fn len(&self) -> usize { 137 pub(crate) fn len(&self) -> usize {
118 self.len_split().0 138 self.len_split().0
119 } 139 }
140
120 /// (total, parents, child) 141 /// (total, parents, child)
121 pub(crate) fn len_split(&self) -> (usize, usize, usize) { 142 pub(crate) fn len_split(&self) -> (usize, usize, usize) {
122 let parent = self.parent_generics.as_ref().map_or(0, |p| p.len()); 143 let parent = self.parent_generics.as_ref().map_or(0, |p| p.len());
123 let child = self.params.types.len(); 144 let child = self.params.types.len();
124 (parent + child, parent, child) 145 (parent + child, parent, child)
125 } 146 }
126 pub(crate) fn param_idx(&self, param: TypeParamId) -> u32 { 147
127 self.find_param(param).0 148 /// (parent total, self param, type param list, impl trait)
149 pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize) {
150 let parent = self.parent_generics.as_ref().map_or(0, |p| p.len());
151 let self_params = self
152 .params
153 .types
154 .iter()
155 .filter(|(_, p)| p.provenance == TypeParamProvenance::TraitSelf)
156 .count();
157 let list_params = self
158 .params
159 .types
160 .iter()
161 .filter(|(_, p)| p.provenance == TypeParamProvenance::TypeParamList)
162 .count();
163 let impl_trait_params = self
164 .params
165 .types
166 .iter()
167 .filter(|(_, p)| p.provenance == TypeParamProvenance::ArgumentImplTrait)
168 .count();
169 (parent, self_params, list_params, impl_trait_params)
128 } 170 }
129 pub(crate) fn param_name(&self, param: TypeParamId) -> Name { 171
130 self.find_param(param).1.name.clone() 172 pub(crate) fn param_idx(&self, param: TypeParamId) -> Option<u32> {
173 Some(self.find_param(param)?.0)
131 } 174 }
132 fn find_param(&self, param: TypeParamId) -> (u32, &TypeParamData) { 175
176 fn find_param(&self, param: TypeParamId) -> Option<(u32, &TypeParamData)> {
133 if param.parent == self.def { 177 if param.parent == self.def {
134 let (idx, (_local_id, data)) = self 178 let (idx, (_local_id, data)) = self
135 .params 179 .params
@@ -139,9 +183,10 @@ impl Generics {
139 .find(|(_, (idx, _))| *idx == param.local_id) 183 .find(|(_, (idx, _))| *idx == param.local_id)
140 .unwrap(); 184 .unwrap();
141 let (_total, parent_len, _child) = self.len_split(); 185 let (_total, parent_len, _child) = self.len_split();
142 return ((parent_len + idx) as u32, data); 186 Some(((parent_len + idx) as u32, data))
187 } else {
188 self.parent_generics.as_ref().and_then(|g| g.find_param(param))
143 } 189 }
144 self.parent_generics.as_ref().unwrap().find_param(param)
145 } 190 }
146} 191}
147 192
diff --git a/crates/ra_ide/src/assists.rs b/crates/ra_ide/src/assists.rs
index b60b1a60d..40d56a4f7 100644
--- a/crates/ra_ide/src/assists.rs
+++ b/crates/ra_ide/src/assists.rs
@@ -1,6 +1,5 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use either::Either;
4use ra_assists::{resolved_assists, AssistAction, AssistLabel}; 3use ra_assists::{resolved_assists, AssistAction, AssistLabel};
5use ra_db::{FilePosition, FileRange}; 4use ra_db::{FilePosition, FileRange};
6use ra_ide_db::RootDatabase; 5use ra_ide_db::RootDatabase;
@@ -13,7 +12,8 @@ pub use ra_assists::AssistId;
13pub struct Assist { 12pub struct Assist {
14 pub id: AssistId, 13 pub id: AssistId,
15 pub label: String, 14 pub label: String,
16 pub change_data: Either<SourceChange, Vec<SourceChange>>, 15 pub group_label: Option<String>,
16 pub source_change: SourceChange,
17} 17}
18 18
19pub(crate) fn assists(db: &RootDatabase, frange: FileRange) -> Vec<Assist> { 19pub(crate) fn assists(db: &RootDatabase, frange: FileRange) -> Vec<Assist> {
@@ -25,17 +25,8 @@ pub(crate) fn assists(db: &RootDatabase, frange: FileRange) -> Vec<Assist> {
25 Assist { 25 Assist {
26 id: assist_label.id, 26 id: assist_label.id,
27 label: assist_label.label.clone(), 27 label: assist_label.label.clone(),
28 change_data: match assist.action_data { 28 group_label: assist.group_label.map(|it| it.0),
29 Either::Left(action) => { 29 source_change: action_to_edit(assist.action, file_id, assist_label),
30 Either::Left(action_to_edit(action, file_id, assist_label))
31 }
32 Either::Right(actions) => Either::Right(
33 actions
34 .into_iter()
35 .map(|action| action_to_edit(action, file_id, assist_label))
36 .collect(),
37 ),
38 },
39 } 30 }
40 }) 31 })
41 .collect() 32 .collect()
@@ -47,9 +38,6 @@ fn action_to_edit(
47 assist_label: &AssistLabel, 38 assist_label: &AssistLabel,
48) -> SourceChange { 39) -> SourceChange {
49 let file_edit = SourceFileEdit { file_id, edit: action.edit }; 40 let file_edit = SourceFileEdit { file_id, edit: action.edit };
50 SourceChange::source_file_edit( 41 SourceChange::source_file_edit(assist_label.label.clone(), file_edit)
51 action.label.unwrap_or_else(|| assist_label.label.clone()), 42 .with_cursor_opt(action.cursor_position.map(|offset| FilePosition { offset, file_id }))
52 file_edit,
53 )
54 .with_cursor_opt(action.cursor_position.map(|offset| FilePosition { offset, file_id }))
55} 43}
diff --git a/crates/ra_ide/src/completion/complete_scope.rs b/crates/ra_ide/src/completion/complete_scope.rs
index 64b04ec2b..e2ee86dd1 100644
--- a/crates/ra_ide/src/completion/complete_scope.rs
+++ b/crates/ra_ide/src/completion/complete_scope.rs
@@ -1,12 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use ra_assists::auto_import_text_edit; 3use crate::completion::{CompletionContext, Completions};
4use ra_syntax::{ast, AstNode, SmolStr};
5use ra_text_edit::TextEditBuilder;
6use rustc_hash::FxHashMap;
7
8use crate::completion::{CompletionContext, CompletionItem, CompletionKind, Completions};
9use hir::{ModPath, PathKind};
10 4
11pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { 5pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
12 if !ctx.is_trivial_path { 6 if !ctx.is_trivial_path {
@@ -16,138 +10,14 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
16 ctx.analyzer.process_all_names(ctx.db, &mut |name, res| { 10 ctx.analyzer.process_all_names(ctx.db, &mut |name, res| {
17 acc.add_resolution(ctx, name.to_string(), &res) 11 acc.add_resolution(ctx, name.to_string(), &res)
18 }); 12 });
19
20 // auto-import
21 // We fetch ident from the original file, because we need to pre-filter auto-imports
22 if ast::NameRef::cast(ctx.token.parent()).is_some() {
23 let import_resolver = ImportResolver::new();
24 let import_names = import_resolver.all_names(ctx.token.text());
25 import_names.into_iter().for_each(|(name, path)| {
26 let edit = {
27 let mut builder = TextEditBuilder::default();
28 builder.replace(ctx.source_range(), name.to_string());
29 auto_import_text_edit(
30 &ctx.token.parent(),
31 &ctx.token.parent(),
32 &path,
33 &mut builder,
34 );
35 builder.finish()
36 };
37
38 // Hack: copied this check form conv.rs beacause auto import can produce edits
39 // that invalidate assert in conv_with.
40 if edit
41 .as_atoms()
42 .iter()
43 .filter(|atom| !ctx.source_range().is_subrange(&atom.delete))
44 .all(|atom| ctx.source_range().intersection(&atom.delete).is_none())
45 {
46 CompletionItem::new(
47 CompletionKind::Reference,
48 ctx.source_range(),
49 build_import_label(&name, &path),
50 )
51 .text_edit(edit)
52 .add_to(acc);
53 }
54 });
55 }
56}
57
58fn build_import_label(name: &str, path: &ModPath) -> String {
59 let mut buf = String::with_capacity(64);
60 buf.push_str(name);
61 buf.push_str(" (");
62 buf.push_str(&path.to_string());
63 buf.push_str(")");
64 buf
65}
66
67#[derive(Debug, Clone, Default)]
68pub(crate) struct ImportResolver {
69 // todo: use fst crate or something like that
70 dummy_names: Vec<(SmolStr, ModPath)>,
71}
72
73impl ImportResolver {
74 pub(crate) fn new() -> Self {
75 use hir::name;
76
77 let dummy_names = vec![
78 (
79 SmolStr::new("fmt"),
80 ModPath { kind: PathKind::Plain, segments: vec![name![std], name![fmt]] },
81 ),
82 (
83 SmolStr::new("io"),
84 ModPath { kind: PathKind::Plain, segments: vec![name![std], name![io]] },
85 ),
86 (
87 SmolStr::new("iter"),
88 ModPath { kind: PathKind::Plain, segments: vec![name![std], name![iter]] },
89 ),
90 (
91 SmolStr::new("hash"),
92 ModPath { kind: PathKind::Plain, segments: vec![name![std], name![hash]] },
93 ),
94 (
95 SmolStr::new("Debug"),
96 ModPath {
97 kind: PathKind::Plain,
98 segments: vec![name![std], name![fmt], name![Debug]],
99 },
100 ),
101 (
102 SmolStr::new("Display"),
103 ModPath {
104 kind: PathKind::Plain,
105 segments: vec![name![std], name![fmt], name![Display]],
106 },
107 ),
108 (
109 SmolStr::new("Hash"),
110 ModPath {
111 kind: PathKind::Plain,
112 segments: vec![name![std], name![hash], name![Hash]],
113 },
114 ),
115 (
116 SmolStr::new("Hasher"),
117 ModPath {
118 kind: PathKind::Plain,
119 segments: vec![name![std], name![hash], name![Hasher]],
120 },
121 ),
122 (
123 SmolStr::new("Iterator"),
124 ModPath {
125 kind: PathKind::Plain,
126 segments: vec![name![std], name![iter], name![Iterator]],
127 },
128 ),
129 ];
130
131 ImportResolver { dummy_names }
132 }
133
134 // Returns a map of importable items filtered by name.
135 // The map associates item name with its full path.
136 // todo: should return Resolutions
137 pub(crate) fn all_names(&self, name: &str) -> FxHashMap<SmolStr, ModPath> {
138 if name.len() > 1 {
139 self.dummy_names.iter().filter(|(n, _)| n.contains(name)).cloned().collect()
140 } else {
141 FxHashMap::default()
142 }
143 }
144} 13}
145 14
146#[cfg(test)] 15#[cfg(test)]
147mod tests { 16mod tests {
148 use crate::completion::{do_completion, CompletionItem, CompletionKind};
149 use insta::assert_debug_snapshot; 17 use insta::assert_debug_snapshot;
150 18
19 use crate::completion::{do_completion, CompletionItem, CompletionKind};
20
151 fn do_reference_completion(code: &str) -> Vec<CompletionItem> { 21 fn do_reference_completion(code: &str) -> Vec<CompletionItem> {
152 do_completion(code, CompletionKind::Reference) 22 do_completion(code, CompletionKind::Reference)
153 } 23 }
diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs
index 6b0d3d996..2ae97e65f 100644
--- a/crates/ra_ide/src/inlay_hints.rs
+++ b/crates/ra_ide/src/inlay_hints.rs
@@ -80,8 +80,7 @@ fn get_inlay_hints(
80 }, 80 },
81 ast::MatchArmList(it) => { 81 ast::MatchArmList(it) => {
82 it.arms() 82 it.arms()
83 .map(|match_arm| match_arm.pats()) 83 .filter_map(|match_arm| match_arm.pat())
84 .flatten()
85 .for_each(|root_pat| get_pat_type_hints(acc, db, &analyzer, root_pat, true, max_inlay_hint_length)); 84 .for_each(|root_pat| get_pat_type_hints(acc, db, &analyzer, root_pat, true, max_inlay_hint_length));
86 }, 85 },
87 ast::CallExpr(it) => { 86 ast::CallExpr(it) => {
@@ -202,6 +201,7 @@ fn get_leaf_pats(root_pat: ast::Pat) -> Vec<ast::Pat> {
202 Some(pat) => pats_to_process.push_back(pat), 201 Some(pat) => pats_to_process.push_back(pat),
203 _ => leaf_pats.push(maybe_leaf_pat), 202 _ => leaf_pats.push(maybe_leaf_pat),
204 }, 203 },
204 ast::Pat::OrPat(ref_pat) => pats_to_process.extend(ref_pat.pats()),
205 ast::Pat::TuplePat(tuple_pat) => pats_to_process.extend(tuple_pat.args()), 205 ast::Pat::TuplePat(tuple_pat) => pats_to_process.extend(tuple_pat.args()),
206 ast::Pat::RecordPat(record_pat) => { 206 ast::Pat::RecordPat(record_pat) => {
207 if let Some(pat_list) = record_pat.record_field_pat_list() { 207 if let Some(pat_list) = record_pat.record_field_pat_list() {
@@ -222,6 +222,7 @@ fn get_leaf_pats(root_pat: ast::Pat) -> Vec<ast::Pat> {
222 ast::Pat::TupleStructPat(tuple_struct_pat) => { 222 ast::Pat::TupleStructPat(tuple_struct_pat) => {
223 pats_to_process.extend(tuple_struct_pat.args()) 223 pats_to_process.extend(tuple_struct_pat.args())
224 } 224 }
225 ast::Pat::ParenPat(inner_pat) => pats_to_process.extend(inner_pat.pat()),
225 ast::Pat::RefPat(ref_pat) => pats_to_process.extend(ref_pat.pat()), 226 ast::Pat::RefPat(ref_pat) => pats_to_process.extend(ref_pat.pat()),
226 _ => (), 227 _ => (),
227 } 228 }
diff --git a/crates/ra_ide/src/join_lines.rs b/crates/ra_ide/src/join_lines.rs
index 7deeb3494..01fb32b3d 100644
--- a/crates/ra_ide/src/join_lines.rs
+++ b/crates/ra_ide/src/join_lines.rs
@@ -60,36 +60,15 @@ fn remove_newline(edit: &mut TextEditBuilder, token: &SyntaxToken, offset: TextU
60 return; 60 return;
61 } 61 }
62 62
63 // Special case that turns something like:
64 //
65 // ```
66 // my_function({<|>
67 // <some-expr>
68 // })
69 // ```
70 //
71 // into `my_function(<some-expr>)`
72 if join_single_expr_block(edit, token).is_some() {
73 return;
74 }
75 // ditto for
76 //
77 // ```
78 // use foo::{<|>
79 // bar
80 // };
81 // ```
82 if join_single_use_tree(edit, token).is_some() {
83 return;
84 }
85
86 // The node is between two other nodes 63 // The node is between two other nodes
87 let prev = token.prev_sibling_or_token().unwrap(); 64 let prev = token.prev_sibling_or_token().unwrap();
88 let next = token.next_sibling_or_token().unwrap(); 65 let next = token.next_sibling_or_token().unwrap();
89 if is_trailing_comma(prev.kind(), next.kind()) { 66 if is_trailing_comma(prev.kind(), next.kind()) {
90 // Removes: trailing comma, newline (incl. surrounding whitespace) 67 // Removes: trailing comma, newline (incl. surrounding whitespace)
91 edit.delete(TextRange::from_to(prev.text_range().start(), token.text_range().end())); 68 edit.delete(TextRange::from_to(prev.text_range().start(), token.text_range().end()));
92 } else if prev.kind() == T![,] && next.kind() == T!['}'] { 69 return;
70 }
71 if prev.kind() == T![,] && next.kind() == T!['}'] {
93 // Removes: comma, newline (incl. surrounding whitespace) 72 // Removes: comma, newline (incl. surrounding whitespace)
94 let space = if let Some(left) = prev.prev_sibling_or_token() { 73 let space = if let Some(left) = prev.prev_sibling_or_token() {
95 compute_ws(left.kind(), next.kind()) 74 compute_ws(left.kind(), next.kind())
@@ -100,7 +79,10 @@ fn remove_newline(edit: &mut TextEditBuilder, token: &SyntaxToken, offset: TextU
100 TextRange::from_to(prev.text_range().start(), token.text_range().end()), 79 TextRange::from_to(prev.text_range().start(), token.text_range().end()),
101 space.to_string(), 80 space.to_string(),
102 ); 81 );
103 } else if let (Some(_), Some(next)) = ( 82 return;
83 }
84
85 if let (Some(_), Some(next)) = (
104 prev.as_token().cloned().and_then(ast::Comment::cast), 86 prev.as_token().cloned().and_then(ast::Comment::cast),
105 next.as_token().cloned().and_then(ast::Comment::cast), 87 next.as_token().cloned().and_then(ast::Comment::cast),
106 ) { 88 ) {
@@ -109,10 +91,34 @@ fn remove_newline(edit: &mut TextEditBuilder, token: &SyntaxToken, offset: TextU
109 token.text_range().start(), 91 token.text_range().start(),
110 next.syntax().text_range().start() + TextUnit::of_str(next.prefix()), 92 next.syntax().text_range().start() + TextUnit::of_str(next.prefix()),
111 )); 93 ));
112 } else { 94 return;
113 // Remove newline but add a computed amount of whitespace characters 95 }
114 edit.replace(token.text_range(), compute_ws(prev.kind(), next.kind()).to_string()); 96
97 // Special case that turns something like:
98 //
99 // ```
100 // my_function({<|>
101 // <some-expr>
102 // })
103 // ```
104 //
105 // into `my_function(<some-expr>)`
106 if join_single_expr_block(edit, token).is_some() {
107 return;
115 } 108 }
109 // ditto for
110 //
111 // ```
112 // use foo::{<|>
113 // bar
114 // };
115 // ```
116 if join_single_use_tree(edit, token).is_some() {
117 return;
118 }
119
120 // Remove newline but add a computed amount of whitespace characters
121 edit.replace(token.text_range(), compute_ws(prev.kind(), next.kind()).to_string());
116} 122}
117 123
118fn has_comma_after(node: &SyntaxNode) -> bool { 124fn has_comma_after(node: &SyntaxNode) -> bool {
@@ -608,4 +614,27 @@ pub fn handle_find_matching_brace() {
608}", 614}",
609 ); 615 );
610 } 616 }
617
618 #[test]
619 fn test_join_lines_commented_block() {
620 check_join_lines(
621 r"
622fn main() {
623 let _ = {
624 // <|>foo
625 // bar
626 92
627 };
628}
629 ",
630 r"
631fn main() {
632 let _ = {
633 // <|>foo bar
634 92
635 };
636}
637 ",
638 )
639 }
611} 640}
diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs
index a6320bd2f..de924fad2 100644
--- a/crates/ra_ide/src/references.rs
+++ b/crates/ra_ide/src/references.rs
@@ -13,6 +13,7 @@ mod classify;
13mod rename; 13mod rename;
14mod search_scope; 14mod search_scope;
15 15
16use crate::expand::descend_into_macros_with_analyzer;
16use hir::{InFile, SourceBinder}; 17use hir::{InFile, SourceBinder};
17use once_cell::unsync::Lazy; 18use once_cell::unsync::Lazy;
18use ra_db::{SourceDatabase, SourceDatabaseExt}; 19use ra_db::{SourceDatabase, SourceDatabaseExt};
@@ -192,39 +193,62 @@ fn process_definition(
192 193
193 let parse = Lazy::new(|| SourceFile::parse(&text)); 194 let parse = Lazy::new(|| SourceFile::parse(&text));
194 let mut sb = Lazy::new(|| SourceBinder::new(db)); 195 let mut sb = Lazy::new(|| SourceBinder::new(db));
196 let mut analyzer = None;
195 197
196 for (idx, _) in text.match_indices(pat) { 198 for (idx, _) in text.match_indices(pat) {
197 let offset = TextUnit::from_usize(idx); 199 let offset = TextUnit::from_usize(idx);
198 200
199 if let Some(name_ref) = 201 let (name_ref, range) = if let Some(name_ref) =
200 find_node_at_offset::<ast::NameRef>(parse.tree().syntax(), offset) 202 find_node_at_offset::<ast::NameRef>(parse.tree().syntax(), offset)
201 { 203 {
202 let range = name_ref.syntax().text_range(); 204 let range = name_ref.syntax().text_range();
203 if let Some(search_range) = search_range { 205 (InFile::new(file_id.into(), name_ref), range)
204 if !range.is_subrange(&search_range) { 206 } else {
205 continue; 207 // Handle macro token cases
206 } 208 let t = match parse.tree().syntax().token_at_offset(offset) {
209 TokenAtOffset::None => continue,
210 TokenAtOffset::Single(t) => t,
211 TokenAtOffset::Between(_, t) => t,
212 };
213 let range = t.text_range();
214 let analyzer = analyzer.get_or_insert_with(|| {
215 sb.analyze(InFile::new(file_id.into(), parse.tree().syntax()), None)
216 });
217 let expanded = descend_into_macros_with_analyzer(
218 db,
219 &analyzer,
220 InFile::new(file_id.into(), t),
221 );
222 if let Some(token) = ast::NameRef::cast(expanded.value.parent()) {
223 (expanded.with_value(token), range)
224 } else {
225 continue;
207 } 226 }
208 // FIXME: reuse sb 227 };
209 // See https://github.com/rust-lang/rust/pull/68198#issuecomment-574269098 228
210 229 if let Some(search_range) = search_range {
211 if let Some(d) = classify_name_ref(&mut sb, InFile::new(file_id.into(), &name_ref)) 230 if !range.is_subrange(&search_range) {
212 { 231 continue;
213 if d == def { 232 }
214 let kind = if is_record_lit_name_ref(&name_ref) 233 }
215 || is_call_expr_name_ref(&name_ref) 234 // FIXME: reuse sb
216 { 235 // See https://github.com/rust-lang/rust/pull/68198#issuecomment-574269098
217 ReferenceKind::StructLiteral 236
218 } else { 237 if let Some(d) = classify_name_ref(&mut sb, name_ref.as_ref()) {
219 ReferenceKind::Other 238 if d == def {
220 }; 239 let kind = if is_record_lit_name_ref(&name_ref.value)
221 240 || is_call_expr_name_ref(&name_ref.value)
222 refs.push(Reference { 241 {
223 file_range: FileRange { file_id, range }, 242 ReferenceKind::StructLiteral
224 kind, 243 } else {
225 access: reference_access(&d.kind, &name_ref), 244 ReferenceKind::Other
226 }); 245 };
227 } 246
247 refs.push(Reference {
248 file_range: FileRange { file_id, range },
249 kind,
250 access: reference_access(&d.kind, &name_ref.value),
251 });
228 } 252 }
229 } 253 }
230 } 254 }
diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs
index 08e77c01f..c46b78cb6 100644
--- a/crates/ra_ide/src/references/rename.rs
+++ b/crates/ra_ide/src/references/rename.rs
@@ -211,6 +211,25 @@ mod tests {
211 } 211 }
212 212
213 #[test] 213 #[test]
214 fn test_rename_for_macro_args() {
215 test_rename(
216 r#"
217 macro_rules! foo {($i:ident) => {$i} }
218 fn main() {
219 let a<|> = "test";
220 foo!(a);
221 }"#,
222 "b",
223 r#"
224 macro_rules! foo {($i:ident) => {$i} }
225 fn main() {
226 let b = "test";
227 foo!(b);
228 }"#,
229 );
230 }
231
232 #[test]
214 fn test_rename_for_param_inside() { 233 fn test_rename_for_param_inside() {
215 test_rename( 234 test_rename(
216 r#" 235 r#"
diff --git a/crates/ra_lsp_server/src/lib.rs b/crates/ra_lsp_server/src/lib.rs
index 1208c1343..a3464a5a3 100644
--- a/crates/ra_lsp_server/src/lib.rs
+++ b/crates/ra_lsp_server/src/lib.rs
@@ -31,6 +31,8 @@ mod config;
31mod world; 31mod world;
32mod diagnostics; 32mod diagnostics;
33 33
34use serde::de::DeserializeOwned;
35
34pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>; 36pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
35pub use crate::{ 37pub use crate::{
36 caps::server_capabilities, 38 caps::server_capabilities,
@@ -38,3 +40,9 @@ pub use crate::{
38 main_loop::LspError, 40 main_loop::LspError,
39 main_loop::{main_loop, show_message}, 41 main_loop::{main_loop, show_message},
40}; 42};
43
44pub fn from_json<T: DeserializeOwned>(what: &'static str, json: serde_json::Value) -> Result<T> {
45 let res = T::deserialize(&json)
46 .map_err(|e| format!("Failed to deserialize {}: {}; {}", what, e, json))?;
47 Ok(res)
48}
diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/main.rs
index 3879eeff2..c8a017c5c 100644
--- a/crates/ra_lsp_server/src/main.rs
+++ b/crates/ra_lsp_server/src/main.rs
@@ -1,7 +1,7 @@
1//! `ra_lsp_server` binary 1//! `ra_lsp_server` binary
2 2
3use lsp_server::Connection; 3use lsp_server::Connection;
4use ra_lsp_server::{show_message, Result, ServerConfig}; 4use ra_lsp_server::{from_json, show_message, Result, ServerConfig};
5use ra_prof; 5use ra_prof;
6 6
7fn main() -> Result<()> { 7fn main() -> Result<()> {
@@ -45,7 +45,8 @@ fn run_server() -> Result<()> {
45 let server_capabilities = serde_json::to_value(ra_lsp_server::server_capabilities()).unwrap(); 45 let server_capabilities = serde_json::to_value(ra_lsp_server::server_capabilities()).unwrap();
46 46
47 let initialize_params = connection.initialize(server_capabilities)?; 47 let initialize_params = connection.initialize(server_capabilities)?;
48 let initialize_params: lsp_types::InitializeParams = serde_json::from_value(initialize_params)?; 48 let initialize_params =
49 from_json::<lsp_types::InitializeParams>("InitializeParams", initialize_params)?;
49 50
50 if let Some(client_info) = initialize_params.client_info { 51 if let Some(client_info) = initialize_params.client_info {
51 log::info!("Client '{}' {}", client_info.name, client_info.version.unwrap_or_default()); 52 log::info!("Client '{}' {}", client_info.name, client_info.version.unwrap_or_default());
@@ -62,17 +63,13 @@ fn run_server() -> Result<()> {
62 .filter(|workspaces| !workspaces.is_empty()) 63 .filter(|workspaces| !workspaces.is_empty())
63 .unwrap_or_else(|| vec![root]); 64 .unwrap_or_else(|| vec![root]);
64 65
65 let server_config: ServerConfig = initialize_params 66 let server_config = initialize_params
66 .initialization_options 67 .initialization_options
67 .and_then(|v| { 68 .and_then(|v| {
68 serde_json::from_value(v) 69 from_json::<ServerConfig>("config", v)
69 .map_err(|e| { 70 .map_err(|e| {
70 log::error!("failed to deserialize config: {}", e); 71 log::error!("{}", e);
71 show_message( 72 show_message(lsp_types::MessageType::Error, e.to_string(), &connection.sender);
72 lsp_types::MessageType::Error,
73 format!("failed to deserialize config: {}", e),
74 &connection.sender,
75 );
76 }) 73 })
77 .ok() 74 .ok()
78 }) 75 })
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index 282f6e8fc..59c86bbfa 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -2,20 +2,21 @@
2//! The majority of requests are fulfilled by calling into the `ra_ide` crate. 2//! The majority of requests are fulfilled by calling into the `ra_ide` crate.
3 3
4use std::{ 4use std::{
5 collections::hash_map::Entry,
5 fmt::Write as _, 6 fmt::Write as _,
6 io::Write as _, 7 io::Write as _,
7 process::{self, Stdio}, 8 process::{self, Stdio},
8}; 9};
9 10
10use either::Either;
11use lsp_server::ErrorCode; 11use lsp_server::ErrorCode;
12use lsp_types::{ 12use lsp_types::{
13 CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem, 13 CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem,
14 CallHierarchyOutgoingCall, CallHierarchyOutgoingCallsParams, CallHierarchyPrepareParams, 14 CallHierarchyOutgoingCall, CallHierarchyOutgoingCallsParams, CallHierarchyPrepareParams,
15 CodeAction, CodeActionResponse, CodeLens, Command, CompletionItem, Diagnostic, 15 CodeAction, CodeActionOrCommand, CodeActionResponse, CodeLens, Command, CompletionItem,
16 DocumentFormattingParams, DocumentHighlight, DocumentSymbol, FoldingRange, FoldingRangeParams, 16 Diagnostic, DocumentFormattingParams, DocumentHighlight, DocumentSymbol, FoldingRange,
17 Hover, HoverContents, Location, MarkupContent, MarkupKind, Position, PrepareRenameResponse, 17 FoldingRangeParams, Hover, HoverContents, Location, MarkupContent, MarkupKind, Position,
18 Range, RenameParams, SymbolInformation, TextDocumentIdentifier, TextEdit, WorkspaceEdit, 18 PrepareRenameResponse, Range, RenameParams, SymbolInformation, TextDocumentIdentifier,
19 TextEdit, WorkspaceEdit,
19}; 20};
20use ra_ide::{ 21use ra_ide::{
21 AssistId, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind, 22 AssistId, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind,
@@ -34,6 +35,7 @@ use crate::{
34 TryConvWithToVec, 35 TryConvWithToVec,
35 }, 36 },
36 diagnostics::DiagnosticTask, 37 diagnostics::DiagnosticTask,
38 from_json,
37 req::{self, Decoration, InlayHint, InlayHintsParams, InlayKind}, 39 req::{self, Decoration, InlayHint, InlayHintsParams, InlayKind},
38 world::WorldSnapshot, 40 world::WorldSnapshot,
39 LspError, Result, 41 LspError, Result,
@@ -685,34 +687,53 @@ pub fn handle_code_action(
685 res.push(fix.action.clone()); 687 res.push(fix.action.clone());
686 } 688 }
687 689
690 let mut groups = FxHashMap::default();
688 for assist in world.analysis().assists(FileRange { file_id, range })?.into_iter() { 691 for assist in world.analysis().assists(FileRange { file_id, range })?.into_iter() {
689 let title = assist.label.clone(); 692 let arg = to_value(assist.source_change.try_conv_with(&world)?)?;
693
694 let (command, title, arg) = match assist.group_label {
695 None => ("rust-analyzer.applySourceChange", assist.label.clone(), arg),
696
697 // Group all assists with the same `group_label` into a single CodeAction.
698 Some(group_label) => {
699 match groups.entry(group_label.clone()) {
700 Entry::Occupied(entry) => {
701 let idx: usize = *entry.get();
702 match &mut res[idx] {
703 CodeActionOrCommand::CodeAction(CodeAction {
704 command: Some(Command { arguments: Some(arguments), .. }),
705 ..
706 }) => match arguments.as_mut_slice() {
707 [serde_json::Value::Array(arguments)] => arguments.push(arg),
708 _ => panic!("invalid group"),
709 },
710 _ => panic!("invalid group"),
711 }
712 continue;
713 }
714 Entry::Vacant(entry) => {
715 entry.insert(res.len());
716 }
717 }
718 ("rust-analyzer.selectAndApplySourceChange", group_label, to_value(vec![arg])?)
719 }
720 };
690 721
691 let command = match assist.change_data { 722 let command = Command {
692 Either::Left(change) => Command { 723 title: assist.label.clone(),
693 title, 724 command: command.to_string(),
694 command: "rust-analyzer.applySourceChange".to_string(), 725 arguments: Some(vec![arg]),
695 arguments: Some(vec![to_value(change.try_conv_with(&world)?)?]), 726 };
696 }, 727
697 Either::Right(changes) => Command { 728 let kind = match assist.id {
698 title, 729 AssistId("introduce_variable") => Some("refactor.extract.variable".to_string()),
699 command: "rust-analyzer.selectAndApplySourceChange".to_string(), 730 AssistId("add_custom_impl") => Some("refactor.rewrite.add_custom_impl".to_string()),
700 arguments: Some(vec![to_value( 731 _ => None,
701 changes
702 .into_iter()
703 .map(|change| change.try_conv_with(&world))
704 .collect::<Result<Vec<_>>>()?,
705 )?]),
706 },
707 }; 732 };
708 733
709 let action = CodeAction { 734 let action = CodeAction {
710 title: command.title.clone(), 735 title,
711 kind: match assist.id { 736 kind,
712 AssistId("introduce_variable") => Some("refactor.extract.variable".to_string()),
713 AssistId("add_custom_impl") => Some("refactor.rewrite.add_custom_impl".to_string()),
714 _ => None,
715 },
716 diagnostics: None, 737 diagnostics: None,
717 edit: None, 738 edit: None,
718 command: Some(command), 739 command: Some(command),
@@ -791,7 +812,7 @@ enum CodeLensResolveData {
791pub fn handle_code_lens_resolve(world: WorldSnapshot, code_lens: CodeLens) -> Result<CodeLens> { 812pub fn handle_code_lens_resolve(world: WorldSnapshot, code_lens: CodeLens) -> Result<CodeLens> {
792 let _p = profile("handle_code_lens_resolve"); 813 let _p = profile("handle_code_lens_resolve");
793 let data = code_lens.data.unwrap(); 814 let data = code_lens.data.unwrap();
794 let resolve = serde_json::from_value(data)?; 815 let resolve = from_json::<Option<CodeLensResolveData>>("CodeLensResolveData", data)?;
795 match resolve { 816 match resolve {
796 Some(CodeLensResolveData::Impls(lens_params)) => { 817 Some(CodeLensResolveData::Impls(lens_params)) => {
797 let locations: Vec<Location> = 818 let locations: Vec<Location> =
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs
index f154077a8..b72d2e9e6 100644
--- a/crates/ra_parser/src/grammar/expressions/atom.rs
+++ b/crates/ra_parser/src/grammar/expressions/atom.rs
@@ -336,7 +336,7 @@ fn for_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
336fn cond(p: &mut Parser) { 336fn cond(p: &mut Parser) {
337 let m = p.start(); 337 let m = p.start();
338 if p.eat(T![let]) { 338 if p.eat(T![let]) {
339 patterns::pattern_list(p); 339 patterns::pattern_top(p);
340 p.expect(T![=]); 340 p.expect(T![=]);
341 } 341 }
342 expr_no_struct(p); 342 expr_no_struct(p);
@@ -430,7 +430,7 @@ fn match_arm(p: &mut Parser) -> BlockLike {
430 // } 430 // }
431 attributes::outer_attributes(p); 431 attributes::outer_attributes(p);
432 432
433 patterns::pattern_list_r(p, TokenSet::EMPTY); 433 patterns::pattern_top_r(p, TokenSet::EMPTY);
434 if p.at(T![if]) { 434 if p.at(T![if]) {
435 match_guard(p); 435 match_guard(p);
436 } 436 }
diff --git a/crates/ra_parser/src/grammar/params.rs b/crates/ra_parser/src/grammar/params.rs
index 94edc7f35..ed4f93347 100644
--- a/crates/ra_parser/src/grammar/params.rs
+++ b/crates/ra_parser/src/grammar/params.rs
@@ -116,7 +116,7 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) {
116 // type Qux = fn(baz: Bar::Baz); 116 // type Qux = fn(baz: Bar::Baz);
117 Flavor::FnPointer => { 117 Flavor::FnPointer => {
118 if p.at(IDENT) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) { 118 if p.at(IDENT) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) {
119 patterns::pattern(p); 119 patterns::pattern_single(p);
120 types::ascription(p); 120 types::ascription(p);
121 } else { 121 } else {
122 types::type_(p); 122 types::type_(p);
@@ -127,7 +127,7 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) {
127 // let foo = |bar, baz: Baz, qux: Qux::Quux| (); 127 // let foo = |bar, baz: Baz, qux: Qux::Quux| ();
128 // } 128 // }
129 Flavor::Closure => { 129 Flavor::Closure => {
130 patterns::pattern(p); 130 patterns::pattern_single(p);
131 if p.at(T![:]) && !p.at(T![::]) { 131 if p.at(T![:]) && !p.at(T![::]) {
132 types::ascription(p); 132 types::ascription(p);
133 } 133 }
diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs
index 422a4e3dc..3afbaa82b 100644
--- a/crates/ra_parser/src/grammar/patterns.rs
+++ b/crates/ra_parser/src/grammar/patterns.rs
@@ -11,22 +11,47 @@ pub(crate) fn pattern(p: &mut Parser) {
11} 11}
12 12
13/// Parses a pattern list separated by pipes `|` 13/// Parses a pattern list separated by pipes `|`
14pub(super) fn pattern_list(p: &mut Parser) { 14pub(super) fn pattern_top(p: &mut Parser) {
15 pattern_list_r(p, PAT_RECOVERY_SET) 15 pattern_top_r(p, PAT_RECOVERY_SET)
16}
17
18pub(crate) fn pattern_single(p: &mut Parser) {
19 pattern_single_r(p, PAT_RECOVERY_SET);
16} 20}
17 21
18/// Parses a pattern list separated by pipes `|` 22/// Parses a pattern list separated by pipes `|`
19/// using the given `recovery_set` 23/// using the given `recovery_set`
20pub(super) fn pattern_list_r(p: &mut Parser, recovery_set: TokenSet) { 24pub(super) fn pattern_top_r(p: &mut Parser, recovery_set: TokenSet) {
21 p.eat(T![|]); 25 p.eat(T![|]);
22 pattern_r(p, recovery_set); 26 pattern_r(p, recovery_set);
27}
23 28
29/// Parses a pattern list separated by pipes `|`, with no leading `|`,using the
30/// given `recovery_set`
31// test or_pattern
32// fn main() {
33// match () {
34// (_ | _) => (),
35// &(_ | _) => (),
36// (_ | _,) => (),
37// [_ | _,] => (),
38// }
39// }
40fn pattern_r(p: &mut Parser, recovery_set: TokenSet) {
41 let m = p.start();
42 pattern_single_r(p, recovery_set);
43
44 if !p.at(T![|]) {
45 m.abandon(p);
46 return;
47 }
24 while p.eat(T![|]) { 48 while p.eat(T![|]) {
25 pattern_r(p, recovery_set); 49 pattern_single_r(p, recovery_set);
26 } 50 }
51 m.complete(p, OR_PAT);
27} 52}
28 53
29pub(super) fn pattern_r(p: &mut Parser, recovery_set: TokenSet) { 54fn pattern_single_r(p: &mut Parser, recovery_set: TokenSet) {
30 if let Some(lhs) = atom_pat(p, recovery_set) { 55 if let Some(lhs) = atom_pat(p, recovery_set) {
31 // test range_pat 56 // test range_pat
32 // fn main() { 57 // fn main() {
@@ -258,19 +283,41 @@ fn ref_pat(p: &mut Parser) -> CompletedMarker {
258 let m = p.start(); 283 let m = p.start();
259 p.bump(T![&]); 284 p.bump(T![&]);
260 p.eat(T![mut]); 285 p.eat(T![mut]);
261 pattern(p); 286 pattern_single(p);
262 m.complete(p, REF_PAT) 287 m.complete(p, REF_PAT)
263} 288}
264 289
265// test tuple_pat 290// test tuple_pat
266// fn main() { 291// fn main() {
267// let (a, b, ..) = (); 292// let (a, b, ..) = ();
293// let (a,) = ();
294// let (..) = ();
295// let () = ();
268// } 296// }
269fn tuple_pat(p: &mut Parser) -> CompletedMarker { 297fn tuple_pat(p: &mut Parser) -> CompletedMarker {
270 assert!(p.at(T!['('])); 298 assert!(p.at(T!['(']));
271 let m = p.start(); 299 let m = p.start();
272 tuple_pat_fields(p); 300 p.bump(T!['(']);
273 m.complete(p, TUPLE_PAT) 301 let mut has_comma = false;
302 let mut has_pat = false;
303 let mut has_rest = false;
304 while !p.at(EOF) && !p.at(T![')']) {
305 has_pat = true;
306 if !p.at_ts(PATTERN_FIRST) {
307 p.error("expected a pattern");
308 break;
309 }
310 has_rest |= p.at(T![..]);
311
312 pattern(p);
313 if !p.at(T![')']) {
314 has_comma = true;
315 p.expect(T![,]);
316 }
317 }
318 p.expect(T![')']);
319
320 m.complete(p, if !has_comma && !has_rest && has_pat { PAREN_PAT } else { TUPLE_PAT })
274} 321}
275 322
276// test slice_pat 323// test slice_pat
@@ -315,7 +362,7 @@ fn bind_pat(p: &mut Parser, with_at: bool) -> CompletedMarker {
315 p.eat(T![mut]); 362 p.eat(T![mut]);
316 name(p); 363 name(p);
317 if with_at && p.eat(T![@]) { 364 if with_at && p.eat(T![@]) {
318 pattern(p); 365 pattern_single(p);
319 } 366 }
320 m.complete(p, BIND_PAT) 367 m.complete(p, BIND_PAT)
321} 368}
@@ -330,6 +377,6 @@ fn box_pat(p: &mut Parser) -> CompletedMarker {
330 assert!(p.at(T![box])); 377 assert!(p.at(T![box]));
331 let m = p.start(); 378 let m = p.start();
332 p.bump(T![box]); 379 p.bump(T![box]);
333 pattern(p); 380 pattern_single(p);
334 m.complete(p, BOX_PAT) 381 m.complete(p, BOX_PAT)
335} 382}
diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs
index 4b301d67a..1068da0a0 100644
--- a/crates/ra_parser/src/syntax_kind/generated.rs
+++ b/crates/ra_parser/src/syntax_kind/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#![allow(bad_style, missing_docs, unreachable_pub)] 3#![allow(bad_style, missing_docs, unreachable_pub)]
4#[doc = r" The kind of syntax node, e.g. `IDENT`, `USE_KW`, or `STRUCT_DEF`."] 4#[doc = r" The kind of syntax node, e.g. `IDENT`, `USE_KW`, or `STRUCT_DEF`."]
@@ -151,6 +151,8 @@ pub enum SyntaxKind {
151 FOR_TYPE, 151 FOR_TYPE,
152 IMPL_TRAIT_TYPE, 152 IMPL_TRAIT_TYPE,
153 DYN_TRAIT_TYPE, 153 DYN_TRAIT_TYPE,
154 OR_PAT,
155 PAREN_PAT,
154 REF_PAT, 156 REF_PAT,
155 BOX_PAT, 157 BOX_PAT,
156 BIND_PAT, 158 BIND_PAT,
diff --git a/crates/ra_project_model/src/sysroot.rs b/crates/ra_project_model/src/sysroot.rs
index 34d066b1e..a23265fc0 100644
--- a/crates/ra_project_model/src/sysroot.rs
+++ b/crates/ra_project_model/src/sysroot.rs
@@ -99,7 +99,8 @@ fn try_find_src_path(cargo_toml: &Path) -> Result<PathBuf> {
99 let rustc_output = Command::new("rustc") 99 let rustc_output = Command::new("rustc")
100 .current_dir(cargo_toml.parent().unwrap()) 100 .current_dir(cargo_toml.parent().unwrap())
101 .args(&["--print", "sysroot"]) 101 .args(&["--print", "sysroot"])
102 .output()?; 102 .output()
103 .map_err(|e| format!("rustc --print sysroot failed: {}", e))?;
103 if !rustc_output.status.success() { 104 if !rustc_output.status.success() {
104 Err("failed to locate sysroot")?; 105 Err("failed to locate sysroot")?;
105 } 106 }
diff --git a/crates/ra_syntax/Cargo.toml b/crates/ra_syntax/Cargo.toml
index c5a3d1999..83db943fe 100644
--- a/crates/ra_syntax/Cargo.toml
+++ b/crates/ra_syntax/Cargo.toml
@@ -4,7 +4,7 @@ name = "ra_syntax"
4version = "0.1.0" 4version = "0.1.0"
5authors = ["rust-analyzer developers"] 5authors = ["rust-analyzer developers"]
6license = "MIT OR Apache-2.0" 6license = "MIT OR Apache-2.0"
7description = "Comment and whitespace preserving parser for the Rust langauge" 7description = "Comment and whitespace preserving parser for the Rust language"
8repository = "https://github.com/rust-analyzer/rust-analyzer" 8repository = "https://github.com/rust-analyzer/rust-analyzer"
9 9
10[lib] 10[lib]
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 8a3669bd1..8eb240801 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/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
3use crate::{ 3use crate::{
4 ast::{self, AstChildren, AstNode}, 4 ast::{self, AstChildren, AstNode},
@@ -1759,8 +1759,8 @@ impl AstNode for MatchArm {
1759} 1759}
1760impl ast::AttrsOwner for MatchArm {} 1760impl ast::AttrsOwner for MatchArm {}
1761impl MatchArm { 1761impl MatchArm {
1762 pub fn pats(&self) -> AstChildren<Pat> { 1762 pub fn pat(&self) -> Option<Pat> {
1763 AstChildren::new(&self.syntax) 1763 AstChildren::new(&self.syntax).next()
1764 } 1764 }
1765 pub fn guard(&self) -> Option<MatchGuard> { 1765 pub fn guard(&self) -> Option<MatchGuard> {
1766 AstChildren::new(&self.syntax).next() 1766 AstChildren::new(&self.syntax).next()
@@ -1887,6 +1887,60 @@ impl RecordField {
1887 } 1887 }
1888} 1888}
1889#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1889#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1890pub struct OrPat {
1891 pub(crate) syntax: SyntaxNode,
1892}
1893impl AstNode for OrPat {
1894 fn can_cast(kind: SyntaxKind) -> bool {
1895 match kind {
1896 OR_PAT => true,
1897 _ => false,
1898 }
1899 }
1900 fn cast(syntax: SyntaxNode) -> Option<Self> {
1901 if Self::can_cast(syntax.kind()) {
1902 Some(Self { syntax })
1903 } else {
1904 None
1905 }
1906 }
1907 fn syntax(&self) -> &SyntaxNode {
1908 &self.syntax
1909 }
1910}
1911impl OrPat {
1912 pub fn pats(&self) -> AstChildren<Pat> {
1913 AstChildren::new(&self.syntax)
1914 }
1915}
1916#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1917pub struct ParenPat {
1918 pub(crate) syntax: SyntaxNode,
1919}
1920impl AstNode for ParenPat {
1921 fn can_cast(kind: SyntaxKind) -> bool {
1922 match kind {
1923 PAREN_PAT => true,
1924 _ => false,
1925 }
1926 }
1927 fn cast(syntax: SyntaxNode) -> Option<Self> {
1928 if Self::can_cast(syntax.kind()) {
1929 Some(Self { syntax })
1930 } else {
1931 None
1932 }
1933 }
1934 fn syntax(&self) -> &SyntaxNode {
1935 &self.syntax
1936 }
1937}
1938impl ParenPat {
1939 pub fn pat(&self) -> Option<Pat> {
1940 AstChildren::new(&self.syntax).next()
1941 }
1942}
1943#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1890pub struct RefPat { 1944pub struct RefPat {
1891 pub(crate) syntax: SyntaxNode, 1945 pub(crate) syntax: SyntaxNode,
1892} 1946}
@@ -3904,6 +3958,8 @@ impl AstNode for Expr {
3904} 3958}
3905#[derive(Debug, Clone, PartialEq, Eq, Hash)] 3959#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3906pub enum Pat { 3960pub enum Pat {
3961 OrPat(OrPat),
3962 ParenPat(ParenPat),
3907 RefPat(RefPat), 3963 RefPat(RefPat),
3908 BoxPat(BoxPat), 3964 BoxPat(BoxPat),
3909 BindPat(BindPat), 3965 BindPat(BindPat),
@@ -3917,6 +3973,16 @@ pub enum Pat {
3917 RangePat(RangePat), 3973 RangePat(RangePat),
3918 LiteralPat(LiteralPat), 3974 LiteralPat(LiteralPat),
3919} 3975}
3976impl From<OrPat> for Pat {
3977 fn from(node: OrPat) -> Pat {
3978 Pat::OrPat(node)
3979 }
3980}
3981impl From<ParenPat> for Pat {
3982 fn from(node: ParenPat) -> Pat {
3983 Pat::ParenPat(node)
3984 }
3985}
3920impl From<RefPat> for Pat { 3986impl From<RefPat> for Pat {
3921 fn from(node: RefPat) -> Pat { 3987 fn from(node: RefPat) -> Pat {
3922 Pat::RefPat(node) 3988 Pat::RefPat(node)
@@ -3980,15 +4046,16 @@ impl From<LiteralPat> for Pat {
3980impl AstNode for Pat { 4046impl AstNode for Pat {
3981 fn can_cast(kind: SyntaxKind) -> bool { 4047 fn can_cast(kind: SyntaxKind) -> bool {
3982 match kind { 4048 match kind {
3983 REF_PAT | BOX_PAT | BIND_PAT | PLACEHOLDER_PAT | DOT_DOT_PAT | PATH_PAT 4049 OR_PAT | PAREN_PAT | REF_PAT | BOX_PAT | BIND_PAT | PLACEHOLDER_PAT | DOT_DOT_PAT
3984 | RECORD_PAT | TUPLE_STRUCT_PAT | TUPLE_PAT | SLICE_PAT | RANGE_PAT | LITERAL_PAT => { 4050 | PATH_PAT | RECORD_PAT | TUPLE_STRUCT_PAT | TUPLE_PAT | SLICE_PAT | RANGE_PAT
3985 true 4051 | LITERAL_PAT => true,
3986 }
3987 _ => false, 4052 _ => false,
3988 } 4053 }
3989 } 4054 }
3990 fn cast(syntax: SyntaxNode) -> Option<Self> { 4055 fn cast(syntax: SyntaxNode) -> Option<Self> {
3991 let res = match syntax.kind() { 4056 let res = match syntax.kind() {
4057 OR_PAT => Pat::OrPat(OrPat { syntax }),
4058 PAREN_PAT => Pat::ParenPat(ParenPat { syntax }),
3992 REF_PAT => Pat::RefPat(RefPat { syntax }), 4059 REF_PAT => Pat::RefPat(RefPat { syntax }),
3993 BOX_PAT => Pat::BoxPat(BoxPat { syntax }), 4060 BOX_PAT => Pat::BoxPat(BoxPat { syntax }),
3994 BIND_PAT => Pat::BindPat(BindPat { syntax }), 4061 BIND_PAT => Pat::BindPat(BindPat { syntax }),
@@ -4007,6 +4074,8 @@ impl AstNode for Pat {
4007 } 4074 }
4008 fn syntax(&self) -> &SyntaxNode { 4075 fn syntax(&self) -> &SyntaxNode {
4009 match self { 4076 match self {
4077 Pat::OrPat(it) => &it.syntax,
4078 Pat::ParenPat(it) => &it.syntax,
4010 Pat::RefPat(it) => &it.syntax, 4079 Pat::RefPat(it) => &it.syntax,
4011 Pat::BoxPat(it) => &it.syntax, 4080 Pat::BoxPat(it) => &it.syntax,
4012 Pat::BindPat(it) => &it.syntax, 4081 Pat::BindPat(it) => &it.syntax,
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0030_cond.txt b/crates/ra_syntax/test_data/parser/inline/ok/0030_cond.txt
index 4028ca243..6fd49c7bc 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0030_cond.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0030_cond.txt
@@ -63,27 +63,28 @@ SOURCE_FILE@[0; 197)
63 CONDITION@[56; 84) 63 CONDITION@[56; 84)
64 LET_KW@[56; 59) "let" 64 LET_KW@[56; 59) "let"
65 WHITESPACE@[59; 60) " " 65 WHITESPACE@[59; 60) " "
66 TUPLE_STRUCT_PAT@[60; 67) 66 OR_PAT@[60; 77)
67 PATH@[60; 64) 67 TUPLE_STRUCT_PAT@[60; 67)
68 PATH_SEGMENT@[60; 64) 68 PATH@[60; 64)
69 NAME_REF@[60; 64) 69 PATH_SEGMENT@[60; 64)
70 IDENT@[60; 64) "Some" 70 NAME_REF@[60; 64)
71 L_PAREN@[64; 65) "(" 71 IDENT@[60; 64) "Some"
72 PLACEHOLDER_PAT@[65; 66) 72 L_PAREN@[64; 65) "("
73 UNDERSCORE@[65; 66) "_" 73 PLACEHOLDER_PAT@[65; 66)
74 R_PAREN@[66; 67) ")" 74 UNDERSCORE@[65; 66) "_"
75 WHITESPACE@[67; 68) " " 75 R_PAREN@[66; 67) ")"
76 PIPE@[68; 69) "|" 76 WHITESPACE@[67; 68) " "
77 WHITESPACE@[69; 70) " " 77 PIPE@[68; 69) "|"
78 TUPLE_STRUCT_PAT@[70; 77) 78 WHITESPACE@[69; 70) " "
79 PATH@[70; 74) 79 TUPLE_STRUCT_PAT@[70; 77)
80 PATH_SEGMENT@[70; 74) 80 PATH@[70; 74)
81 NAME_REF@[70; 74) 81 PATH_SEGMENT@[70; 74)
82 IDENT@[70; 74) "Some" 82 NAME_REF@[70; 74)
83 L_PAREN@[74; 75) "(" 83 IDENT@[70; 74) "Some"
84 PLACEHOLDER_PAT@[75; 76) 84 L_PAREN@[74; 75) "("
85 UNDERSCORE@[75; 76) "_" 85 PLACEHOLDER_PAT@[75; 76)
86 R_PAREN@[76; 77) ")" 86 UNDERSCORE@[75; 76) "_"
87 R_PAREN@[76; 77) ")"
87 WHITESPACE@[77; 78) " " 88 WHITESPACE@[77; 78) " "
88 EQ@[78; 79) "=" 89 EQ@[78; 79) "="
89 WHITESPACE@[79; 80) " " 90 WHITESPACE@[79; 80) " "
@@ -137,27 +138,28 @@ SOURCE_FILE@[0; 197)
137 CONDITION@[129; 157) 138 CONDITION@[129; 157)
138 LET_KW@[129; 132) "let" 139 LET_KW@[129; 132) "let"
139 WHITESPACE@[132; 133) " " 140 WHITESPACE@[132; 133) " "
140 TUPLE_STRUCT_PAT@[133; 140) 141 OR_PAT@[133; 150)
141 PATH@[133; 137) 142 TUPLE_STRUCT_PAT@[133; 140)
142 PATH_SEGMENT@[133; 137) 143 PATH@[133; 137)
143 NAME_REF@[133; 137) 144 PATH_SEGMENT@[133; 137)
144 IDENT@[133; 137) "Some" 145 NAME_REF@[133; 137)
145 L_PAREN@[137; 138) "(" 146 IDENT@[133; 137) "Some"
146 PLACEHOLDER_PAT@[138; 139) 147 L_PAREN@[137; 138) "("
147 UNDERSCORE@[138; 139) "_" 148 PLACEHOLDER_PAT@[138; 139)
148 R_PAREN@[139; 140) ")" 149 UNDERSCORE@[138; 139) "_"
149 WHITESPACE@[140; 141) " " 150 R_PAREN@[139; 140) ")"
150 PIPE@[141; 142) "|" 151 WHITESPACE@[140; 141) " "
151 WHITESPACE@[142; 143) " " 152 PIPE@[141; 142) "|"
152 TUPLE_STRUCT_PAT@[143; 150) 153 WHITESPACE@[142; 143) " "
153 PATH@[143; 147) 154 TUPLE_STRUCT_PAT@[143; 150)
154 PATH_SEGMENT@[143; 147) 155 PATH@[143; 147)
155 NAME_REF@[143; 147) 156 PATH_SEGMENT@[143; 147)
156 IDENT@[143; 147) "Some" 157 NAME_REF@[143; 147)
157 L_PAREN@[147; 148) "(" 158 IDENT@[143; 147) "Some"
158 PLACEHOLDER_PAT@[148; 149) 159 L_PAREN@[147; 148) "("
159 UNDERSCORE@[148; 149) "_" 160 PLACEHOLDER_PAT@[148; 149)
160 R_PAREN@[149; 150) ")" 161 UNDERSCORE@[148; 149) "_"
162 R_PAREN@[149; 150) ")"
161 WHITESPACE@[150; 151) " " 163 WHITESPACE@[150; 151) " "
162 EQ@[151; 152) "=" 164 EQ@[151; 152) "="
163 WHITESPACE@[152; 153) " " 165 WHITESPACE@[152; 153) " "
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.txt b/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.txt
index 87272917b..2f07af4e1 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.txt
@@ -74,15 +74,16 @@ SOURCE_FILE@[0; 167)
74 COMMA@[83; 84) "," 74 COMMA@[83; 84) ","
75 WHITESPACE@[84; 93) "\n " 75 WHITESPACE@[84; 93) "\n "
76 MATCH_ARM@[93; 109) 76 MATCH_ARM@[93; 109)
77 BIND_PAT@[93; 94) 77 OR_PAT@[93; 98)
78 NAME@[93; 94) 78 BIND_PAT@[93; 94)
79 IDENT@[93; 94) "X" 79 NAME@[93; 94)
80 WHITESPACE@[94; 95) " " 80 IDENT@[93; 94) "X"
81 PIPE@[95; 96) "|" 81 WHITESPACE@[94; 95) " "
82 WHITESPACE@[96; 97) " " 82 PIPE@[95; 96) "|"
83 BIND_PAT@[97; 98) 83 WHITESPACE@[96; 97) " "
84 NAME@[97; 98) 84 BIND_PAT@[97; 98)
85 IDENT@[97; 98) "Y" 85 NAME@[97; 98)
86 IDENT@[97; 98) "Y"
86 WHITESPACE@[98; 99) " " 87 WHITESPACE@[98; 99) " "
87 MATCH_GUARD@[99; 103) 88 MATCH_GUARD@[99; 103)
88 IF_KW@[99; 101) "if" 89 IF_KW@[99; 101) "if"
@@ -103,15 +104,16 @@ SOURCE_FILE@[0; 167)
103 MATCH_ARM@[119; 137) 104 MATCH_ARM@[119; 137)
104 PIPE@[119; 120) "|" 105 PIPE@[119; 120) "|"
105 WHITESPACE@[120; 121) " " 106 WHITESPACE@[120; 121) " "
106 BIND_PAT@[121; 122) 107 OR_PAT@[121; 126)
107 NAME@[121; 122) 108 BIND_PAT@[121; 122)
108 IDENT@[121; 122) "X" 109 NAME@[121; 122)
109 WHITESPACE@[122; 123) " " 110 IDENT@[121; 122) "X"
110 PIPE@[123; 124) "|" 111 WHITESPACE@[122; 123) " "
111 WHITESPACE@[124; 125) " " 112 PIPE@[123; 124) "|"
112 BIND_PAT@[125; 126) 113 WHITESPACE@[124; 125) " "
113 NAME@[125; 126) 114 BIND_PAT@[125; 126)
114 IDENT@[125; 126) "Y" 115 NAME@[125; 126)
116 IDENT@[125; 126) "Y"
115 WHITESPACE@[126; 127) " " 117 WHITESPACE@[126; 127) " "
116 MATCH_GUARD@[127; 131) 118 MATCH_GUARD@[127; 131)
117 IF_KW@[127; 129) "if" 119 IF_KW@[127; 129) "if"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.rs b/crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.rs
index f785acd36..ba719879d 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.rs
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.rs
@@ -1,3 +1,6 @@
1fn main() { 1fn main() {
2 let (a, b, ..) = (); 2 let (a, b, ..) = ();
3 let (a,) = ();
4 let (..) = ();
5 let () = ();
3} 6}
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.txt b/crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.txt
index 674dec493..4680c267e 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 39) 1SOURCE_FILE@[0; 94)
2 FN_DEF@[0; 38) 2 FN_DEF@[0; 93)
3 FN_KW@[0; 2) "fn" 3 FN_KW@[0; 2) "fn"
4 WHITESPACE@[2; 3) " " 4 WHITESPACE@[2; 3) " "
5 NAME@[3; 7) 5 NAME@[3; 7)
@@ -8,8 +8,8 @@ SOURCE_FILE@[0; 39)
8 L_PAREN@[7; 8) "(" 8 L_PAREN@[7; 8) "("
9 R_PAREN@[8; 9) ")" 9 R_PAREN@[8; 9) ")"
10 WHITESPACE@[9; 10) " " 10 WHITESPACE@[9; 10) " "
11 BLOCK_EXPR@[10; 38) 11 BLOCK_EXPR@[10; 93)
12 BLOCK@[10; 38) 12 BLOCK@[10; 93)
13 L_CURLY@[10; 11) "{" 13 L_CURLY@[10; 11) "{"
14 WHITESPACE@[11; 16) "\n " 14 WHITESPACE@[11; 16) "\n "
15 LET_STMT@[16; 36) 15 LET_STMT@[16; 36)
@@ -37,6 +37,54 @@ SOURCE_FILE@[0; 39)
37 L_PAREN@[33; 34) "(" 37 L_PAREN@[33; 34) "("
38 R_PAREN@[34; 35) ")" 38 R_PAREN@[34; 35) ")"
39 SEMI@[35; 36) ";" 39 SEMI@[35; 36) ";"
40 WHITESPACE@[36; 37) "\n" 40 WHITESPACE@[36; 41) "\n "
41 R_CURLY@[37; 38) "}" 41 LET_STMT@[41; 55)
42 WHITESPACE@[38; 39) "\n" 42 LET_KW@[41; 44) "let"
43 WHITESPACE@[44; 45) " "
44 TUPLE_PAT@[45; 49)
45 L_PAREN@[45; 46) "("
46 BIND_PAT@[46; 47)
47 NAME@[46; 47)
48 IDENT@[46; 47) "a"
49 COMMA@[47; 48) ","
50 R_PAREN@[48; 49) ")"
51 WHITESPACE@[49; 50) " "
52 EQ@[50; 51) "="
53 WHITESPACE@[51; 52) " "
54 TUPLE_EXPR@[52; 54)
55 L_PAREN@[52; 53) "("
56 R_PAREN@[53; 54) ")"
57 SEMI@[54; 55) ";"
58 WHITESPACE@[55; 60) "\n "
59 LET_STMT@[60; 74)
60 LET_KW@[60; 63) "let"
61 WHITESPACE@[63; 64) " "
62 TUPLE_PAT@[64; 68)
63 L_PAREN@[64; 65) "("
64 DOT_DOT_PAT@[65; 67)
65 DOTDOT@[65; 67) ".."
66 R_PAREN@[67; 68) ")"
67 WHITESPACE@[68; 69) " "
68 EQ@[69; 70) "="
69 WHITESPACE@[70; 71) " "
70 TUPLE_EXPR@[71; 73)
71 L_PAREN@[71; 72) "("
72 R_PAREN@[72; 73) ")"
73 SEMI@[73; 74) ";"
74 WHITESPACE@[74; 79) "\n "
75 LET_STMT@[79; 91)
76 LET_KW@[79; 82) "let"
77 WHITESPACE@[82; 83) " "
78 TUPLE_PAT@[83; 85)
79 L_PAREN@[83; 84) "("
80 R_PAREN@[84; 85) ")"
81 WHITESPACE@[85; 86) " "
82 EQ@[86; 87) "="
83 WHITESPACE@[87; 88) " "
84 TUPLE_EXPR@[88; 90)
85 L_PAREN@[88; 89) "("
86 R_PAREN@[89; 90) ")"
87 SEMI@[90; 91) ";"
88 WHITESPACE@[91; 92) "\n"
89 R_CURLY@[92; 93) "}"
90 WHITESPACE@[93; 94) "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0156_or_pattern.rs b/crates/ra_syntax/test_data/parser/inline/ok/0156_or_pattern.rs
new file mode 100644
index 000000000..a26316605
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0156_or_pattern.rs
@@ -0,0 +1,8 @@
1fn main() {
2 match () {
3 (_ | _) => (),
4 &(_ | _) => (),
5 (_ | _,) => (),
6 [_ | _,] => (),
7 }
8}
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0156_or_pattern.txt b/crates/ra_syntax/test_data/parser/inline/ok/0156_or_pattern.txt
new file mode 100644
index 000000000..3a196d3c0
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0156_or_pattern.txt
@@ -0,0 +1,112 @@
1SOURCE_FILE@[0; 130)
2 FN_DEF@[0; 129)
3 FN_KW@[0; 2) "fn"
4 WHITESPACE@[2; 3) " "
5 NAME@[3; 7)
6 IDENT@[3; 7) "main"
7 PARAM_LIST@[7; 9)
8 L_PAREN@[7; 8) "("
9 R_PAREN@[8; 9) ")"
10 WHITESPACE@[9; 10) " "
11 BLOCK_EXPR@[10; 129)
12 BLOCK@[10; 129)
13 L_CURLY@[10; 11) "{"
14 WHITESPACE@[11; 16) "\n "
15 MATCH_EXPR@[16; 127)
16 MATCH_KW@[16; 21) "match"
17 WHITESPACE@[21; 22) " "
18 TUPLE_EXPR@[22; 24)
19 L_PAREN@[22; 23) "("
20 R_PAREN@[23; 24) ")"
21 WHITESPACE@[24; 25) " "
22 MATCH_ARM_LIST@[25; 127)
23 L_CURLY@[25; 26) "{"
24 WHITESPACE@[26; 35) "\n "
25 MATCH_ARM@[35; 48)
26 PAREN_PAT@[35; 42)
27 L_PAREN@[35; 36) "("
28 OR_PAT@[36; 41)
29 PLACEHOLDER_PAT@[36; 37)
30 UNDERSCORE@[36; 37) "_"
31 WHITESPACE@[37; 38) " "
32 PIPE@[38; 39) "|"
33 WHITESPACE@[39; 40) " "
34 PLACEHOLDER_PAT@[40; 41)
35 UNDERSCORE@[40; 41) "_"
36 R_PAREN@[41; 42) ")"
37 WHITESPACE@[42; 43) " "
38 FAT_ARROW@[43; 45) "=>"
39 WHITESPACE@[45; 46) " "
40 TUPLE_EXPR@[46; 48)
41 L_PAREN@[46; 47) "("
42 R_PAREN@[47; 48) ")"
43 COMMA@[48; 49) ","
44 WHITESPACE@[49; 58) "\n "
45 MATCH_ARM@[58; 72)
46 REF_PAT@[58; 66)
47 AMP@[58; 59) "&"
48 PAREN_PAT@[59; 66)
49 L_PAREN@[59; 60) "("
50 OR_PAT@[60; 65)
51 PLACEHOLDER_PAT@[60; 61)
52 UNDERSCORE@[60; 61) "_"
53 WHITESPACE@[61; 62) " "
54 PIPE@[62; 63) "|"
55 WHITESPACE@[63; 64) " "
56 PLACEHOLDER_PAT@[64; 65)
57 UNDERSCORE@[64; 65) "_"
58 R_PAREN@[65; 66) ")"
59 WHITESPACE@[66; 67) " "
60 FAT_ARROW@[67; 69) "=>"
61 WHITESPACE@[69; 70) " "
62 TUPLE_EXPR@[70; 72)
63 L_PAREN@[70; 71) "("
64 R_PAREN@[71; 72) ")"
65 COMMA@[72; 73) ","
66 WHITESPACE@[73; 82) "\n "
67 MATCH_ARM@[82; 96)
68 TUPLE_PAT@[82; 90)
69 L_PAREN@[82; 83) "("
70 OR_PAT@[83; 88)
71 PLACEHOLDER_PAT@[83; 84)
72 UNDERSCORE@[83; 84) "_"
73 WHITESPACE@[84; 85) " "
74 PIPE@[85; 86) "|"
75 WHITESPACE@[86; 87) " "
76 PLACEHOLDER_PAT@[87; 88)
77 UNDERSCORE@[87; 88) "_"
78 COMMA@[88; 89) ","
79 R_PAREN@[89; 90) ")"
80 WHITESPACE@[90; 91) " "
81 FAT_ARROW@[91; 93) "=>"
82 WHITESPACE@[93; 94) " "
83 TUPLE_EXPR@[94; 96)
84 L_PAREN@[94; 95) "("
85 R_PAREN@[95; 96) ")"
86 COMMA@[96; 97) ","
87 WHITESPACE@[97; 106) "\n "
88 MATCH_ARM@[106; 120)
89 SLICE_PAT@[106; 114)
90 L_BRACK@[106; 107) "["
91 OR_PAT@[107; 112)
92 PLACEHOLDER_PAT@[107; 108)
93 UNDERSCORE@[107; 108) "_"
94 WHITESPACE@[108; 109) " "
95 PIPE@[109; 110) "|"
96 WHITESPACE@[110; 111) " "
97 PLACEHOLDER_PAT@[111; 112)
98 UNDERSCORE@[111; 112) "_"
99 COMMA@[112; 113) ","
100 R_BRACK@[113; 114) "]"
101 WHITESPACE@[114; 115) " "
102 FAT_ARROW@[115; 117) "=>"
103 WHITESPACE@[117; 118) " "
104 TUPLE_EXPR@[118; 120)
105 L_PAREN@[118; 119) "("
106 R_PAREN@[119; 120) ")"
107 COMMA@[120; 121) ","
108 WHITESPACE@[121; 126) "\n "
109 R_CURLY@[126; 127) "}"
110 WHITESPACE@[127; 128) "\n"
111 R_CURLY@[128; 129) "}"
112 WHITESPACE@[129; 130) "\n"
diff --git a/crates/ra_text_edit/src/lib.rs b/crates/ra_text_edit/src/lib.rs
index 5f1b12222..37f23d043 100644
--- a/crates/ra_text_edit/src/lib.rs
+++ b/crates/ra_text_edit/src/lib.rs
@@ -29,8 +29,8 @@ impl AtomTextEdit {
29 } 29 }
30 30
31 pub fn apply(&self, mut text: String) -> String { 31 pub fn apply(&self, mut text: String) -> String {
32 let start = u32::from(self.delete.start()) as usize; 32 let start = self.delete.start().to_usize();
33 let end = u32::from(self.delete.end()) as usize; 33 let end = self.delete.end().to_usize();
34 text.replace_range(start..end, &self.insert); 34 text.replace_range(start..end, &self.insert);
35 text 35 text
36 } 36 }
diff --git a/crates/ra_text_edit/src/text_edit.rs b/crates/ra_text_edit/src/text_edit.rs
index 413c7d782..3291ada42 100644
--- a/crates/ra_text_edit/src/text_edit.rs
+++ b/crates/ra_text_edit/src/text_edit.rs
@@ -66,13 +66,13 @@ impl TextEdit {
66 let mut total_len = text.len(); 66 let mut total_len = text.len();
67 for atom in self.atoms.iter() { 67 for atom in self.atoms.iter() {
68 total_len += atom.insert.len(); 68 total_len += atom.insert.len();
69 total_len -= u32::from(atom.delete.end() - atom.delete.start()) as usize; 69 total_len -= (atom.delete.end() - atom.delete.start()).to_usize();
70 } 70 }
71 let mut buf = String::with_capacity(total_len); 71 let mut buf = String::with_capacity(total_len);
72 let mut prev = 0; 72 let mut prev = 0;
73 for atom in self.atoms.iter() { 73 for atom in self.atoms.iter() {
74 let start = u32::from(atom.delete.start()) as usize; 74 let start = atom.delete.start().to_usize();
75 let end = u32::from(atom.delete.end()) as usize; 75 let end = atom.delete.end().to_usize();
76 if start > prev { 76 if start > prev {
77 buf.push_str(&text[prev..start]); 77 buf.push_str(&text[prev..start]);
78 } 78 }