aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md20
-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.rs53
-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/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.rs24
-rw-r--r--crates/ra_hir_ty/src/infer/pat.rs7
-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/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_lsp_server/src/main_loop/handlers.rs76
-rw-r--r--crates/ra_parser/src/syntax_kind/generated.rs2
-rw-r--r--crates/ra_syntax/Cargo.toml2
-rw-r--r--crates/ra_syntax/src/ast/generated.rs2
-rw-r--r--docs/dev/README.md12
-rw-r--r--docs/user/README.md18
-rw-r--r--docs/user/assists.md28
-rw-r--r--editors/emacs/rust-analyzer.el295
-rw-r--r--xtask/src/lib.rs3
44 files changed, 1463 insertions, 1333 deletions
diff --git a/README.md b/README.md
index 2f6ed1e05..fabb8479d 100644
--- a/README.md
+++ b/README.md
@@ -2,13 +2,13 @@
2 <img src="https://user-images.githubusercontent.com/1711539/72443316-5a79f280-37ae-11ea-858f-035209ece2dd.png" alt="rust-analyzer logo"> 2 <img src="https://user-images.githubusercontent.com/1711539/72443316-5a79f280-37ae-11ea-858f-035209ece2dd.png" alt="rust-analyzer logo">
3</p> 3</p>
4 4
5Rust Analyzer is an **experimental** modular compiler frontend for the Rust 5rust-analyzer is an **experimental** modular compiler frontend for the Rust
6language. It is a part of a larger rls-2.0 effort to create excellent IDE 6language. It is a part of a larger rls-2.0 effort to create excellent IDE
7support for Rust. If you want to get involved, check the rls-2.0 working group: 7support for Rust. If you want to get involved, check the rls-2.0 working group:
8 8
9https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0 9https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0
10 10
11Work on the Rust Analyzer is sponsored by 11Work on rust-analyzer is sponsored by
12 12
13[<img src="https://user-images.githubusercontent.com/1711539/58105231-cf306900-7bee-11e9-83d8-9f1102e59d29.png" alt="Ferrous Systems" width="300">](https://ferrous-systems.com/) 13[<img src="https://user-images.githubusercontent.com/1711539/58105231-cf306900-7bee-11e9-83d8-9f1102e59d29.png" alt="Ferrous Systems" width="300">](https://ferrous-systems.com/)
14- [Mozilla](https://www.mozilla.org/en-US/) 14- [Mozilla](https://www.mozilla.org/en-US/)
@@ -16,17 +16,17 @@ Work on the Rust Analyzer is sponsored by
16 16
17## Language Server Quick Start 17## Language Server Quick Start
18 18
19Rust Analyzer is a work-in-progress, so you'll have to build it from source, and 19rust-analyzer is a work-in-progress, so you might encounter critical bugs. That
20you might encounter critical bugs. That said, it is complete enough to provide a 20said, it is complete enough to provide a useful IDE experience and some people
21useful IDE experience and some people use it as a daily driver. 21use it as a daily driver.
22 22
23To build rust-analyzer, you need: 23To build rust-analyzer, you need:
24 24
25* latest stable rust for language server itself 25* latest stable Rust for the language server itself
26* latest stable npm and VS Code for VS Code extension 26* latest stable npm and VS Code for VS Code extension
27 27
28To quickly install rust-analyzer with VS Code extension with standard setup 28To quickly install the rust-analyzer language server and VS Code extension with
29(`code` and `cargo` in `$PATH`, etc), use this: 29standard setup (`code` and `cargo` in `$PATH`, etc), use this:
30 30
31``` 31```
32# clone the repo 32# clone the repo
@@ -44,8 +44,8 @@ cannot start, see [./docs/user](./docs/user).
44 44
45## Documentation 45## Documentation
46 46
47If you want to **contribute** to rust-analyzer or just curious about how things work 47If you want to **contribute** to rust-analyzer or are just curious about how
48under the hood, check the [./docs/dev](./docs/dev) folder. 48things work under the hood, check the [./docs/dev](./docs/dev) folder.
49 49
50If you want to **use** rust-analyzer's language server with your editor of 50If you want to **use** rust-analyzer's language server with your editor of
51choice, check [./docs/user](./docs/user) folder. It also contains some tips & tricks to help 51choice, check [./docs/user](./docs/user) folder. It also contains some tips & tricks to help
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..e88c121eb 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
@@ -67,24 +63,24 @@ pub(crate) fn auto_import(ctx: AssistCtx) -> Option<Assist> {
67 return None; 63 return None;
68 } 64 }
69 65
70 ctx.add_assist_group(AssistId("auto_import"), format!("Import {}", name_to_import), || { 66 let mut group = ctx.add_assist_group(format!("Import {}", name_to_import));
71 proposed_imports 67 for import in proposed_imports {
72 .into_iter() 68 group.add_assist(AssistId("auto_import"), format!("Import `{}`", &import), |edit| {
73 .map(|import| import_to_action(import, &position, &path_to_import_syntax)) 69 edit.target(path_to_import_syntax.text_range());
74 .collect() 70 insert_use_statement(
75 }) 71 &position,
76} 72 path_to_import_syntax,
77 73 &import,
78fn import_to_action(import: ModPath, position: &SyntaxNode, anchor: &SyntaxNode) -> ActionBuilder { 74 edit.text_edit_builder(),
79 let mut action_builder = ActionBuilder::default(); 75 );
80 action_builder.label(format!("Import `{}`", &import)); 76 });
81 auto_import_text_edit(position, anchor, &import, action_builder.text_edit_builder()); 77 }
82 action_builder 78 group.finish()
83} 79}
84 80
85#[cfg(test)] 81#[cfg(test)]
86mod tests { 82mod tests {
87 use crate::helpers::{check_assist, check_assist_not_applicable}; 83 use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target};
88 84
89 use super::*; 85 use super::*;
90 86
@@ -255,4 +251,19 @@ mod tests {
255 ", 251 ",
256 ); 252 );
257 } 253 }
254
255 #[test]
256 fn auto_import_target() {
257 check_assist_target(
258 auto_import,
259 r"
260 struct AssistInfo {
261 group_label: Option<<|>GroupLabel>,
262 }
263
264 mod m { pub struct GroupLabel; }
265 ",
266 "GroupLabel",
267 )
268 }
258} 269}
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/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..3c9c02d03 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};
@@ -236,8 +236,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
236 self.result.record_field_resolutions.insert(field.expr, field_def); 236 self.result.record_field_resolutions.insert(field.expr, field_def);
237 } 237 }
238 let field_ty = field_def 238 let field_ty = field_def
239 .map_or(Ty::Unknown, |it| field_types[it.local_id].clone()) 239 .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)); 240 self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty));
242 } 241 }
243 if let Some(expr) = spread { 242 if let Some(expr) = spread {
@@ -588,10 +587,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
588 self.write_method_resolution(tgt_expr, func); 587 self.write_method_resolution(tgt_expr, func);
589 (ty, self.db.value_ty(func.into()), Some(generics(self.db, func.into()))) 588 (ty, self.db.value_ty(func.into()), Some(generics(self.db, func.into())))
590 } 589 }
591 None => (receiver_ty, Ty::Unknown, None), 590 None => (receiver_ty, Binders::new(0, Ty::Unknown), None),
592 }; 591 };
593 let substs = self.substs_for_method_call(def_generics, generic_args, &derefed_receiver_ty); 592 let substs = self.substs_for_method_call(def_generics, generic_args, &derefed_receiver_ty);
594 let method_ty = method_ty.apply_substs(substs); 593 let method_ty = method_ty.subst(&substs);
595 let method_ty = self.insert_type_vars(method_ty); 594 let method_ty = self.insert_type_vars(method_ty);
596 self.register_obligations_for_call(&method_ty); 595 self.register_obligations_for_call(&method_ty);
597 let (expected_receiver_ty, param_tys, ret_ty) = match method_ty.callable_sig(self.db) { 596 let (expected_receiver_ty, param_tys, ret_ty) = match method_ty.callable_sig(self.db) {
@@ -635,7 +634,6 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
635 continue; 634 continue;
636 } 635 }
637 636
638 let param_ty = self.insert_vars_for_impl_trait(param_ty);
639 let param_ty = self.normalize_associated_types_in(param_ty); 637 let param_ty = self.normalize_associated_types_in(param_ty);
640 self.infer_expr_coerce(arg, &Expectation::has_type(param_ty.clone())); 638 self.infer_expr_coerce(arg, &Expectation::has_type(param_ty.clone()));
641 } 639 }
@@ -648,13 +646,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
648 generic_args: Option<&GenericArgs>, 646 generic_args: Option<&GenericArgs>,
649 receiver_ty: &Ty, 647 receiver_ty: &Ty,
650 ) -> Substs { 648 ) -> Substs {
651 let (total_len, _parent_len, child_len) = 649 let (parent_params, self_params, type_params, impl_trait_params) =
652 def_generics.as_ref().map_or((0, 0, 0), |g| g.len_split()); 650 def_generics.as_ref().map_or((0, 0, 0, 0), |g| g.provenance_split());
651 assert_eq!(self_params, 0); // method shouldn't have another Self param
652 let total_len = parent_params + type_params + impl_trait_params;
653 let mut substs = Vec::with_capacity(total_len); 653 let mut substs = Vec::with_capacity(total_len);
654 // Parent arguments are unknown, except for the receiver type 654 // Parent arguments are unknown, except for the receiver type
655 if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) { 655 if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) {
656 for (_id, param) in parent_generics { 656 for (_id, param) in parent_generics {
657 if param.name == name![Self] { 657 if param.provenance == hir_def::generics::TypeParamProvenance::TraitSelf {
658 substs.push(receiver_ty.clone()); 658 substs.push(receiver_ty.clone());
659 } else { 659 } else {
660 substs.push(Ty::Unknown); 660 substs.push(Ty::Unknown);
@@ -664,7 +664,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
664 // handle provided type arguments 664 // handle provided type arguments
665 if let Some(generic_args) = generic_args { 665 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 666 // 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) { 667 for arg in generic_args.args.iter().take(type_params) {
668 match arg { 668 match arg {
669 GenericArg::Type(type_ref) => { 669 GenericArg::Type(type_ref) => {
670 let ty = self.make_ty(type_ref); 670 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..e7283f24c 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 }
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/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_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index 282f6e8fc..65e8bc856 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,
@@ -685,34 +686,53 @@ pub fn handle_code_action(
685 res.push(fix.action.clone()); 686 res.push(fix.action.clone());
686 } 687 }
687 688
689 let mut groups = FxHashMap::default();
688 for assist in world.analysis().assists(FileRange { file_id, range })?.into_iter() { 690 for assist in world.analysis().assists(FileRange { file_id, range })?.into_iter() {
689 let title = assist.label.clone(); 691 let arg = to_value(assist.source_change.try_conv_with(&world)?)?;
692
693 let (command, title, arg) = match assist.group_label {
694 None => ("rust-analyzer.applySourceChange", assist.label.clone(), arg),
695
696 // Group all assists with the same `group_label` into a single CodeAction.
697 Some(group_label) => {
698 match groups.entry(group_label.clone()) {
699 Entry::Occupied(entry) => {
700 let idx: usize = *entry.get();
701 match &mut res[idx] {
702 CodeActionOrCommand::CodeAction(CodeAction {
703 command: Some(Command { arguments: Some(arguments), .. }),
704 ..
705 }) => match arguments.as_mut_slice() {
706 [serde_json::Value::Array(arguments)] => arguments.push(arg),
707 _ => panic!("invalid group"),
708 },
709 _ => panic!("invalid group"),
710 }
711 continue;
712 }
713 Entry::Vacant(entry) => {
714 entry.insert(res.len());
715 }
716 }
717 ("rust-analyzer.selectAndApplySourceChange", group_label, to_value(vec![arg])?)
718 }
719 };
690 720
691 let command = match assist.change_data { 721 let command = Command {
692 Either::Left(change) => Command { 722 title: assist.label.clone(),
693 title, 723 command: command.to_string(),
694 command: "rust-analyzer.applySourceChange".to_string(), 724 arguments: Some(vec![arg]),
695 arguments: Some(vec![to_value(change.try_conv_with(&world)?)?]), 725 };
696 }, 726
697 Either::Right(changes) => Command { 727 let kind = match assist.id {
698 title, 728 AssistId("introduce_variable") => Some("refactor.extract.variable".to_string()),
699 command: "rust-analyzer.selectAndApplySourceChange".to_string(), 729 AssistId("add_custom_impl") => Some("refactor.rewrite.add_custom_impl".to_string()),
700 arguments: Some(vec![to_value( 730 _ => None,
701 changes
702 .into_iter()
703 .map(|change| change.try_conv_with(&world))
704 .collect::<Result<Vec<_>>>()?,
705 )?]),
706 },
707 }; 731 };
708 732
709 let action = CodeAction { 733 let action = CodeAction {
710 title: command.title.clone(), 734 title,
711 kind: match assist.id { 735 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, 736 diagnostics: None,
717 edit: None, 737 edit: None,
718 command: Some(command), 738 command: Some(command),
diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs
index 4b301d67a..e27b27ffa 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`."]
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 33d5578e7..435135f92 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},
diff --git a/docs/dev/README.md b/docs/dev/README.md
index d30727786..732e4bdd3 100644
--- a/docs/dev/README.md
+++ b/docs/dev/README.md
@@ -43,7 +43,7 @@ https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0
43 43
44We use GitHub Actions for CI. Most of the things, including formatting, are checked by 44We use GitHub Actions for CI. Most of the things, including formatting, are checked by
45`cargo test` so, if `cargo test` passes locally, that's a good sign that CI will 45`cargo test` so, if `cargo test` passes locally, that's a good sign that CI will
46be green as well. The only exception is that long-running by default a skipped locally. 46be green as well. The only exception is that some long-running tests are skipped locally by default.
47Use `env RUN_SLOW_TESTS=1 cargo test` to run the full suite. 47Use `env RUN_SLOW_TESTS=1 cargo test` to run the full suite.
48 48
49We use bors-ng to enforce the [not rocket science](https://graydon2.dreamwidth.org/1597.html) rule. 49We use bors-ng to enforce the [not rocket science](https://graydon2.dreamwidth.org/1597.html) rule.
@@ -54,9 +54,9 @@ You can run `cargo xtask install-pre-commit-hook` to install git-hook to run rus
54 54
55All Rust code lives in the `crates` top-level directory, and is organized as a 55All Rust code lives in the `crates` top-level directory, and is organized as a
56single Cargo workspace. The `editors` top-level directory contains code for 56single Cargo workspace. The `editors` top-level directory contains code for
57integrating with editors. Currently, it contains plugins for VS Code (in 57integrating with editors. Currently, it contains the plugin for VS Code (in
58typescript) and Emacs (in elisp). The `docs` top-level directory contains both 58typescript). The `docs` top-level directory contains both developer and user
59developer and user documentation. 59documentation.
60 60
61We have some automation infra in Rust in the `xtask` package. It contains 61We have some automation infra in Rust in the `xtask` package. It contains
62stuff like formatting checking, code generation and powers `cargo xtask install`. 62stuff like formatting checking, code generation and powers `cargo xtask install`.
@@ -107,8 +107,8 @@ If I need to fix something simultaneously in the server and in the client, I
107feel even more sad. I don't have a specific workflow for this case. 107feel even more sad. I don't have a specific workflow for this case.
108 108
109Additionally, I use `cargo run --release -p ra_cli -- analysis-stats 109Additionally, I use `cargo run --release -p ra_cli -- analysis-stats
110path/to/some/rust/crate` to run a batch analysis. This is primaraly useful for 110path/to/some/rust/crate` to run a batch analysis. This is primarily useful for
111performance optimiations, or for bug minimization. 111performance optimizations, or for bug minimization.
112 112
113# Logging 113# Logging
114 114
diff --git a/docs/user/README.md b/docs/user/README.md
index 082dadd76..3da30a193 100644
--- a/docs/user/README.md
+++ b/docs/user/README.md
@@ -5,8 +5,7 @@ install lsp server, clone the repository and then run `cargo xtask install
5./crates/ra_lsp_server`). This will produce a binary named `ra_lsp_server` which 5./crates/ra_lsp_server`). This will produce a binary named `ra_lsp_server` which
6you should be able to use it with any LSP-compatible editor. We use custom 6you should be able to use it with any LSP-compatible editor. We use custom
7extensions to LSP, so special client-side support is required to take full 7extensions to LSP, so special client-side support is required to take full
8advantage of rust-analyzer. This repository contains support code for VS Code 8advantage of rust-analyzer. This repository contains support code for VS Code.
9and Emacs.
10 9
11``` 10```
12$ git clone [email protected]:rust-analyzer/rust-analyzer && cd rust-analyzer 11$ git clone [email protected]:rust-analyzer/rust-analyzer && cd rust-analyzer
@@ -162,17 +161,12 @@ host.
162 161
163## Emacs 162## Emacs
164 163
165Prerequisites: 164* install recent version of `emacs-lsp` package by following the instructions [here][emacs-lsp]
166 165* set `lsp-rust-server` to `'rust-analyzer`
167`emacs-lsp`, `dash` and `ht` packages. 166* run `lsp` in a Rust buffer
168 167* (Optionally) bind commands like `lsp-rust-analyzer-join-lines`, `lsp-extend-selection` and `lsp-rust-analyzer-expand-macro` to keys
169Installation:
170 168
171* add 169[emacs-lsp]: https://github.com/emacs-lsp/lsp-mode
172[rust-analyzer.el](../../editors/emacs/rust-analyzer.el)
173to load path and require it in `init.el`
174* run `lsp` in a rust buffer
175* (Optionally) bind commands like `rust-analyzer-join-lines`, `rust-analyzer-extend-selection` and `rust-analyzer-expand-macro` to keys, and enable `rust-analyzer-inlay-hints-mode` to get inline type hints
176 170
177 171
178## Vim and NeoVim (coc-rust-analyzer) 172## Vim and NeoVim (coc-rust-analyzer)
diff --git a/docs/user/assists.md b/docs/user/assists.md
index 1e2dd7485..f737a2fa4 100644
--- a/docs/user/assists.md
+++ b/docs/user/assists.md
@@ -154,20 +154,6 @@ impl Trait<u32> for () {
154} 154}
155``` 155```
156 156
157## `add_import`
158
159Adds a use statement for a given fully-qualified path.
160
161```rust
162// BEFORE
163fn process(map: std::collections::┃HashMap<String, String>) {}
164
165// AFTER
166use std::collections::HashMap;
167
168fn process(map: HashMap<String, String>) {}
169```
170
171## `add_new` 157## `add_new`
172 158
173Adds a new inherent impl for a type. 159Adds a new inherent impl for a type.
@@ -568,6 +554,20 @@ fn handle(action: Action) {
568} 554}
569``` 555```
570 556
557## `replace_qualified_name_with_use`
558
559Adds a use statement for a given fully-qualified name.
560
561```rust
562// BEFORE
563fn process(map: std::collections::┃HashMap<String, String>) {}
564
565// AFTER
566use std::collections::HashMap;
567
568fn process(map: HashMap<String, String>) {}
569```
570
571## `split_import` 571## `split_import`
572 572
573Wraps the tail of import into braces. 573Wraps the tail of import into braces.
diff --git a/editors/emacs/rust-analyzer.el b/editors/emacs/rust-analyzer.el
deleted file mode 100644
index 9b426fcae..000000000
--- a/editors/emacs/rust-analyzer.el
+++ /dev/null
@@ -1,295 +0,0 @@
1;;; rust-analyzer.el --- Rust analyzer emacs bindings for emacs-lsp -*- lexical-binding: t; -*-
2;;; Code:
3
4(require 'lsp)
5(require 'dash)
6(require 'ht)
7
8;; This currently
9;; - sets up rust-analyzer with emacs-lsp, giving
10;; - code actions
11;; - completion (use company-lsp for proper snippet support)
12;; - imenu support
13;; - on-type formatting
14;; - 'hover' type information & documentation (with lsp-ui)
15;; - implements source changes (for code actions etc.), except for file system changes
16;; - implements joinLines (you need to bind rust-analyzer-join-lines to a key)
17;; - implements selectionRanges (either bind lsp-extend-selection to a key, or use expand-region)
18;; - provides rust-analyzer-inlay-hints-mode for inline type hints
19;; - provides rust-analyzer-expand-macro to expand macros
20
21;; What's missing:
22;; - file system changes in apply-source-change
23;; - semantic highlighting
24;; - onEnter, parentModule, findMatchingBrace
25;; - runnables
26;; - the debugging commands (syntaxTree and analyzerStatus)
27;; - more
28
29;; Also, there's a problem with company-lsp's caching being too eager, sometimes
30;; resulting in outdated completions.
31
32(defcustom rust-analyzer-command '("ra_lsp_server")
33 ""
34 :type '(repeat (string)))
35
36(defconst rust-analyzer--notification-handlers
37 '(("rust-analyzer/publishDecorations" . (lambda (_w _p)))))
38
39(defconst rust-analyzer--action-handlers
40 '(("rust-analyzer.applySourceChange" .
41 (lambda (p) (rust-analyzer--apply-source-change-command p)))
42 ("rust-analyzer.selectAndApplySourceChange" .
43 (lambda (p) (rust-analyzer--select-and-apply-source-change-command p)))))
44
45(defun rust-analyzer--uri-filename (text-document)
46 (lsp--uri-to-path (gethash "uri" text-document)))
47
48(defun rust-analyzer--goto-lsp-loc (loc)
49 (-let (((&hash "line" "character") loc))
50 (goto-line (1+ line))
51 (move-to-column character)))
52
53(defun rust-analyzer--apply-text-document-edit (edit)
54 "Like lsp--apply-text-document-edit, but it allows nil version."
55 (let* ((ident (gethash "textDocument" edit))
56 (filename (rust-analyzer--uri-filename ident))
57 (version (gethash "version" ident)))
58 (with-current-buffer (find-file-noselect filename)
59 (when (or (not version) (= version (lsp--cur-file-version)))
60 (lsp--apply-text-edits (gethash "edits" edit))))))
61
62(defun rust-analyzer--apply-source-change (data)
63 ;; TODO fileSystemEdits
64 (seq-doseq (it (-> data (ht-get "workspaceEdit") (ht-get "documentChanges")))
65 (rust-analyzer--apply-text-document-edit it))
66 (-when-let (cursor-position (ht-get data "cursorPosition"))
67 (let ((filename (rust-analyzer--uri-filename (ht-get cursor-position "textDocument")))
68 (position (ht-get cursor-position "position")))
69 (find-file filename)
70 (rust-analyzer--goto-lsp-loc position))))
71
72(defun rust-analyzer--apply-source-change-command (p)
73 (let ((data (-> p (ht-get "arguments") (lsp-seq-first))))
74 (rust-analyzer--apply-source-change data)))
75
76(defun rust-analyzer--select-and-apply-source-change-command (p)
77 (let* ((options (-> p (ht-get "arguments") (lsp-seq-first)))
78 (chosen-option (lsp--completing-read "Select option:" options
79 (-lambda ((&hash "label")) label))))
80 (rust-analyzer--apply-source-change chosen-option)))
81
82(lsp-register-client
83 (make-lsp-client
84 :new-connection (lsp-stdio-connection (lambda () rust-analyzer-command))
85 :notification-handlers (ht<-alist rust-analyzer--notification-handlers)
86 :action-handlers (ht<-alist rust-analyzer--action-handlers)
87 :major-modes '(rust-mode)
88 :ignore-messages nil
89 :server-id 'rust-analyzer))
90
91(defun rust-analyzer--initialized? ()
92 (when-let ((workspace (lsp-find-workspace 'rust-analyzer (buffer-file-name))))
93 (eq 'initialized (lsp--workspace-status workspace))))
94
95(with-eval-after-load 'company-lsp
96 ;; company-lsp provides a snippet handler for rust by default that adds () after function calls, which RA does better
97 (setq company-lsp--snippet-functions (cl-delete "rust" company-lsp--snippet-functions :key #'car :test #'equal)))
98
99;; join lines
100
101(defun rust-analyzer--join-lines-params ()
102 "Join lines params."
103 (list :textDocument (lsp--text-document-identifier)
104 :range (if (use-region-p)
105 (lsp--region-to-range (region-beginning) (region-end))
106 (lsp--region-to-range (point) (point)))))
107
108(defun rust-analyzer-join-lines ()
109 (interactive)
110 (->
111 (lsp-send-request (lsp-make-request "rust-analyzer/joinLines"
112 (rust-analyzer--join-lines-params)))
113 (rust-analyzer--apply-source-change)))
114
115;; selection ranges
116
117(defun rust-analyzer--add-er-expansion ()
118 (make-variable-buffer-local 'er/try-expand-list)
119 (setq er/try-expand-list (append
120 er/try-expand-list
121 '(lsp-extend-selection))))
122
123(with-eval-after-load 'expand-region
124 ;; add the expansion for all existing rust-mode buffers. If expand-region is
125 ;; loaded lazily, it might be loaded when the first rust buffer is opened, and
126 ;; then it's too late for the hook for that buffer
127 (dolist (buf (buffer-list))
128 (with-current-buffer buf
129 (when (eq 'rust-mode major-mode)
130 (rust-analyzer--add-er-expansion))))
131 (add-hook 'rust-mode-hook 'rust-analyzer--add-er-expansion))
132
133;; runnables
134(defvar rust-analyzer--last-runnable nil)
135
136(defun rust-analyzer--runnables-params ()
137 (list :textDocument (lsp--text-document-identifier)
138 :position (lsp--cur-position)))
139
140(defun rust-analyzer--runnables ()
141 (lsp-send-request (lsp-make-request "rust-analyzer/runnables"
142 (rust-analyzer--runnables-params))))
143
144(defun rust-analyzer--select-runnable ()
145 (lsp--completing-read
146 "Select runnable:"
147 (if rust-analyzer--last-runnable
148 (cons rust-analyzer--last-runnable (rust-analyzer--runnables))
149 (rust-analyzer--runnables))
150 (-lambda ((&hash "label")) label)))
151
152(defun rust-analyzer-run (runnable)
153 (interactive (list (rust-analyzer--select-runnable)))
154 (-let* (((&hash "env" "bin" "args" "label") runnable)
155 (compilation-environment (-map (-lambda ((k v)) (concat k "=" v)) (ht-items env))))
156 (compilation-start
157 (string-join (append (list bin) args '()) " ")
158 ;; cargo-process-mode is nice, but try to work without it...
159 (if (functionp 'cargo-process-mode) 'cargo-process-mode nil)
160 (lambda (_) (concat "*" label "*")))
161 (setq rust-analyzer--last-runnable runnable)))
162
163(defun rust-analyzer-rerun (&optional runnable)
164 (interactive (list (or rust-analyzer--last-runnable
165 (rust-analyzer--select-runnable))))
166 (rust-analyzer-run (or runnable rust-analyzer--last-runnable)))
167
168;; analyzer status buffer
169(define-derived-mode rust-analyzer-status-mode special-mode "Rust-Analyzer-Status"
170 "Mode for the rust-analyzer status buffer.")
171
172(defvar-local rust-analyzer--status-buffer-workspace nil)
173
174(defun rust-analyzer-status ()
175 "Displays status information for rust-analyzer."
176 (interactive)
177 (let* ((workspace (lsp-find-workspace 'rust-analyzer (buffer-file-name)))
178 (buf (get-buffer-create (concat "*rust-analyzer status " (with-lsp-workspace workspace (lsp-workspace-root)) "*"))))
179 (with-current-buffer buf
180 (rust-analyzer-status-mode)
181 (setq rust-analyzer--status-buffer-workspace workspace)
182 (rust-analyzer-status-buffer-refresh))
183 (pop-to-buffer buf)))
184
185(defun rust-analyzer-status-buffer-refresh ()
186 (interactive)
187 (when rust-analyzer--status-buffer-workspace
188 (let ((inhibit-read-only t))
189 (erase-buffer)
190 (insert (with-lsp-workspace rust-analyzer--status-buffer-workspace
191 (lsp-send-request (lsp-make-request
192 "rust-analyzer/analyzerStatus")))))))
193
194
195(defun rust-analyzer--syntax-tree-params ()
196 "Syntax tree params."
197 (list :textDocument (lsp--text-document-identifier)
198 :range (if (use-region-p)
199 (lsp--region-to-range (region-beginning) (region-end))
200 (lsp--region-to-range (point-min) (point-max)))))
201
202(defun rust-analyzer-syntax-tree ()
203 "Displays syntax tree for current buffer."
204 (interactive)
205 (when (eq 'rust-mode major-mode)
206 (let* ((workspace (lsp-find-workspace 'rust-analyzer (buffer-file-name)))
207 (buf (get-buffer-create (concat "*rust-analyzer syntax tree " (with-lsp-workspace workspace (lsp-workspace-root)) "*"))))
208 (when workspace
209 (let ((parse-result (with-lsp-workspace workspace
210 (lsp-send-request (lsp-make-request
211 "rust-analyzer/syntaxTree"
212 (rust-analyzer--syntax-tree-params))))))
213 (with-current-buffer buf
214 (let ((inhibit-read-only t))
215 (erase-buffer)
216 (insert parse-result)))
217 (pop-to-buffer buf))))))
218
219;; inlay hints
220(defun rust-analyzer--update-inlay-hints (buffer)
221 (if (and (rust-analyzer--initialized?) (eq buffer (current-buffer)))
222 (lsp-request-async
223 "rust-analyzer/inlayHints"
224 (list :textDocument (lsp--text-document-identifier))
225 (lambda (res)
226 (remove-overlays (point-min) (point-max) 'rust-analyzer--inlay-hint t)
227 (dolist (hint res)
228 (-let* (((&hash "range" "label" "kind") hint)
229 ((beg . end) (lsp--range-to-region range))
230 (overlay (make-overlay beg end)))
231 (overlay-put overlay 'rust-analyzer--inlay-hint t)
232 (overlay-put overlay 'evaporate t)
233 (cond
234 ((string= kind "TypeHint")
235 (overlay-put overlay 'after-string (propertize (concat ": " label)
236 'font-lock-face 'font-lock-comment-face)))
237 ((string= kind "ParameterHint")
238 (overlay-put overlay 'before-string (propertize (concat label ": ")
239 'font-lock-face 'font-lock-comment-face)))
240 )
241 )))
242 :mode 'tick))
243 nil)
244
245(defvar-local rust-analyzer--inlay-hints-timer nil)
246
247(defun rust-analyzer--inlay-hints-change-handler (&rest rest)
248 (when rust-analyzer--inlay-hints-timer
249 (cancel-timer rust-analyzer--inlay-hints-timer))
250 (setq rust-analyzer--inlay-hints-timer
251 (run-with-idle-timer 0.1 nil #'rust-analyzer--update-inlay-hints (current-buffer))))
252
253(define-minor-mode rust-analyzer-inlay-hints-mode
254 "Mode for showing inlay hints."
255 nil nil nil
256 (cond
257 (rust-analyzer-inlay-hints-mode
258 (rust-analyzer--update-inlay-hints (current-buffer))
259 (add-hook 'lsp-after-initialize-hook #'rust-analyzer--inlay-hints-change-handler nil t)
260 (add-hook 'after-change-functions #'rust-analyzer--inlay-hints-change-handler nil t))
261 (t
262 (remove-overlays (point-min) (point-max) 'rust-analyzer--inlay-hint t)
263 (remove-hook 'lsp-after-initialize-hook #'rust-analyzer--inlay-hints-change-handler t)
264 (remove-hook 'after-change-functions #'rust-analyzer--inlay-hints-change-handler t))))
265
266
267
268;; expand macros
269(defun rust-analyzer-expand-macro ()
270 "Expands the macro call at point recursively."
271 (interactive)
272 (when (eq 'rust-mode major-mode)
273 (let* ((workspace (lsp-find-workspace 'rust-analyzer (buffer-file-name)))
274 (params (list :textDocument (lsp--text-document-identifier)
275 :position (lsp--cur-position))))
276 (when workspace
277 (let* ((response (with-lsp-workspace workspace
278 (lsp-send-request (lsp-make-request
279 "rust-analyzer/expandMacro"
280 params))))
281 (result (when response (ht-get response "expansion"))))
282 (if result
283 (let ((buf (get-buffer-create (concat "*rust-analyzer macro expansion " (with-lsp-workspace workspace (lsp-workspace-root)) "*"))))
284 (with-current-buffer buf
285 (let ((inhibit-read-only t))
286 (erase-buffer)
287 (insert result)
288 (setq buffer-read-only t)
289 (special-mode)))
290 (pop-to-buffer buf))
291 (message "No macro found at point, or it could not be expanded")))))))
292
293
294(provide 'rust-analyzer)
295;;; rust-analyzer.el ends here
diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs
index 9b0afe8e0..8fdf43e4a 100644
--- a/xtask/src/lib.rs
+++ b/xtask/src/lib.rs
@@ -53,8 +53,7 @@ fn reformat(text: impl std::fmt::Display) -> Result<String> {
53 write!(rustfmt.stdin.take().unwrap(), "{}", text)?; 53 write!(rustfmt.stdin.take().unwrap(), "{}", text)?;
54 let output = rustfmt.wait_with_output()?; 54 let output = rustfmt.wait_with_output()?;
55 let stdout = String::from_utf8(output.stdout)?; 55 let stdout = String::from_utf8(output.stdout)?;
56 // TODO: update the preable: replace ra_tools with the relevant path 56 let preamble = "Generated file, do not edit by hand, see `xtask/src/codegen`";
57 let preamble = "Generated file, do not edit by hand, see `crate/ra_tools/src/codegen`";
58 Ok(format!("//! {}\n\n{}", preamble, stdout)) 57 Ok(format!("//! {}\n\n{}", preamble, stdout))
59} 58}
60 59