aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/base_db/src/fixture.rs60
-rw-r--r--crates/hir/src/lib.rs8
-rw-r--r--crates/hir/src/source_analyzer.rs12
-rw-r--r--crates/hir_def/src/attr.rs66
-rw-r--r--crates/hir_def/src/db.rs15
-rw-r--r--crates/hir_def/src/item_scope.rs13
-rw-r--r--crates/hir_def/src/lib.rs8
-rw-r--r--crates/hir_def/src/nameres/collector.rs34
-rw-r--r--crates/hir_ty/src/autoderef.rs10
-rw-r--r--crates/hir_ty/src/infer.rs40
-rw-r--r--crates/hir_ty/src/infer/coerce.rs11
-rw-r--r--crates/hir_ty/src/infer/pat.rs6
-rw-r--r--crates/hir_ty/src/infer/unify.rs36
-rw-r--r--crates/hir_ty/src/lib.rs2
-rw-r--r--crates/hir_ty/src/method_resolution.rs54
-rw-r--r--crates/hir_ty/src/tests/method_resolution.rs22
-rw-r--r--crates/hir_ty/src/traits.rs16
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs118
-rw-r--r--crates/hir_ty/src/types.rs35
-rw-r--r--crates/ide/src/expand_macro.rs3
-rw-r--r--crates/ide_completion/src/completions/flyimport.rs43
-rw-r--r--crates/ide_db/src/apply_change.rs4
-rw-r--r--crates/test_utils/src/fixture.rs62
23 files changed, 421 insertions, 257 deletions
diff --git a/crates/base_db/src/fixture.rs b/crates/base_db/src/fixture.rs
index 8d4641355..04e2be390 100644
--- a/crates/base_db/src/fixture.rs
+++ b/crates/base_db/src/fixture.rs
@@ -1,62 +1,4 @@
1//! Fixtures are strings containing rust source code with optional metadata. 1//! A set of high-level utility fixture methods to use in tests.
2//! A fixture without metadata is parsed into a single source file.
3//! Use this to test functionality local to one file.
4//!
5//! Simple Example:
6//! ```
7//! r#"
8//! fn main() {
9//! println!("Hello World")
10//! }
11//! "#
12//! ```
13//!
14//! Metadata can be added to a fixture after a `//-` comment.
15//! The basic form is specifying filenames,
16//! which is also how to define multiple files in a single test fixture
17//!
18//! Example using two files in the same crate:
19//! ```
20//! "
21//! //- /main.rs
22//! mod foo;
23//! fn main() {
24//! foo::bar();
25//! }
26//!
27//! //- /foo.rs
28//! pub fn bar() {}
29//! "
30//! ```
31//!
32//! Example using two crates with one file each, with one crate depending on the other:
33//! ```
34//! r#"
35//! //- /main.rs crate:a deps:b
36//! fn main() {
37//! b::foo();
38//! }
39//! //- /lib.rs crate:b
40//! pub fn b() {
41//! println!("Hello World")
42//! }
43//! "#
44//! ```
45//!
46//! Metadata allows specifying all settings and variables
47//! that are available in a real rust project:
48//! - crate names via `crate:cratename`
49//! - dependencies via `deps:dep1,dep2`
50//! - configuration settings via `cfg:dbg=false,opt_level=2`
51//! - environment variables via `env:PATH=/bin,RUST_LOG=debug`
52//!
53//! Example using all available metadata:
54//! ```
55//! "
56//! //- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo
57//! fn insert_source_code_here() {}
58//! "
59//! ```
60use std::{mem, str::FromStr, sync::Arc}; 2use std::{mem, str::FromStr, sync::Arc};
61 3
62use cfg::CfgOptions; 4use cfg::CfgOptions;
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 8d00f7401..caa22dace 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -58,9 +58,8 @@ use hir_ty::{
58 subst_prefix, 58 subst_prefix,
59 traits::FnTrait, 59 traits::FnTrait,
60 AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, 60 AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast,
61 DebruijnIndex, InEnvironment, Interner, QuantifiedWhereClause, Scalar, Solution, 61 DebruijnIndex, InEnvironment, Interner, QuantifiedWhereClause, Scalar, Solution, Substitution,
62 SolutionVariables, Substitution, TraitEnvironment, Ty, TyBuilder, TyDefId, TyExt, TyKind, 62 TraitEnvironment, Ty, TyBuilder, TyDefId, TyExt, TyKind, TyVariableKind, WhereClause,
63 TyVariableKind, WhereClause,
64}; 63};
65use itertools::Itertools; 64use itertools::Itertools;
66use rustc_hash::FxHashSet; 65use rustc_hash::FxHashSet;
@@ -1822,8 +1821,9 @@ impl Type {
1822 ); 1821 );
1823 1822
1824 match db.trait_solve(self.krate, goal)? { 1823 match db.trait_solve(self.krate, goal)? {
1825 Solution::Unique(SolutionVariables(subst)) => subst 1824 Solution::Unique(s) => s
1826 .value 1825 .value
1826 .subst
1827 .interned() 1827 .interned()
1828 .first() 1828 .first()
1829 .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone())), 1829 .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone())),
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index c013e78d9..ce6f3c008 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -185,12 +185,16 @@ impl SourceAnalyzer {
185 185
186 pub(crate) fn resolve_record_pat_field( 186 pub(crate) fn resolve_record_pat_field(
187 &self, 187 &self,
188 _db: &dyn HirDatabase, 188 db: &dyn HirDatabase,
189 field: &ast::RecordPatField, 189 field: &ast::RecordPatField,
190 ) -> Option<Field> { 190 ) -> Option<Field> {
191 let pat_id = self.pat_id(&field.pat()?)?; 191 let field_name = field.field_name()?.as_name();
192 let struct_field = self.infer.as_ref()?.record_pat_field_resolution(pat_id)?; 192 let record_pat = ast::RecordPat::cast(field.syntax().parent().and_then(|p| p.parent())?)?;
193 Some(struct_field.into()) 193 let pat_id = self.pat_id(&record_pat.into())?;
194 let variant = self.infer.as_ref()?.variant_resolution_for_pat(pat_id)?;
195 let variant_data = variant.variant_data(db.upcast());
196 let field = FieldId { parent: variant, local_id: variant_data.field(&field_name)? };
197 Some(field.into())
194 } 198 }
195 199
196 pub(crate) fn resolve_macro_call( 200 pub(crate) fn resolve_macro_call(
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index ab77d924a..d9df7564d 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -16,7 +16,7 @@ use mbe::ast_to_token_tree;
16use smallvec::{smallvec, SmallVec}; 16use smallvec::{smallvec, SmallVec};
17use syntax::{ 17use syntax::{
18 ast::{self, AstNode, AttrsOwner}, 18 ast::{self, AstNode, AttrsOwner},
19 match_ast, AstToken, SmolStr, SyntaxNode, TextRange, TextSize, 19 match_ast, AstPtr, AstToken, SmolStr, SyntaxNode, TextRange, TextSize,
20}; 20};
21use tt::Subtree; 21use tt::Subtree;
22 22
@@ -215,12 +215,11 @@ impl Attrs {
215 let mut res = ArenaMap::default(); 215 let mut res = ArenaMap::default();
216 216
217 for (id, fld) in src.value.iter() { 217 for (id, fld) in src.value.iter() {
218 let attrs = match fld { 218 let owner: &dyn AttrsOwner = match fld {
219 Either::Left(_tuple) => Attrs::default(), 219 Either::Left(tuple) => tuple,
220 Either::Right(record) => { 220 Either::Right(record) => record,
221 RawAttrs::from_attrs_owner(db, src.with_value(record)).filter(db, krate)
222 }
223 }; 221 };
222 let attrs = RawAttrs::from_attrs_owner(db, src.with_value(owner)).filter(db, krate);
224 223
225 res.insert(id, attrs); 224 res.insert(id, attrs);
226 } 225 }
@@ -404,10 +403,14 @@ impl AttrsWithOwner {
404 return AttrSourceMap { attrs }; 403 return AttrSourceMap { attrs };
405 } 404 }
406 AttrDefId::FieldId(id) => { 405 AttrDefId::FieldId(id) => {
407 id.parent.child_source(db).map(|source| match &source[id.local_id] { 406 let map = db.fields_attrs_source_map(id.parent);
408 Either::Left(field) => ast::AttrsOwnerNode::new(field.clone()), 407 let file_id = id.parent.file_id(db);
409 Either::Right(field) => ast::AttrsOwnerNode::new(field.clone()), 408 let root = db.parse_or_expand(file_id).unwrap();
410 }) 409 let owner = match &map[id.local_id] {
410 Either::Left(it) => ast::AttrsOwnerNode::new(it.to_node(&root)),
411 Either::Right(it) => ast::AttrsOwnerNode::new(it.to_node(&root)),
412 };
413 InFile::new(file_id, owner)
411 } 414 }
412 AttrDefId::AdtId(adt) => match adt { 415 AttrDefId::AdtId(adt) => match adt {
413 AdtId::StructId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 416 AdtId::StructId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
@@ -415,10 +418,12 @@ impl AttrsWithOwner {
415 AdtId::EnumId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 418 AdtId::EnumId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
416 }, 419 },
417 AttrDefId::FunctionId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 420 AttrDefId::FunctionId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
418 AttrDefId::EnumVariantId(id) => id 421 AttrDefId::EnumVariantId(id) => {
419 .parent 422 let map = db.variants_attrs_source_map(id.parent);
420 .child_source(db) 423 let file_id = id.parent.lookup(db).id.file_id();
421 .map(|source| ast::AttrsOwnerNode::new(source[id.local_id].clone())), 424 let root = db.parse_or_expand(file_id).unwrap();
425 InFile::new(file_id, ast::AttrsOwnerNode::new(map[id.local_id].to_node(&root)))
426 }
422 AttrDefId::StaticId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 427 AttrDefId::StaticId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
423 AttrDefId::ConstId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 428 AttrDefId::ConstId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
424 AttrDefId::TraitId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 429 AttrDefId::TraitId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
@@ -747,3 +752,36 @@ fn collect_attrs(
747 752
748 attrs.into_iter().map(|(_, attr)| attr) 753 attrs.into_iter().map(|(_, attr)| attr)
749} 754}
755
756pub(crate) fn variants_attrs_source_map(
757 db: &dyn DefDatabase,
758 def: EnumId,
759) -> Arc<ArenaMap<LocalEnumVariantId, AstPtr<ast::Variant>>> {
760 let mut res = ArenaMap::default();
761 let child_source = def.child_source(db);
762
763 for (idx, variant) in child_source.value.iter() {
764 res.insert(idx, AstPtr::new(variant));
765 }
766
767 Arc::new(res)
768}
769
770pub(crate) fn fields_attrs_source_map(
771 db: &dyn DefDatabase,
772 def: VariantId,
773) -> Arc<ArenaMap<LocalFieldId, Either<AstPtr<ast::TupleField>, AstPtr<ast::RecordField>>>> {
774 let mut res = ArenaMap::default();
775 let child_source = def.child_source(db);
776
777 for (idx, variant) in child_source.value.iter() {
778 res.insert(
779 idx,
780 variant
781 .as_ref()
782 .either(|l| Either::Left(AstPtr::new(l)), |r| Either::Right(AstPtr::new(r))),
783 );
784 }
785
786 Arc::new(res)
787}
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs
index 9b7a213a1..7eadc8e0d 100644
--- a/crates/hir_def/src/db.rs
+++ b/crates/hir_def/src/db.rs
@@ -2,9 +2,10 @@
2use std::sync::Arc; 2use std::sync::Arc;
3 3
4use base_db::{salsa, CrateId, SourceDatabase, Upcast}; 4use base_db::{salsa, CrateId, SourceDatabase, Upcast};
5use either::Either;
5use hir_expand::{db::AstDatabase, HirFileId}; 6use hir_expand::{db::AstDatabase, HirFileId};
6use la_arena::ArenaMap; 7use la_arena::ArenaMap;
7use syntax::SmolStr; 8use syntax::{ast, AstPtr, SmolStr};
8 9
9use crate::{ 10use crate::{
10 adt::{EnumData, StructData}, 11 adt::{EnumData, StructData},
@@ -122,6 +123,18 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
122 #[salsa::invoke(Attrs::fields_attrs_query)] 123 #[salsa::invoke(Attrs::fields_attrs_query)]
123 fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>; 124 fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>;
124 125
126 #[salsa::invoke(crate::attr::variants_attrs_source_map)]
127 fn variants_attrs_source_map(
128 &self,
129 def: EnumId,
130 ) -> Arc<ArenaMap<LocalEnumVariantId, AstPtr<ast::Variant>>>;
131
132 #[salsa::invoke(crate::attr::fields_attrs_source_map)]
133 fn fields_attrs_source_map(
134 &self,
135 def: VariantId,
136 ) -> Arc<ArenaMap<LocalFieldId, Either<AstPtr<ast::TupleField>, AstPtr<ast::RecordField>>>>;
137
125 #[salsa::invoke(AttrsWithOwner::attrs_query)] 138 #[salsa::invoke(AttrsWithOwner::attrs_query)]
126 fn attrs(&self, def: AttrDefId) -> AttrsWithOwner; 139 fn attrs(&self, def: AttrDefId) -> AttrsWithOwner;
127 140
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs
index a8ee5eeac..9014468ea 100644
--- a/crates/hir_def/src/item_scope.rs
+++ b/crates/hir_def/src/item_scope.rs
@@ -11,7 +11,7 @@ use rustc_hash::{FxHashMap, FxHashSet};
11use stdx::format_to; 11use stdx::format_to;
12 12
13use crate::{ 13use crate::{
14 db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ImplId, 14 db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ConstId, ImplId,
15 LocalModuleId, MacroDefId, ModuleDefId, ModuleId, TraitId, 15 LocalModuleId, MacroDefId, ModuleDefId, ModuleId, TraitId,
16}; 16};
17 17
@@ -37,6 +37,7 @@ pub struct ItemScope {
37 37
38 defs: Vec<ModuleDefId>, 38 defs: Vec<ModuleDefId>,
39 impls: Vec<ImplId>, 39 impls: Vec<ImplId>,
40 unnamed_consts: Vec<ConstId>,
40 /// Traits imported via `use Trait as _;`. 41 /// Traits imported via `use Trait as _;`.
41 unnamed_trait_imports: FxHashMap<TraitId, Visibility>, 42 unnamed_trait_imports: FxHashMap<TraitId, Visibility>,
42 /// Macros visible in current module in legacy textual scope 43 /// Macros visible in current module in legacy textual scope
@@ -106,6 +107,10 @@ impl ItemScope {
106 .map(|(_, v)| v) 107 .map(|(_, v)| v)
107 } 108 }
108 109
110 pub fn unnamed_consts(&self) -> impl Iterator<Item = ConstId> + '_ {
111 self.unnamed_consts.iter().copied()
112 }
113
109 /// Iterate over all module scoped macros 114 /// Iterate over all module scoped macros
110 pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a { 115 pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
111 self.entries().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_))) 116 self.entries().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_)))
@@ -156,6 +161,10 @@ impl ItemScope {
156 self.impls.push(imp) 161 self.impls.push(imp)
157 } 162 }
158 163
164 pub(crate) fn define_unnamed_const(&mut self, konst: ConstId) {
165 self.unnamed_consts.push(konst);
166 }
167
159 pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroDefId) { 168 pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroDefId) {
160 self.legacy_macros.insert(name, mac); 169 self.legacy_macros.insert(name, mac);
161 } 170 }
@@ -295,6 +304,7 @@ impl ItemScope {
295 unresolved, 304 unresolved,
296 defs, 305 defs,
297 impls, 306 impls,
307 unnamed_consts,
298 unnamed_trait_imports, 308 unnamed_trait_imports,
299 legacy_macros, 309 legacy_macros,
300 } = self; 310 } = self;
@@ -304,6 +314,7 @@ impl ItemScope {
304 unresolved.shrink_to_fit(); 314 unresolved.shrink_to_fit();
305 defs.shrink_to_fit(); 315 defs.shrink_to_fit();
306 impls.shrink_to_fit(); 316 impls.shrink_to_fit();
317 unnamed_consts.shrink_to_fit();
307 unnamed_trait_imports.shrink_to_fit(); 318 unnamed_trait_imports.shrink_to_fit();
308 legacy_macros.shrink_to_fit(); 319 legacy_macros.shrink_to_fit();
309 } 320 }
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs
index abd6c553f..e2af0e514 100644
--- a/crates/hir_def/src/lib.rs
+++ b/crates/hir_def/src/lib.rs
@@ -453,6 +453,14 @@ impl VariantId {
453 } 453 }
454 } 454 }
455 } 455 }
456
457 pub fn file_id(self, db: &dyn db::DefDatabase) -> HirFileId {
458 match self {
459 VariantId::EnumVariantId(it) => it.parent.lookup(db).id.file_id(),
460 VariantId::StructId(it) => it.lookup(db).id.file_id(),
461 VariantId::UnionId(it) => it.lookup(db).id.file_id(),
462 }
463 }
456} 464}
457 465
458trait Intern { 466trait Intern {
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index f42f92702..492d8c71f 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -1163,19 +1163,27 @@ impl ModCollector<'_, '_> {
1163 } 1163 }
1164 ModItem::Const(id) => { 1164 ModItem::Const(id) => {
1165 let it = &self.item_tree[id]; 1165 let it = &self.item_tree[id];
1166 1166 let const_id = ConstLoc {
1167 if let Some(name) = &it.name { 1167 container: module.into(),
1168 def = Some(DefData { 1168 id: ItemTreeId::new(self.file_id, id),
1169 id: ConstLoc { 1169 }
1170 container: module.into(), 1170 .intern(self.def_collector.db);
1171 id: ItemTreeId::new(self.file_id, id), 1171
1172 } 1172 match &it.name {
1173 .intern(self.def_collector.db) 1173 Some(name) => {
1174 .into(), 1174 def = Some(DefData {
1175 name, 1175 id: const_id.into(),
1176 visibility: &self.item_tree[it.visibility], 1176 name,
1177 has_constructor: false, 1177 visibility: &self.item_tree[it.visibility],
1178 }); 1178 has_constructor: false,
1179 });
1180 }
1181 None => {
1182 // const _: T = ...;
1183 self.def_collector.def_map.modules[self.module_id]
1184 .scope
1185 .define_unnamed_const(const_id);
1186 }
1179 } 1187 }
1180 } 1188 }
1181 ModItem::Static(id) => { 1189 ModItem::Static(id) => {
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs
index c5890e24d..80e192a57 100644
--- a/crates/hir_ty/src/autoderef.rs
+++ b/crates/hir_ty/src/autoderef.rs
@@ -120,8 +120,8 @@ fn deref_by_trait(
120 // assumptions will be broken. We would need to properly introduce 120 // assumptions will be broken. We would need to properly introduce
121 // new variables in that case 121 // new variables in that case
122 122
123 for i in 1..vars.0.binders.len(&Interner) { 123 for i in 1..vars.binders.len(&Interner) {
124 if vars.0.value.at(&Interner, i - 1).assert_ty_ref(&Interner).kind(&Interner) 124 if vars.value.subst.at(&Interner, i - 1).assert_ty_ref(&Interner).kind(&Interner)
125 != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) 125 != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1))
126 { 126 {
127 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution); 127 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution);
@@ -130,12 +130,12 @@ fn deref_by_trait(
130 } 130 }
131 Some(Canonical { 131 Some(Canonical {
132 value: vars 132 value: vars
133 .0
134 .value 133 .value
135 .at(&Interner, vars.0.value.len(&Interner) - 1) 134 .subst
135 .at(&Interner, vars.value.subst.len(&Interner) - 1)
136 .assert_ty_ref(&Interner) 136 .assert_ty_ref(&Interner)
137 .clone(), 137 .clone(),
138 binders: vars.0.binders.clone(), 138 binders: vars.binders.clone(),
139 }) 139 })
140 } 140 }
141 Solution::Ambig(_) => { 141 Solution::Ambig(_) => {
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index 796f77ab0..6af0c59b8 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -42,7 +42,7 @@ use super::{
42}; 42};
43use crate::{ 43use crate::{
44 db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, 44 db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode,
45 to_assoc_type_id, AliasEq, AliasTy, Interner, TyBuilder, TyExt, TyKind, 45 to_assoc_type_id, AliasEq, AliasTy, Canonical, Interner, TyBuilder, TyExt, TyKind,
46}; 46};
47 47
48// This lint has a false positive here. See the link below for details. 48// This lint has a false positive here. See the link below for details.
@@ -131,8 +131,7 @@ pub struct InferenceResult {
131 method_resolutions: FxHashMap<ExprId, FunctionId>, 131 method_resolutions: FxHashMap<ExprId, FunctionId>,
132 /// For each field access expr, records the field it resolves to. 132 /// For each field access expr, records the field it resolves to.
133 field_resolutions: FxHashMap<ExprId, FieldId>, 133 field_resolutions: FxHashMap<ExprId, FieldId>,
134 record_pat_field_resolutions: FxHashMap<PatId, FieldId>, 134 /// For each struct literal or pattern, records the variant it resolves to.
135 /// For each struct literal, records the variant it resolves to.
136 variant_resolutions: FxHashMap<ExprOrPatId, VariantId>, 135 variant_resolutions: FxHashMap<ExprOrPatId, VariantId>,
137 /// For each associated item record what it resolves to 136 /// For each associated item record what it resolves to
138 assoc_resolutions: FxHashMap<ExprOrPatId, AssocItemId>, 137 assoc_resolutions: FxHashMap<ExprOrPatId, AssocItemId>,
@@ -151,9 +150,6 @@ impl InferenceResult {
151 pub fn field_resolution(&self, expr: ExprId) -> Option<FieldId> { 150 pub fn field_resolution(&self, expr: ExprId) -> Option<FieldId> {
152 self.field_resolutions.get(&expr).copied() 151 self.field_resolutions.get(&expr).copied()
153 } 152 }
154 pub fn record_pat_field_resolution(&self, pat: PatId) -> Option<FieldId> {
155 self.record_pat_field_resolutions.get(&pat).copied()
156 }
157 pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> { 153 pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> {
158 self.variant_resolutions.get(&id.into()).copied() 154 self.variant_resolutions.get(&id.into()).copied()
159 } 155 }
@@ -346,11 +342,18 @@ impl<'a> InferenceContext<'a> {
346 self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone()); 342 self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone());
347 343
348 match solution { 344 match solution {
349 Some(Solution::Unique(substs)) => { 345 Some(Solution::Unique(canonical_subst)) => {
350 canonicalized.apply_solution(self, substs.0); 346 canonicalized.apply_solution(
347 self,
348 Canonical {
349 binders: canonical_subst.binders,
350 // FIXME: handle constraints
351 value: canonical_subst.value.subst,
352 },
353 );
351 } 354 }
352 Some(Solution::Ambig(Guidance::Definite(substs))) => { 355 Some(Solution::Ambig(Guidance::Definite(substs))) => {
353 canonicalized.apply_solution(self, substs.0); 356 canonicalized.apply_solution(self, substs);
354 self.obligations.push(obligation); 357 self.obligations.push(obligation);
355 } 358 }
356 Some(_) => { 359 Some(_) => {
@@ -691,25 +694,6 @@ impl<'a> InferenceContext<'a> {
691 } 694 }
692} 695}
693 696
694/// The kinds of placeholders we need during type inference. There's separate
695/// values for general types, and for integer and float variables. The latter
696/// two are used for inference of literal values (e.g. `100` could be one of
697/// several integer types).
698#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
699pub struct InferenceVar {
700 index: u32,
701}
702
703impl InferenceVar {
704 fn to_inner(self) -> unify::TypeVarId {
705 unify::TypeVarId(self.index)
706 }
707
708 fn from_inner(unify::TypeVarId(index): unify::TypeVarId) -> Self {
709 InferenceVar { index }
710 }
711}
712
713/// When inferring an expression, we propagate downward whatever type hint we 697/// When inferring an expression, we propagate downward whatever type hint we
714/// are able in the form of an `Expectation`. 698/// are able in the form of an `Expectation`.
715#[derive(Clone, PartialEq, Eq, Debug)] 699#[derive(Clone, PartialEq, Eq, Debug)]
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs
index 159a53a63..f1af2a0bd 100644
--- a/crates/hir_ty/src/infer/coerce.rs
+++ b/crates/hir_ty/src/infer/coerce.rs
@@ -7,7 +7,7 @@
7use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; 7use chalk_ir::{cast::Cast, Mutability, TyVariableKind};
8use hir_def::lang_item::LangItemTarget; 8use hir_def::lang_item::LangItemTarget;
9 9
10use crate::{autoderef, Interner, Solution, Ty, TyBuilder, TyExt, TyKind}; 10use crate::{autoderef, Canonical, Interner, Solution, Ty, TyBuilder, TyExt, TyKind};
11 11
12use super::{InEnvironment, InferenceContext}; 12use super::{InEnvironment, InferenceContext};
13 13
@@ -148,7 +148,14 @@ impl<'a> InferenceContext<'a> {
148 148
149 match solution { 149 match solution {
150 Solution::Unique(v) => { 150 Solution::Unique(v) => {
151 canonicalized.apply_solution(self, v.0); 151 canonicalized.apply_solution(
152 self,
153 Canonical {
154 binders: v.binders,
155 // FIXME handle constraints
156 value: v.value.subst,
157 },
158 );
152 } 159 }
153 _ => return None, 160 _ => return None,
154 }; 161 };
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index 942f70edf..e4813c87c 100644
--- a/crates/hir_ty/src/infer/pat.rs
+++ b/crates/hir_ty/src/infer/pat.rs
@@ -7,7 +7,6 @@ use chalk_ir::Mutability;
7use hir_def::{ 7use hir_def::{
8 expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat}, 8 expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat},
9 path::Path, 9 path::Path,
10 FieldId,
11}; 10};
12use hir_expand::name::Name; 11use hir_expand::name::Name;
13 12
@@ -80,11 +79,6 @@ impl<'a> InferenceContext<'a> {
80 let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); 79 let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default();
81 for subpat in subpats { 80 for subpat in subpats {
82 let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name)); 81 let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name));
83 if let Some(local_id) = matching_field {
84 let field_def = FieldId { parent: def.unwrap(), local_id };
85 self.result.record_pat_field_resolutions.insert(subpat.pat, field_def);
86 }
87
88 let expected_ty = matching_field.map_or(self.err_ty(), |field| { 82 let expected_ty = matching_field.map_or(self.err_ty(), |field| {
89 field_tys[field].clone().substitute(&Interner, &substs) 83 field_tys[field].clone().substitute(&Interner, &substs)
90 }); 84 });
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs
index 7d76cda68..d717e3375 100644
--- a/crates/hir_ty/src/infer/unify.rs
+++ b/crates/hir_ty/src/infer/unify.rs
@@ -51,7 +51,7 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
51 t.fold_binders( 51 t.fold_binders(
52 &mut |ty, binders| match ty.kind(&Interner) { 52 &mut |ty, binders| match ty.kind(&Interner) {
53 &TyKind::InferenceVar(var, kind) => { 53 &TyKind::InferenceVar(var, kind) => {
54 let inner = var.to_inner(); 54 let inner = from_inference_var(var);
55 if self.var_stack.contains(&inner) { 55 if self.var_stack.contains(&inner) {
56 // recursive type 56 // recursive type
57 return self.ctx.table.type_variable_table.fallback_value(var, kind); 57 return self.ctx.table.type_variable_table.fallback_value(var, kind);
@@ -65,7 +65,7 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
65 result 65 result
66 } else { 66 } else {
67 let root = self.ctx.table.var_unification_table.find(inner); 67 let root = self.ctx.table.var_unification_table.find(inner);
68 let position = self.add(InferenceVar::from_inner(root), kind); 68 let position = self.add(to_inference_var(root), kind);
69 TyKind::BoundVar(BoundVar::new(binders, position)).intern(&Interner) 69 TyKind::BoundVar(BoundVar::new(binders, position)).intern(&Interner)
70 } 70 }
71 } 71 }
@@ -207,16 +207,16 @@ impl TypeVariableTable {
207 } 207 }
208 208
209 pub(super) fn set_diverging(&mut self, iv: InferenceVar, diverging: bool) { 209 pub(super) fn set_diverging(&mut self, iv: InferenceVar, diverging: bool) {
210 self.inner[iv.to_inner().0 as usize].diverging = diverging; 210 self.inner[from_inference_var(iv).0 as usize].diverging = diverging;
211 } 211 }
212 212
213 fn is_diverging(&mut self, iv: InferenceVar) -> bool { 213 fn is_diverging(&mut self, iv: InferenceVar) -> bool {
214 self.inner[iv.to_inner().0 as usize].diverging 214 self.inner[from_inference_var(iv).0 as usize].diverging
215 } 215 }
216 216
217 fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty { 217 fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty {
218 match kind { 218 match kind {
219 _ if self.inner[iv.to_inner().0 as usize].diverging => TyKind::Never, 219 _ if self.inner[from_inference_var(iv).0 as usize].diverging => TyKind::Never,
220 TyVariableKind::General => TyKind::Error, 220 TyVariableKind::General => TyKind::Error,
221 TyVariableKind::Integer => TyKind::Scalar(Scalar::Int(IntTy::I32)), 221 TyVariableKind::Integer => TyKind::Scalar(Scalar::Int(IntTy::I32)),
222 TyVariableKind::Float => TyKind::Scalar(Scalar::Float(FloatTy::F64)), 222 TyVariableKind::Float => TyKind::Scalar(Scalar::Float(FloatTy::F64)),
@@ -250,7 +250,7 @@ impl InferenceTable {
250 self.type_variable_table.push(TypeVariableData { diverging }); 250 self.type_variable_table.push(TypeVariableData { diverging });
251 let key = self.var_unification_table.new_key(TypeVarValue::Unknown); 251 let key = self.var_unification_table.new_key(TypeVarValue::Unknown);
252 assert_eq!(key.0 as usize, self.type_variable_table.inner.len() - 1); 252 assert_eq!(key.0 as usize, self.type_variable_table.inner.len() - 1);
253 TyKind::InferenceVar(InferenceVar::from_inner(key), kind).intern(&Interner) 253 TyKind::InferenceVar(to_inference_var(key), kind).intern(&Interner)
254 } 254 }
255 255
256 pub(crate) fn new_type_var(&mut self) -> Ty { 256 pub(crate) fn new_type_var(&mut self) -> Ty {
@@ -369,8 +369,12 @@ impl InferenceTable {
369 == self.type_variable_table.is_diverging(*tv2) => 369 == self.type_variable_table.is_diverging(*tv2) =>
370 { 370 {
371 // both type vars are unknown since we tried to resolve them 371 // both type vars are unknown since we tried to resolve them
372 if !self.var_unification_table.unioned(tv1.to_inner(), tv2.to_inner()) { 372 if !self
373 self.var_unification_table.union(tv1.to_inner(), tv2.to_inner()); 373 .var_unification_table
374 .unioned(from_inference_var(*tv1), from_inference_var(*tv2))
375 {
376 self.var_unification_table
377 .union(from_inference_var(*tv1), from_inference_var(*tv2));
374 self.revision += 1; 378 self.revision += 1;
375 } 379 }
376 true 380 true
@@ -407,7 +411,7 @@ impl InferenceTable {
407 ) => { 411 ) => {
408 // the type var is unknown since we tried to resolve it 412 // the type var is unknown since we tried to resolve it
409 self.var_unification_table.union_value( 413 self.var_unification_table.union_value(
410 tv.to_inner(), 414 from_inference_var(*tv),
411 TypeVarValue::Known(other.clone().intern(&Interner)), 415 TypeVarValue::Known(other.clone().intern(&Interner)),
412 ); 416 );
413 self.revision += 1; 417 self.revision += 1;
@@ -462,7 +466,7 @@ impl InferenceTable {
462 } 466 }
463 match ty.kind(&Interner) { 467 match ty.kind(&Interner) {
464 TyKind::InferenceVar(tv, _) => { 468 TyKind::InferenceVar(tv, _) => {
465 let inner = tv.to_inner(); 469 let inner = from_inference_var(*tv);
466 match self.var_unification_table.inlined_probe_value(inner).known() { 470 match self.var_unification_table.inlined_probe_value(inner).known() {
467 Some(known_ty) => { 471 Some(known_ty) => {
468 // The known_ty can't be a type var itself 472 // The known_ty can't be a type var itself
@@ -485,7 +489,7 @@ impl InferenceTable {
485 fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { 489 fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
486 ty.fold(&mut |ty| match ty.kind(&Interner) { 490 ty.fold(&mut |ty| match ty.kind(&Interner) {
487 &TyKind::InferenceVar(tv, kind) => { 491 &TyKind::InferenceVar(tv, kind) => {
488 let inner = tv.to_inner(); 492 let inner = from_inference_var(tv);
489 if tv_stack.contains(&inner) { 493 if tv_stack.contains(&inner) {
490 cov_mark::hit!(type_var_cycles_resolve_as_possible); 494 cov_mark::hit!(type_var_cycles_resolve_as_possible);
491 // recursive type 495 // recursive type
@@ -512,7 +516,7 @@ impl InferenceTable {
512 fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { 516 fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
513 ty.fold(&mut |ty| match ty.kind(&Interner) { 517 ty.fold(&mut |ty| match ty.kind(&Interner) {
514 &TyKind::InferenceVar(tv, kind) => { 518 &TyKind::InferenceVar(tv, kind) => {
515 let inner = tv.to_inner(); 519 let inner = from_inference_var(tv);
516 if tv_stack.contains(&inner) { 520 if tv_stack.contains(&inner) {
517 cov_mark::hit!(type_var_cycles_resolve_completely); 521 cov_mark::hit!(type_var_cycles_resolve_completely);
518 // recursive type 522 // recursive type
@@ -555,6 +559,14 @@ impl UnifyKey for TypeVarId {
555 } 559 }
556} 560}
557 561
562fn from_inference_var(var: InferenceVar) -> TypeVarId {
563 TypeVarId(var.index())
564}
565
566fn to_inference_var(TypeVarId(index): TypeVarId) -> InferenceVar {
567 index.into()
568}
569
558/// The value of a type variable: either we already know the type, or we don't 570/// The value of a type variable: either we already know the type, or we don't
559/// know it yet. 571/// know it yet.
560#[derive(Clone, PartialEq, Eq, Debug)] 572#[derive(Clone, PartialEq, Eq, Debug)]
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index f5b658cba..5c83a508d 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -42,7 +42,7 @@ use crate::{db::HirDatabase, display::HirDisplay, utils::generics};
42pub use autoderef::autoderef; 42pub use autoderef::autoderef;
43pub use builder::TyBuilder; 43pub use builder::TyBuilder;
44pub use chalk_ext::{ProjectionTyExt, TyExt}; 44pub use chalk_ext::{ProjectionTyExt, TyExt};
45pub use infer::{could_unify, InferenceResult, InferenceVar}; 45pub use infer::{could_unify, InferenceResult};
46pub use lower::{ 46pub use lower::{
47 associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, 47 associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode,
48 TyDefId, TyLoweringContext, ValueTyDefId, 48 TyDefId, TyLoweringContext, ValueTyDefId,
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index ee725fd46..f29319f20 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -8,8 +8,8 @@ use arrayvec::ArrayVec;
8use base_db::CrateId; 8use base_db::CrateId;
9use chalk_ir::{cast::Cast, Mutability, UniverseIndex}; 9use chalk_ir::{cast::Cast, Mutability, UniverseIndex};
10use hir_def::{ 10use hir_def::{
11 lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule, 11 lang_item::LangItemTarget, nameres::DefMap, AssocContainerId, AssocItemId, FunctionId,
12 ImplId, Lookup, ModuleId, TraitId, 12 GenericDefId, HasModule, ImplId, Lookup, ModuleId, TraitId,
13}; 13};
14use hir_expand::name::Name; 14use hir_expand::name::Name;
15use rustc_hash::{FxHashMap, FxHashSet}; 15use rustc_hash::{FxHashMap, FxHashSet};
@@ -100,25 +100,38 @@ impl TraitImpls {
100 let mut impls = Self { map: FxHashMap::default() }; 100 let mut impls = Self { map: FxHashMap::default() };
101 101
102 let crate_def_map = db.crate_def_map(krate); 102 let crate_def_map = db.crate_def_map(krate);
103 for (_module_id, module_data) in crate_def_map.modules() { 103 collect_def_map(db, &crate_def_map, &mut impls);
104 for impl_id in module_data.scope.impls() { 104
105 let target_trait = match db.impl_trait(impl_id) { 105 return Arc::new(impls);
106 Some(tr) => tr.skip_binders().hir_trait_id(), 106
107 None => continue, 107 fn collect_def_map(db: &dyn HirDatabase, def_map: &DefMap, impls: &mut TraitImpls) {
108 }; 108 for (_module_id, module_data) in def_map.modules() {
109 let self_ty = db.impl_self_ty(impl_id); 109 for impl_id in module_data.scope.impls() {
110 let self_ty_fp = TyFingerprint::for_impl(self_ty.skip_binders()); 110 let target_trait = match db.impl_trait(impl_id) {
111 impls 111 Some(tr) => tr.skip_binders().hir_trait_id(),
112 .map 112 None => continue,
113 .entry(target_trait) 113 };
114 .or_default() 114 let self_ty = db.impl_self_ty(impl_id);
115 .entry(self_ty_fp) 115 let self_ty_fp = TyFingerprint::for_impl(self_ty.skip_binders());
116 .or_default() 116 impls
117 .push(impl_id); 117 .map
118 .entry(target_trait)
119 .or_default()
120 .entry(self_ty_fp)
121 .or_default()
122 .push(impl_id);
123 }
124
125 // To better support custom derives, collect impls in all unnamed const items.
126 // const _: () = { ... };
127 for konst in module_data.scope.unnamed_consts() {
128 let body = db.body(konst.into());
129 for (_, block_def_map) in body.blocks(db.upcast()) {
130 collect_def_map(db, &block_def_map, impls);
131 }
132 }
118 } 133 }
119 } 134 }
120
121 Arc::new(impls)
122 } 135 }
123 136
124 pub(crate) fn trait_impls_in_deps_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> { 137 pub(crate) fn trait_impls_in_deps_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> {
@@ -208,6 +221,9 @@ impl InherentImpls {
208 } 221 }
209 } 222 }
210 223
224 // NOTE: We're not collecting inherent impls from unnamed consts here, we intentionally only
225 // support trait impls there.
226
211 Arc::new(Self { map }) 227 Arc::new(Self { map })
212 } 228 }
213 229
diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs
index 61f18b0d2..4b2c82b41 100644
--- a/crates/hir_ty/src/tests/method_resolution.rs
+++ b/crates/hir_ty/src/tests/method_resolution.rs
@@ -1292,3 +1292,25 @@ mod b {
1292 "#]], 1292 "#]],
1293 ) 1293 )
1294} 1294}
1295
1296#[test]
1297fn impl_in_unnamed_const() {
1298 check_types(
1299 r#"
1300struct S;
1301
1302trait Tr {
1303 fn method(&self) -> u16;
1304}
1305
1306const _: () = {
1307 impl Tr for S {}
1308};
1309
1310fn f() {
1311 S.method();
1312 //^^^^^^^^^^ u16
1313}
1314 "#,
1315 );
1316}
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs
index c8883485c..3374532c3 100644
--- a/crates/hir_ty/src/traits.rs
+++ b/crates/hir_ty/src/traits.rs
@@ -9,7 +9,7 @@ use stdx::panic_context;
9 9
10use crate::{ 10use crate::{
11 db::HirDatabase, AliasEq, AliasTy, Canonical, DomainGoal, Guidance, HirDisplay, InEnvironment, 11 db::HirDatabase, AliasEq, AliasTy, Canonical, DomainGoal, Guidance, HirDisplay, InEnvironment,
12 Solution, SolutionVariables, Ty, TyKind, WhereClause, 12 Solution, Ty, TyKind, WhereClause,
13}; 13};
14 14
15use self::chalk::{from_chalk, Interner, ToChalk}; 15use self::chalk::{from_chalk, Interner, ToChalk};
@@ -173,23 +173,15 @@ fn solution_from_chalk(
173 db: &dyn HirDatabase, 173 db: &dyn HirDatabase,
174 solution: chalk_solve::Solution<Interner>, 174 solution: chalk_solve::Solution<Interner>,
175) -> Solution { 175) -> Solution {
176 let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<Interner>>| {
177 let result = from_chalk(db, subst);
178 SolutionVariables(result)
179 };
180 match solution { 176 match solution {
181 chalk_solve::Solution::Unique(constr_subst) => { 177 chalk_solve::Solution::Unique(constr_subst) => {
182 let subst = chalk_ir::Canonical { 178 Solution::Unique(from_chalk(db, constr_subst))
183 value: constr_subst.value.subst,
184 binders: constr_subst.binders,
185 };
186 Solution::Unique(convert_subst(subst))
187 } 179 }
188 chalk_solve::Solution::Ambig(chalk_solve::Guidance::Definite(subst)) => { 180 chalk_solve::Solution::Ambig(chalk_solve::Guidance::Definite(subst)) => {
189 Solution::Ambig(Guidance::Definite(convert_subst(subst))) 181 Solution::Ambig(Guidance::Definite(from_chalk(db, subst)))
190 } 182 }
191 chalk_solve::Solution::Ambig(chalk_solve::Guidance::Suggested(subst)) => { 183 chalk_solve::Solution::Ambig(chalk_solve::Guidance::Suggested(subst)) => {
192 Solution::Ambig(Guidance::Suggested(convert_subst(subst))) 184 Solution::Ambig(Guidance::Suggested(from_chalk(db, subst)))
193 } 185 }
194 chalk_solve::Solution::Ambig(chalk_solve::Guidance::Unknown) => { 186 chalk_solve::Solution::Ambig(chalk_solve::Guidance::Unknown) => {
195 Solution::Ambig(Guidance::Unknown) 187 Solution::Ambig(Guidance::Unknown)
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs
index cf73cb078..84abd99b2 100644
--- a/crates/hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/hir_ty/src/traits/chalk/mapping.rs
@@ -10,10 +10,9 @@ use base_db::salsa::InternKey;
10use hir_def::{GenericDefId, TypeAliasId}; 10use hir_def::{GenericDefId, TypeAliasId};
11 11
12use crate::{ 12use crate::{
13 chalk_ext::ProjectionTyExt, db::HirDatabase, dummy_usize_const, static_lifetime, AliasTy, 13 chalk_ext::ProjectionTyExt, db::HirDatabase, static_lifetime, AliasTy, CallableDefId,
14 CallableDefId, Canonical, Const, DomainGoal, FnPointer, GenericArg, InEnvironment, Lifetime, 14 Canonical, ConstrainedSubst, DomainGoal, FnPointer, GenericArg, InEnvironment, OpaqueTy,
15 OpaqueTy, ProjectionTy, QuantifiedWhereClause, Substitution, TraitRef, Ty, TypeWalk, 15 ProjectionTy, QuantifiedWhereClause, Substitution, TraitRef, Ty, TypeWalk, WhereClause,
16 WhereClause,
17}; 16};
18 17
19use super::interner::*; 18use super::interner::*;
@@ -23,16 +22,16 @@ impl ToChalk for Ty {
23 type Chalk = chalk_ir::Ty<Interner>; 22 type Chalk = chalk_ir::Ty<Interner>;
24 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> { 23 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> {
25 match self.into_inner() { 24 match self.into_inner() {
26 TyKind::Ref(m, lt, ty) => ref_to_chalk(db, m, lt, ty), 25 TyKind::Ref(m, lt, ty) => {
27 TyKind::Array(ty, size) => array_to_chalk(db, ty, size), 26 chalk_ir::TyKind::Ref(m, lt, ty.to_chalk(db)).intern(&Interner)
28 TyKind::Function(FnPointer { sig, substitution: substs, .. }) => { 27 }
28 TyKind::Array(ty, size) => {
29 chalk_ir::TyKind::Array(ty.to_chalk(db), size).intern(&Interner)
30 }
31 TyKind::Function(FnPointer { sig, substitution: substs, num_binders }) => {
29 let substitution = chalk_ir::FnSubst(substs.0.to_chalk(db)); 32 let substitution = chalk_ir::FnSubst(substs.0.to_chalk(db));
30 chalk_ir::TyKind::Function(chalk_ir::FnPointer { 33 chalk_ir::TyKind::Function(chalk_ir::FnPointer { num_binders, sig, substitution })
31 num_binders: 0, 34 .intern(&Interner)
32 sig,
33 substitution,
34 })
35 .intern(&Interner)
36 } 35 }
37 TyKind::AssociatedType(assoc_type_id, substs) => { 36 TyKind::AssociatedType(assoc_type_id, substs) => {
38 let substitution = substs.to_chalk(db); 37 let substitution = substs.to_chalk(db);
@@ -74,22 +73,13 @@ impl ToChalk for Ty {
74 chalk_ir::TyKind::Adt(adt_id, substitution).intern(&Interner) 73 chalk_ir::TyKind::Adt(adt_id, substitution).intern(&Interner)
75 } 74 }
76 TyKind::Alias(AliasTy::Projection(proj_ty)) => { 75 TyKind::Alias(AliasTy::Projection(proj_ty)) => {
77 let associated_ty_id = proj_ty.associated_ty_id; 76 chalk_ir::AliasTy::Projection(proj_ty.to_chalk(db))
78 let substitution = proj_ty.substitution.to_chalk(db);
79 chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
80 associated_ty_id,
81 substitution,
82 })
83 .cast(&Interner)
84 .intern(&Interner)
85 }
86 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
87 let opaque_ty_id = opaque_ty.opaque_ty_id;
88 let substitution = opaque_ty.substitution.to_chalk(db);
89 chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy { opaque_ty_id, substitution })
90 .cast(&Interner) 77 .cast(&Interner)
91 .intern(&Interner) 78 .intern(&Interner)
92 } 79 }
80 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
81 chalk_ir::AliasTy::Opaque(opaque_ty.to_chalk(db)).cast(&Interner).intern(&Interner)
82 }
93 TyKind::Placeholder(idx) => idx.to_ty::<Interner>(&Interner), 83 TyKind::Placeholder(idx) => idx.to_ty::<Interner>(&Interner),
94 TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner), 84 TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner),
95 TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"), 85 TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"),
@@ -101,7 +91,7 @@ impl ToChalk for Ty {
101 ); 91 );
102 let bounded_ty = chalk_ir::DynTy { 92 let bounded_ty = chalk_ir::DynTy {
103 bounds: chalk_ir::Binders::new(binders, where_clauses), 93 bounds: chalk_ir::Binders::new(binders, where_clauses),
104 lifetime: static_lifetime(), 94 lifetime: dyn_ty.lifetime,
105 }; 95 };
106 chalk_ir::TyKind::Dyn(bounded_ty).intern(&Interner) 96 chalk_ir::TyKind::Dyn(bounded_ty).intern(&Interner)
107 } 97 }
@@ -114,17 +104,10 @@ impl ToChalk for Ty {
114 chalk_ir::TyKind::Array(ty, size) => TyKind::Array(from_chalk(db, ty), size), 104 chalk_ir::TyKind::Array(ty, size) => TyKind::Array(from_chalk(db, ty), size),
115 chalk_ir::TyKind::Placeholder(idx) => TyKind::Placeholder(idx), 105 chalk_ir::TyKind::Placeholder(idx) => TyKind::Placeholder(idx),
116 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(proj)) => { 106 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(proj)) => {
117 let associated_ty = proj.associated_ty_id; 107 TyKind::Alias(AliasTy::Projection(from_chalk(db, proj)))
118 let parameters = from_chalk(db, proj.substitution);
119 TyKind::Alias(AliasTy::Projection(ProjectionTy {
120 associated_ty_id: associated_ty,
121 substitution: parameters,
122 }))
123 } 108 }
124 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(opaque_ty)) => { 109 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(opaque_ty)) => {
125 let opaque_ty_id = opaque_ty.opaque_ty_id; 110 TyKind::Alias(AliasTy::Opaque(from_chalk(db, opaque_ty)))
126 let parameters = from_chalk(db, opaque_ty.substitution);
127 TyKind::Alias(AliasTy::Opaque(OpaqueTy { opaque_ty_id, substitution: parameters }))
128 } 111 }
129 chalk_ir::TyKind::Function(chalk_ir::FnPointer { 112 chalk_ir::TyKind::Function(chalk_ir::FnPointer {
130 num_binders, 113 num_binders,
@@ -138,18 +121,19 @@ impl ToChalk for Ty {
138 } 121 }
139 chalk_ir::TyKind::BoundVar(idx) => TyKind::BoundVar(idx), 122 chalk_ir::TyKind::BoundVar(idx) => TyKind::BoundVar(idx),
140 chalk_ir::TyKind::InferenceVar(_iv, _kind) => TyKind::Error, 123 chalk_ir::TyKind::InferenceVar(_iv, _kind) => TyKind::Error,
141 chalk_ir::TyKind::Dyn(where_clauses) => { 124 chalk_ir::TyKind::Dyn(dyn_ty) => {
142 assert_eq!(where_clauses.bounds.binders.len(&Interner), 1); 125 assert_eq!(dyn_ty.bounds.binders.len(&Interner), 1);
143 let bounds = where_clauses 126 let (bounds, binders) = dyn_ty.bounds.into_value_and_skipped_binders();
144 .bounds 127 let where_clauses = crate::QuantifiedWhereClauses::from_iter(
145 .skip_binders() 128 &Interner,
146 .iter(&Interner) 129 bounds.interned().iter().cloned().map(|p| from_chalk(db, p)),
147 .map(|c| from_chalk(db, c.clone())); 130 );
148 TyKind::Dyn(crate::DynTy { 131 TyKind::Dyn(crate::DynTy {
149 bounds: crate::Binders::new( 132 bounds: crate::Binders::new(binders, where_clauses),
150 where_clauses.bounds.binders.clone(), 133 // HACK: we sometimes get lifetime variables back in solutions
151 crate::QuantifiedWhereClauses::from_iter(&Interner, bounds), 134 // from Chalk, and don't have the infrastructure to substitute
152 ), 135 // them yet. So for now we just turn them into 'static right
136 // when we get them
153 lifetime: static_lifetime(), 137 lifetime: static_lifetime(),
154 }) 138 })
155 } 139 }
@@ -169,8 +153,12 @@ impl ToChalk for Ty {
169 } 153 }
170 chalk_ir::TyKind::Raw(mutability, ty) => TyKind::Raw(mutability, from_chalk(db, ty)), 154 chalk_ir::TyKind::Raw(mutability, ty) => TyKind::Raw(mutability, from_chalk(db, ty)),
171 chalk_ir::TyKind::Slice(ty) => TyKind::Slice(from_chalk(db, ty)), 155 chalk_ir::TyKind::Slice(ty) => TyKind::Slice(from_chalk(db, ty)),
172 chalk_ir::TyKind::Ref(mutability, lifetime, ty) => { 156 chalk_ir::TyKind::Ref(mutability, _lifetime, ty) => {
173 TyKind::Ref(mutability, lifetime, from_chalk(db, ty)) 157 // HACK: we sometimes get lifetime variables back in solutions
158 // from Chalk, and don't have the infrastructure to substitute
159 // them yet. So for now we just turn them into 'static right
160 // when we get them
161 TyKind::Ref(mutability, static_lifetime(), from_chalk(db, ty))
174 } 162 }
175 chalk_ir::TyKind::Str => TyKind::Str, 163 chalk_ir::TyKind::Str => TyKind::Str,
176 chalk_ir::TyKind::Never => TyKind::Never, 164 chalk_ir::TyKind::Never => TyKind::Never,
@@ -189,26 +177,6 @@ impl ToChalk for Ty {
189 } 177 }
190} 178}
191 179
192/// We currently don't model lifetimes, but Chalk does. So, we have to insert a
193/// fake lifetime here, because Chalks built-in logic may expect it to be there.
194fn ref_to_chalk(
195 db: &dyn HirDatabase,
196 mutability: chalk_ir::Mutability,
197 _lifetime: Lifetime,
198 ty: Ty,
199) -> chalk_ir::Ty<Interner> {
200 let arg = ty.to_chalk(db);
201 let lifetime = static_lifetime();
202 chalk_ir::TyKind::Ref(mutability, lifetime, arg).intern(&Interner)
203}
204
205/// We currently don't model constants, but Chalk does. So, we have to insert a
206/// fake constant here, because Chalks built-in logic may expect it to be there.
207fn array_to_chalk(db: &dyn HirDatabase, ty: Ty, _: Const) -> chalk_ir::Ty<Interner> {
208 let arg = ty.to_chalk(db);
209 chalk_ir::TyKind::Array(arg, dummy_usize_const()).intern(&Interner)
210}
211
212impl ToChalk for GenericArg { 180impl ToChalk for GenericArg {
213 type Chalk = chalk_ir::GenericArg<Interner>; 181 type Chalk = chalk_ir::GenericArg<Interner>;
214 182
@@ -491,6 +459,18 @@ where
491 } 459 }
492} 460}
493 461
462impl ToChalk for crate::ConstrainedSubst {
463 type Chalk = chalk_ir::ConstrainedSubst<Interner>;
464
465 fn to_chalk(self, _db: &dyn HirDatabase) -> Self::Chalk {
466 unimplemented!()
467 }
468
469 fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self {
470 ConstrainedSubst { subst: from_chalk(db, chalk.subst) }
471 }
472}
473
494pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> 474pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T>
495where 475where
496 T: HasInterner<Interner = Interner>, 476 T: HasInterner<Interner = Interner>,
diff --git a/crates/hir_ty/src/types.rs b/crates/hir_ty/src/types.rs
index 89c0ddd1a..c25bc2d6a 100644
--- a/crates/hir_ty/src/types.rs
+++ b/crates/hir_ty/src/types.rs
@@ -11,8 +11,7 @@ use smallvec::SmallVec;
11 11
12use crate::{ 12use crate::{
13 AssocTypeId, CanonicalVarKinds, ChalkTraitId, ClosureId, Const, FnDefId, FnSig, ForeignDefId, 13 AssocTypeId, CanonicalVarKinds, ChalkTraitId, ClosureId, Const, FnDefId, FnSig, ForeignDefId,
14 InferenceVar, Interner, Lifetime, OpaqueTyId, PlaceholderIndex, TypeWalk, VariableKind, 14 Interner, Lifetime, OpaqueTyId, PlaceholderIndex, TypeWalk, VariableKind, VariableKinds,
15 VariableKinds,
16}; 15};
17 16
18#[derive(Clone, PartialEq, Eq, Debug, Hash)] 17#[derive(Clone, PartialEq, Eq, Debug, Hash)]
@@ -491,14 +490,16 @@ pub struct AliasEq {
491} 490}
492 491
493#[derive(Clone, Debug, PartialEq, Eq)] 492#[derive(Clone, Debug, PartialEq, Eq)]
494pub struct SolutionVariables(pub Canonical<Substitution>); 493pub struct ConstrainedSubst {
494 pub subst: Substitution,
495}
495 496
496#[derive(Clone, Debug, PartialEq, Eq)] 497#[derive(Clone, Debug, PartialEq, Eq)]
497/// A (possible) solution for a proposed goal. 498/// A (possible) solution for a proposed goal.
498pub enum Solution { 499pub enum Solution {
499 /// The goal indeed holds, and there is a unique value for all existential 500 /// The goal indeed holds, and there is a unique value for all existential
500 /// variables. 501 /// variables.
501 Unique(SolutionVariables), 502 Unique(Canonical<ConstrainedSubst>),
502 503
503 /// The goal may be provable in multiple ways, but regardless we may have some guidance 504 /// The goal may be provable in multiple ways, but regardless we may have some guidance
504 /// for type inference. In this case, we don't return any lifetime 505 /// for type inference. In this case, we don't return any lifetime
@@ -514,13 +515,35 @@ pub enum Guidance {
514 /// The existential variables *must* have the given values if the goal is 515 /// The existential variables *must* have the given values if the goal is
515 /// ever to hold, but that alone isn't enough to guarantee the goal will 516 /// ever to hold, but that alone isn't enough to guarantee the goal will
516 /// actually hold. 517 /// actually hold.
517 Definite(SolutionVariables), 518 Definite(Canonical<Substitution>),
518 519
519 /// There are multiple plausible values for the existentials, but the ones 520 /// There are multiple plausible values for the existentials, but the ones
520 /// here are suggested as the preferred choice heuristically. These should 521 /// here are suggested as the preferred choice heuristically. These should
521 /// be used for inference fallback only. 522 /// be used for inference fallback only.
522 Suggested(SolutionVariables), 523 Suggested(Canonical<Substitution>),
523 524
524 /// There's no useful information to feed back to type inference 525 /// There's no useful information to feed back to type inference
525 Unknown, 526 Unknown,
526} 527}
528
529/// The kinds of placeholders we need during type inference. There's separate
530/// values for general types, and for integer and float variables. The latter
531/// two are used for inference of literal values (e.g. `100` could be one of
532/// several integer types).
533#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
534pub struct InferenceVar {
535 index: u32,
536}
537
538impl From<u32> for InferenceVar {
539 fn from(index: u32) -> InferenceVar {
540 InferenceVar { index }
541 }
542}
543
544impl InferenceVar {
545 /// Gets the underlying index value.
546 pub fn index(self) -> u32 {
547 self.index
548 }
549}
diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs
index 9eeabbeda..d5628e3df 100644
--- a/crates/ide/src/expand_macro.rs
+++ b/crates/ide/src/expand_macro.rs
@@ -103,6 +103,9 @@ fn insert_whitespaces(syn: SyntaxNode) -> String {
103 format!("\n{}}}", " ".repeat(indent)) 103 format!("\n{}}}", " ".repeat(indent))
104 } 104 }
105 R_CURLY => format!("}}\n{}", " ".repeat(indent)), 105 R_CURLY => format!("}}\n{}", " ".repeat(indent)),
106 LIFETIME_IDENT if is_next(|it| it == IDENT, true) => {
107 format!("{} ", token.text().to_string())
108 }
106 T![;] => format!(";\n{}", " ".repeat(indent)), 109 T![;] => format!(";\n{}", " ".repeat(indent)),
107 T![->] => " -> ".to_string(), 110 T![->] => " -> ".to_string(),
108 T![=] => " = ".to_string(), 111 T![=] => " = ".to_string(),
diff --git a/crates/ide_completion/src/completions/flyimport.rs b/crates/ide_completion/src/completions/flyimport.rs
index 1ad017198..9ace13e41 100644
--- a/crates/ide_completion/src/completions/flyimport.rs
+++ b/crates/ide_completion/src/completions/flyimport.rs
@@ -113,6 +113,7 @@ pub(crate) fn import_on_the_fly(acc: &mut Completions, ctx: &CompletionContext)
113 if ctx.use_item_syntax.is_some() 113 if ctx.use_item_syntax.is_some()
114 || ctx.attribute_under_caret.is_some() 114 || ctx.attribute_under_caret.is_some()
115 || ctx.mod_declaration_under_caret.is_some() 115 || ctx.mod_declaration_under_caret.is_some()
116 || ctx.record_lit_syntax.is_some()
116 { 117 {
117 return None; 118 return None;
118 } 119 }
@@ -1034,4 +1035,46 @@ fn main() {
1034 expect![[]], 1035 expect![[]],
1035 ); 1036 );
1036 } 1037 }
1038
1039 #[test]
1040 fn no_fuzzy_during_fields_of_record_lit_syntax() {
1041 check(
1042 r#"
1043mod m {
1044 pub fn some_fn() -> i32 {
1045 42
1046 }
1047}
1048struct Foo {
1049 some_field: i32,
1050}
1051fn main() {
1052 let _ = Foo { so$0 };
1053}
1054"#,
1055 expect![[]],
1056 );
1057 }
1058
1059 #[test]
1060 fn fuzzy_after_fields_of_record_lit_syntax() {
1061 check(
1062 r#"
1063mod m {
1064 pub fn some_fn() -> i32 {
1065 42
1066 }
1067}
1068struct Foo {
1069 some_field: i32,
1070}
1071fn main() {
1072 let _ = Foo { some_field: so$0 };
1073}
1074"#,
1075 expect![[r#"
1076 fn some_fn() (m::some_fn) fn() -> i32
1077 "#]],
1078 );
1079 }
1037} 1080}
diff --git a/crates/ide_db/src/apply_change.rs b/crates/ide_db/src/apply_change.rs
index 111e9325a..6c67425d7 100644
--- a/crates/ide_db/src/apply_change.rs
+++ b/crates/ide_db/src/apply_change.rs
@@ -152,6 +152,10 @@ impl RootDatabase {
152 hir::db::FileItemTreeQuery 152 hir::db::FileItemTreeQuery
153 hir::db::BlockDefMapQuery 153 hir::db::BlockDefMapQuery
154 hir::db::CrateDefMapQueryQuery 154 hir::db::CrateDefMapQueryQuery
155 hir::db::FieldsAttrsQuery
156 hir::db::VariantsAttrsQuery
157 hir::db::FieldsAttrsSourceMapQuery
158 hir::db::VariantsAttrsSourceMapQuery
155 hir::db::StructDataQuery 159 hir::db::StructDataQuery
156 hir::db::UnionDataQuery 160 hir::db::UnionDataQuery
157 hir::db::EnumDataQuery 161 hir::db::EnumDataQuery
diff --git a/crates/test_utils/src/fixture.rs b/crates/test_utils/src/fixture.rs
index 6bc824e94..099baeca2 100644
--- a/crates/test_utils/src/fixture.rs
+++ b/crates/test_utils/src/fixture.rs
@@ -1,5 +1,65 @@
1//! Defines `Fixture` -- a convenient way to describe the initial state of 1//! Defines `Fixture` -- a convenient way to describe the initial state of
2//! rust-analyzer database from a single string. 2//! rust-analyzer database from a single string.
3//!
4//! Fixtures are strings containing rust source code with optional metadata.
5//! A fixture without metadata is parsed into a single source file.
6//! Use this to test functionality local to one file.
7//!
8//! Simple Example:
9//! ```
10//! r#"
11//! fn main() {
12//! println!("Hello World")
13//! }
14//! "#
15//! ```
16//!
17//! Metadata can be added to a fixture after a `//-` comment.
18//! The basic form is specifying filenames,
19//! which is also how to define multiple files in a single test fixture
20//!
21//! Example using two files in the same crate:
22//! ```
23//! "
24//! //- /main.rs
25//! mod foo;
26//! fn main() {
27//! foo::bar();
28//! }
29//!
30//! //- /foo.rs
31//! pub fn bar() {}
32//! "
33//! ```
34//!
35//! Example using two crates with one file each, with one crate depending on the other:
36//! ```
37//! r#"
38//! //- /main.rs crate:a deps:b
39//! fn main() {
40//! b::foo();
41//! }
42//! //- /lib.rs crate:b
43//! pub fn b() {
44//! println!("Hello World")
45//! }
46//! "#
47//! ```
48//!
49//! Metadata allows specifying all settings and variables
50//! that are available in a real rust project:
51//! - crate names via `crate:cratename`
52//! - dependencies via `deps:dep1,dep2`
53//! - configuration settings via `cfg:dbg=false,opt_level=2`
54//! - environment variables via `env:PATH=/bin,RUST_LOG=debug`
55//!
56//! Example using all available metadata:
57//! ```
58//! "
59//! //- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo
60//! fn insert_source_code_here() {}
61//! "
62//! ```
3 63
4use rustc_hash::FxHashMap; 64use rustc_hash::FxHashMap;
5use stdx::{lines_with_ends, split_once, trim_indent}; 65use stdx::{lines_with_ends, split_once, trim_indent};
@@ -24,7 +84,7 @@ impl Fixture {
24 /// //- some meta 84 /// //- some meta
25 /// line 1 85 /// line 1
26 /// line 2 86 /// line 2
27 /// // - other meta 87 /// //- other meta
28 /// ``` 88 /// ```
29 pub fn parse(ra_fixture: &str) -> Vec<Fixture> { 89 pub fn parse(ra_fixture: &str) -> Vec<Fixture> {
30 let fixture = trim_indent(ra_fixture); 90 let fixture = trim_indent(ra_fixture);