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 {