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.rs98
-rw-r--r--crates/hir/src/source_analyzer.rs33
-rw-r--r--crates/hir_def/src/attr.rs105
-rw-r--r--crates/hir_def/src/body/lower.rs29
-rw-r--r--crates/hir_def/src/body/tests.rs2
-rw-r--r--crates/hir_def/src/child_by_source.rs4
-rw-r--r--crates/hir_def/src/db.rs15
-rw-r--r--crates/hir_def/src/expr.rs19
-rw-r--r--crates/hir_def/src/item_scope.rs13
-rw-r--r--crates/hir_def/src/lib.rs34
-rw-r--r--crates/hir_def/src/nameres.rs28
-rw-r--r--crates/hir_def/src/nameres/collector.rs59
-rw-r--r--crates/hir_def/src/nameres/path_resolution.rs51
-rw-r--r--crates/hir_def/src/nameres/tests/diagnostics.rs2
-rw-r--r--crates/hir_def/src/path.rs6
-rw-r--r--crates/hir_expand/src/builtin_derive.rs10
-rw-r--r--crates/hir_expand/src/builtin_macro.rs9
-rw-r--r--crates/hir_expand/src/eager.rs5
-rw-r--r--crates/hir_expand/src/lib.rs21
-rw-r--r--crates/hir_ty/src/autoderef.rs64
-rw-r--r--crates/hir_ty/src/builder.rs21
-rw-r--r--crates/hir_ty/src/chalk_cast.rs73
-rw-r--r--crates/hir_ty/src/chalk_db.rs (renamed from crates/hir_ty/src/traits/chalk.rs)233
-rw-r--r--crates/hir_ty/src/chalk_ext.rs294
-rw-r--r--crates/hir_ty/src/db.rs66
-rw-r--r--crates/hir_ty/src/diagnostics.rs2
-rw-r--r--crates/hir_ty/src/diagnostics/expr.rs11
-rw-r--r--crates/hir_ty/src/diagnostics/match_check.rs2
-rw-r--r--crates/hir_ty/src/diagnostics/unsafe_check.rs4
-rw-r--r--crates/hir_ty/src/display.rs215
-rw-r--r--crates/hir_ty/src/infer.rs141
-rw-r--r--crates/hir_ty/src/infer/coerce.rs29
-rw-r--r--crates/hir_ty/src/infer/expr.rs77
-rw-r--r--crates/hir_ty/src/infer/pat.rs50
-rw-r--r--crates/hir_ty/src/infer/path.rs7
-rw-r--r--crates/hir_ty/src/infer/unify.rs207
-rw-r--r--crates/hir_ty/src/interner.rs (renamed from crates/hir_ty/src/traits/chalk/interner.rs)127
-rw-r--r--crates/hir_ty/src/lib.rs577
-rw-r--r--crates/hir_ty/src/lower.rs81
-rw-r--r--crates/hir_ty/src/mapping.rs154
-rw-r--r--crates/hir_ty/src/method_resolution.rs294
-rw-r--r--crates/hir_ty/src/op.rs58
-rw-r--r--crates/hir_ty/src/primitive.rs5
-rw-r--r--crates/hir_ty/src/tests/method_resolution.rs22
-rw-r--r--crates/hir_ty/src/tests/regression.rs38
-rw-r--r--crates/hir_ty/src/tests/simple.rs33
-rw-r--r--crates/hir_ty/src/tests/traits.rs1467
-rw-r--r--crates/hir_ty/src/tls.rs (renamed from crates/hir_ty/src/traits/chalk/tls.rs)14
-rw-r--r--crates/hir_ty/src/traits.rs52
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs572
-rw-r--r--crates/hir_ty/src/types.rs475
-rw-r--r--crates/hir_ty/src/utils.rs29
-rw-r--r--crates/hir_ty/src/walk.rs283
-rw-r--r--crates/ide/src/diagnostics.rs16
-rw-r--r--crates/ide/src/expand_macro.rs44
-rw-r--r--crates/ide/src/folding_ranges.rs17
-rw-r--r--crates/ide/src/syntax_highlighting/highlight.rs14
-rw-r--r--crates/ide/src/syntax_highlighting/tests.rs96
-rw-r--r--crates/ide/src/typing.rs168
-rw-r--r--crates/ide/src/typing/on_enter.rs20
-rw-r--r--crates/ide_assists/src/handlers/remove_dbg.rs105
-rw-r--r--crates/ide_completion/src/completions/flyimport.rs43
-rw-r--r--crates/ide_completion/src/item.rs2
-rw-r--r--crates/ide_db/src/apply_change.rs4
-rw-r--r--crates/paths/src/lib.rs7
-rw-r--r--crates/project_model/src/build_data.rs86
-rw-r--r--crates/project_model/src/workspace.rs10
-rw-r--r--crates/rust-analyzer/Cargo.toml2
-rw-r--r--crates/rust-analyzer/src/caps.rs2
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs2
-rw-r--r--crates/rust-analyzer/src/config.rs17
-rw-r--r--crates/rust-analyzer/src/global_state.rs62
-rw-r--r--crates/rust-analyzer/src/handlers.rs6
-rw-r--r--crates/rust-analyzer/src/lsp_ext.rs30
-rw-r--r--crates/rust-analyzer/src/lsp_utils.rs24
-rw-r--r--crates/rust-analyzer/src/main_loop.rs103
-rw-r--r--crates/rust-analyzer/src/op_queue.rs16
-rw-r--r--crates/rust-analyzer/src/reload.rs213
-rw-r--r--crates/rust-analyzer/src/to_proto.rs29
-rw-r--r--crates/rust-analyzer/tests/rust-analyzer/support.rs11
-rw-r--r--crates/stdx/src/lib.rs8
-rw-r--r--crates/syntax/Cargo.toml2
-rw-r--r--crates/test_utils/src/bench_fixture.rs3
-rw-r--r--crates/test_utils/src/fixture.rs62
-rw-r--r--crates/vfs/Cargo.toml1
-rw-r--r--crates/vfs/src/path_interner.rs29
87 files changed, 3822 insertions, 3812 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 003821981..eba46a056 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -53,13 +53,14 @@ use hir_def::{
53use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind}; 53use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind};
54use hir_ty::{ 54use hir_ty::{
55 autoderef, could_unify, 55 autoderef, could_unify,
56 method_resolution::{self, TyFingerprint}, 56 method_resolution::{self, def_crates, TyFingerprint},
57 primitive::UintTy, 57 primitive::UintTy,
58 subst_prefix,
58 traits::FnTrait, 59 traits::FnTrait,
59 AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, 60 AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast,
60 DebruijnIndex, InEnvironment, Interner, QuantifiedWhereClause, Scalar, Solution, 61 DebruijnIndex, InEnvironment, Interner, QuantifiedWhereClause, Scalar, Solution, Substitution,
61 SolutionVariables, Substitution, TraitEnvironment, Ty, TyBuilder, TyDefId, TyKind, 62 TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, TyVariableKind,
62 TyVariableKind, WhereClause, 63 WhereClause,
63}; 64};
64use itertools::Itertools; 65use itertools::Itertools;
65use rustc_hash::FxHashSet; 66use rustc_hash::FxHashSet;
@@ -1503,7 +1504,7 @@ impl TypeParam {
1503 let krate = self.id.parent.module(db.upcast()).krate(); 1504 let krate = self.id.parent.module(db.upcast()).krate();
1504 let ty = params.get(local_idx)?.clone(); 1505 let ty = params.get(local_idx)?.clone();
1505 let subst = TyBuilder::type_params_subst(db, self.id.parent); 1506 let subst = TyBuilder::type_params_subst(db, self.id.parent);
1506 let ty = ty.substitute(&Interner, &subst.prefix(local_idx)); 1507 let ty = ty.substitute(&Interner, &subst_prefix(&subst, local_idx));
1507 Some(Type::new_with_resolver_inner(db, krate, &resolver, ty)) 1508 Some(Type::new_with_resolver_inner(db, krate, &resolver, ty))
1508 } 1509 }
1509} 1510}
@@ -1568,7 +1569,7 @@ impl Impl {
1568 } 1569 }
1569 1570
1570 pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty, .. }: Type) -> Vec<Impl> { 1571 pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty, .. }: Type) -> Vec<Impl> {
1571 let def_crates = match ty.def_crates(db, krate) { 1572 let def_crates = match def_crates(db, &ty, krate) {
1572 Some(def_crates) => def_crates, 1573 Some(def_crates) => def_crates,
1573 None => return Vec::new(), 1574 None => return Vec::new(),
1574 }; 1575 };
@@ -1579,11 +1580,24 @@ impl Impl {
1579 ty.equals_ctor(rref.as_ref().map_or(&self_ty.ty, |it| &it.ty)) 1580 ty.equals_ctor(rref.as_ref().map_or(&self_ty.ty, |it| &it.ty))
1580 }; 1581 };
1581 1582
1583 let fp = TyFingerprint::for_inherent_impl(&ty);
1584 let fp = if let Some(fp) = fp {
1585 fp
1586 } else {
1587 return Vec::new();
1588 };
1589
1582 let mut all = Vec::new(); 1590 let mut all = Vec::new();
1583 def_crates.iter().for_each(|&id| { 1591 def_crates.iter().for_each(|&id| {
1584 all.extend(db.inherent_impls_in_crate(id).all_impls().map(Self::from).filter(filter)) 1592 all.extend(
1593 db.inherent_impls_in_crate(id)
1594 .for_self_ty(&ty)
1595 .into_iter()
1596 .cloned()
1597 .map(Self::from)
1598 .filter(filter),
1599 )
1585 }); 1600 });
1586 let fp = TyFingerprint::for_impl(&ty);
1587 for id in def_crates 1601 for id in def_crates
1588 .iter() 1602 .iter()
1589 .flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db)) 1603 .flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db))
@@ -1591,13 +1605,12 @@ impl Impl {
1591 .chain(def_crates.iter().copied()) 1605 .chain(def_crates.iter().copied())
1592 .unique() 1606 .unique()
1593 { 1607 {
1594 match fp { 1608 all.extend(
1595 Some(fp) => all.extend( 1609 db.trait_impls_in_crate(id)
1596 db.trait_impls_in_crate(id).for_self_ty(fp).map(Self::from).filter(filter), 1610 .for_self_ty_without_blanket_impls(fp)
1597 ), 1611 .map(Self::from)
1598 None => all 1612 .filter(filter),
1599 .extend(db.trait_impls_in_crate(id).all_impls().map(Self::from).filter(filter)), 1613 );
1600 }
1601 } 1614 }
1602 all 1615 all
1603 } 1616 }
@@ -1790,7 +1803,7 @@ impl Type {
1790 .build(); 1803 .build();
1791 1804
1792 let goal = Canonical { 1805 let goal = Canonical {
1793 value: hir_ty::InEnvironment::new(self.env.env.clone(), trait_ref.cast(&Interner)), 1806 value: hir_ty::InEnvironment::new(&self.env.env, trait_ref.cast(&Interner)),
1794 binders: CanonicalVarKinds::empty(&Interner), 1807 binders: CanonicalVarKinds::empty(&Interner),
1795 }; 1808 };
1796 1809
@@ -1807,9 +1820,9 @@ impl Type {
1807 .push(self.ty.clone()) 1820 .push(self.ty.clone())
1808 .fill(args.iter().map(|t| t.ty.clone())) 1821 .fill(args.iter().map(|t| t.ty.clone()))
1809 .build(); 1822 .build();
1810 let goal = Canonical::new( 1823 let goal = hir_ty::make_canonical(
1811 InEnvironment::new( 1824 InEnvironment::new(
1812 self.env.env.clone(), 1825 &self.env.env,
1813 AliasEq { 1826 AliasEq {
1814 alias: AliasTy::Projection(projection), 1827 alias: AliasTy::Projection(projection),
1815 ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) 1828 ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
@@ -1821,9 +1834,10 @@ impl Type {
1821 ); 1834 );
1822 1835
1823 match db.trait_solve(self.krate, goal)? { 1836 match db.trait_solve(self.krate, goal)? {
1824 Solution::Unique(SolutionVariables(subst)) => subst 1837 Solution::Unique(s) => s
1825 .value 1838 .value
1826 .interned() 1839 .subst
1840 .as_slice(&Interner)
1827 .first() 1841 .first()
1828 .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone())), 1842 .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone())),
1829 Solution::Ambig(_) => None, 1843 Solution::Ambig(_) => None,
@@ -1887,9 +1901,10 @@ impl Type {
1887 substs.iter(&Interner).filter_map(|a| a.ty(&Interner)).any(go) 1901 substs.iter(&Interner).filter_map(|a| a.ty(&Interner)).any(go)
1888 } 1902 }
1889 1903
1890 TyKind::Array(ty) | TyKind::Slice(ty) | TyKind::Raw(_, ty) | TyKind::Ref(_, ty) => { 1904 TyKind::Array(ty, _)
1891 go(ty) 1905 | TyKind::Slice(ty)
1892 } 1906 | TyKind::Raw(_, ty)
1907 | TyKind::Ref(_, _, ty) => go(ty),
1893 1908
1894 TyKind::Scalar(_) 1909 TyKind::Scalar(_)
1895 | TyKind::Str 1910 | TyKind::Str
@@ -1900,7 +1915,9 @@ impl Type {
1900 | TyKind::Dyn(_) 1915 | TyKind::Dyn(_)
1901 | TyKind::Function(_) 1916 | TyKind::Function(_)
1902 | TyKind::Alias(_) 1917 | TyKind::Alias(_)
1903 | TyKind::Foreign(_) => false, 1918 | TyKind::Foreign(_)
1919 | TyKind::Generator(..)
1920 | TyKind::GeneratorWitness(..) => false,
1904 } 1921 }
1905 } 1922 }
1906 } 1923 }
@@ -1953,7 +1970,7 @@ impl Type {
1953 krate: Crate, 1970 krate: Crate,
1954 mut callback: impl FnMut(AssocItem) -> Option<T>, 1971 mut callback: impl FnMut(AssocItem) -> Option<T>,
1955 ) -> Option<T> { 1972 ) -> Option<T> {
1956 for krate in self.ty.def_crates(db, krate.id)? { 1973 for krate in def_crates(db, &self.ty, krate.id)? {
1957 let impls = db.inherent_impls_in_crate(krate); 1974 let impls = db.inherent_impls_in_crate(krate);
1958 1975
1959 for impl_def in impls.for_self_ty(&self.ty) { 1976 for impl_def in impls.for_self_ty(&self.ty) {
@@ -1970,9 +1987,9 @@ impl Type {
1970 pub fn type_parameters(&self) -> impl Iterator<Item = Type> + '_ { 1987 pub fn type_parameters(&self) -> impl Iterator<Item = Type> + '_ {
1971 self.ty 1988 self.ty
1972 .strip_references() 1989 .strip_references()
1973 .substs() 1990 .as_adt()
1974 .into_iter() 1991 .into_iter()
1975 .flat_map(|substs| substs.iter(&Interner)) 1992 .flat_map(|(_, substs)| substs.iter(&Interner))
1976 .filter_map(|arg| arg.ty(&Interner).cloned()) 1993 .filter_map(|arg| arg.ty(&Interner).cloned())
1977 .map(move |ty| self.derived(ty)) 1994 .map(move |ty| self.derived(ty))
1978 } 1995 }
@@ -2113,18 +2130,22 @@ impl Type {
2113 fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) { 2130 fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
2114 let ty = type_.ty.strip_references(); 2131 let ty = type_.ty.strip_references();
2115 match ty.kind(&Interner) { 2132 match ty.kind(&Interner) {
2116 TyKind::Adt(..) => { 2133 TyKind::Adt(_, substs) => {
2117 cb(type_.derived(ty.clone())); 2134 cb(type_.derived(ty.clone()));
2135 walk_substs(db, type_, &substs, cb);
2118 } 2136 }
2119 TyKind::AssociatedType(..) => { 2137 TyKind::AssociatedType(_, substs) => {
2120 if let Some(_) = ty.associated_type_parent_trait(db) { 2138 if let Some(_) = ty.associated_type_parent_trait(db) {
2121 cb(type_.derived(ty.clone())); 2139 cb(type_.derived(ty.clone()));
2122 } 2140 }
2141 walk_substs(db, type_, &substs, cb);
2123 } 2142 }
2124 TyKind::OpaqueType(..) => { 2143 TyKind::OpaqueType(_, subst) => {
2125 if let Some(bounds) = ty.impl_trait_bounds(db) { 2144 if let Some(bounds) = ty.impl_trait_bounds(db) {
2126 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); 2145 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
2127 } 2146 }
2147
2148 walk_substs(db, type_, subst, cb);
2128 } 2149 }
2129 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { 2150 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
2130 if let Some(bounds) = ty.impl_trait_bounds(db) { 2151 if let Some(bounds) = ty.impl_trait_bounds(db) {
@@ -2147,15 +2168,24 @@ impl Type {
2147 ); 2168 );
2148 } 2169 }
2149 2170
2150 TyKind::Ref(_, ty) | TyKind::Raw(_, ty) | TyKind::Array(ty) | TyKind::Slice(ty) => { 2171 TyKind::Ref(_, _, ty)
2172 | TyKind::Raw(_, ty)
2173 | TyKind::Array(ty, _)
2174 | TyKind::Slice(ty) => {
2151 walk_type(db, &type_.derived(ty.clone()), cb); 2175 walk_type(db, &type_.derived(ty.clone()), cb);
2152 } 2176 }
2153 2177
2178 TyKind::FnDef(_, substs)
2179 | TyKind::Tuple(_, substs)
2180 | TyKind::Closure(.., substs) => {
2181 walk_substs(db, type_, &substs, cb);
2182 }
2183 TyKind::Function(hir_ty::FnPointer { substitution, .. }) => {
2184 walk_substs(db, type_, &substitution.0, cb);
2185 }
2186
2154 _ => {} 2187 _ => {}
2155 } 2188 }
2156 if let Some(substs) = ty.substs() {
2157 walk_substs(db, type_, &substs, cb);
2158 }
2159 } 2189 }
2160 2190
2161 walk_type(db, self, &mut cb); 2191 walk_type(db, self, &mut cb);
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 4ce1c2080..847d2537d 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -20,7 +20,7 @@ use hir_def::{
20use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; 20use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile};
21use hir_ty::{ 21use hir_ty::{
22 diagnostics::{record_literal_missing_fields, record_pattern_missing_fields}, 22 diagnostics::{record_literal_missing_fields, record_pattern_missing_fields},
23 InferenceResult, Interner, Substitution, TyLoweringContext, 23 InferenceResult, Interner, Substitution, TyExt, TyLoweringContext,
24}; 24};
25use syntax::{ 25use syntax::{
26 ast::{self, AstNode}, 26 ast::{self, AstNode},
@@ -161,14 +161,15 @@ impl SourceAnalyzer {
161 db: &dyn HirDatabase, 161 db: &dyn HirDatabase,
162 field: &ast::RecordExprField, 162 field: &ast::RecordExprField,
163 ) -> Option<(Field, Option<Local>)> { 163 ) -> Option<(Field, Option<Local>)> {
164 let expr_id = 164 let record_expr = ast::RecordExpr::cast(field.syntax().parent().and_then(|p| p.parent())?)?;
165 self.body_source_map.as_ref()?.node_field(InFile::new(self.file_id, field))?; 165 let expr = ast::Expr::from(record_expr);
166 let expr_id = self.body_source_map.as_ref()?.node_expr(InFile::new(self.file_id, &expr))?;
166 167
168 let local_name = field.field_name()?.as_name();
167 let local = if field.name_ref().is_some() { 169 let local = if field.name_ref().is_some() {
168 None 170 None
169 } else { 171 } else {
170 let local_name = field.field_name()?.as_name(); 172 let path = ModPath::from_segments(PathKind::Plain, once(local_name.clone()));
171 let path = ModPath::from_segments(PathKind::Plain, once(local_name));
172 match self.resolver.resolve_path_in_value_ns_fully(db.upcast(), &path) { 173 match self.resolver.resolve_path_in_value_ns_fully(db.upcast(), &path) {
173 Some(ValueNs::LocalBinding(pat_id)) => { 174 Some(ValueNs::LocalBinding(pat_id)) => {
174 Some(Local { pat_id, parent: self.resolver.body_owner()? }) 175 Some(Local { pat_id, parent: self.resolver.body_owner()? })
@@ -176,18 +177,24 @@ impl SourceAnalyzer {
176 _ => None, 177 _ => None,
177 } 178 }
178 }; 179 };
179 let struct_field = self.infer.as_ref()?.record_field_resolution(expr_id)?; 180 let variant = self.infer.as_ref()?.variant_resolution_for_expr(expr_id)?;
180 Some((struct_field.into(), local)) 181 let variant_data = variant.variant_data(db.upcast());
182 let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? };
183 Some((field.into(), local))
181 } 184 }
182 185
183 pub(crate) fn resolve_record_pat_field( 186 pub(crate) fn resolve_record_pat_field(
184 &self, 187 &self,
185 _db: &dyn HirDatabase, 188 db: &dyn HirDatabase,
186 field: &ast::RecordPatField, 189 field: &ast::RecordPatField,
187 ) -> Option<Field> { 190 ) -> Option<Field> {
188 let pat_id = self.pat_id(&field.pat()?)?; 191 let field_name = field.field_name()?.as_name();
189 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())?)?;
190 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())
191 } 198 }
192 199
193 pub(crate) fn resolve_macro_call( 200 pub(crate) fn resolve_macro_call(
@@ -299,7 +306,7 @@ impl SourceAnalyzer {
299 let infer = self.infer.as_ref()?; 306 let infer = self.infer.as_ref()?;
300 307
301 let expr_id = self.expr_id(db, &literal.clone().into())?; 308 let expr_id = self.expr_id(db, &literal.clone().into())?;
302 let substs = infer.type_of_expr[expr_id].substs()?; 309 let substs = infer.type_of_expr[expr_id].as_adt()?.1;
303 310
304 let (variant, missing_fields, _exhaustive) = 311 let (variant, missing_fields, _exhaustive) =
305 record_literal_missing_fields(db, infer, expr_id, &body[expr_id])?; 312 record_literal_missing_fields(db, infer, expr_id, &body[expr_id])?;
@@ -317,7 +324,7 @@ impl SourceAnalyzer {
317 let infer = self.infer.as_ref()?; 324 let infer = self.infer.as_ref()?;
318 325
319 let pat_id = self.pat_id(&pattern.clone().into())?; 326 let pat_id = self.pat_id(&pattern.clone().into())?;
320 let substs = infer.type_of_pat[pat_id].substs()?; 327 let substs = infer.type_of_pat[pat_id].as_adt()?.1;
321 328
322 let (variant, missing_fields, _exhaustive) = 329 let (variant, missing_fields, _exhaustive) =
323 record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?; 330 record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?;
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index ab77d924a..786fad6e1 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -9,14 +9,14 @@ use std::{
9use base_db::CrateId; 9use base_db::CrateId;
10use cfg::{CfgExpr, CfgOptions}; 10use cfg::{CfgExpr, CfgOptions};
11use either::Either; 11use either::Either;
12use hir_expand::{hygiene::Hygiene, name::AsName, AstId, InFile}; 12use hir_expand::{hygiene::Hygiene, name::AsName, AstId, AttrId, InFile};
13use itertools::Itertools; 13use itertools::Itertools;
14use la_arena::ArenaMap; 14use la_arena::ArenaMap;
15use mbe::ast_to_token_tree; 15use 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
@@ -98,13 +98,16 @@ impl RawAttrs {
98 pub(crate) fn new(owner: &dyn ast::AttrsOwner, hygiene: &Hygiene) -> Self { 98 pub(crate) fn new(owner: &dyn ast::AttrsOwner, hygiene: &Hygiene) -> Self {
99 let entries = collect_attrs(owner) 99 let entries = collect_attrs(owner)
100 .enumerate() 100 .enumerate()
101 .flat_map(|(i, attr)| match attr { 101 .flat_map(|(i, attr)| {
102 Either::Left(attr) => Attr::from_src(attr, hygiene, i as u32), 102 let index = AttrId(i as u32);
103 Either::Right(comment) => comment.doc_comment().map(|doc| Attr { 103 match attr {
104 index: i as u32, 104 Either::Left(attr) => Attr::from_src(attr, hygiene, index),
105 input: Some(AttrInput::Literal(SmolStr::new(doc))), 105 Either::Right(comment) => comment.doc_comment().map(|doc| Attr {
106 path: Interned::new(ModPath::from(hir_expand::name!(doc))), 106 id: index,
107 }), 107 input: Some(AttrInput::Literal(SmolStr::new(doc))),
108 path: Interned::new(ModPath::from(hir_expand::name!(doc))),
109 }),
110 }
108 }) 111 })
109 .collect::<Arc<_>>(); 112 .collect::<Arc<_>>();
110 113
@@ -161,7 +164,7 @@ impl RawAttrs {
161 let cfg = parts.next().unwrap(); 164 let cfg = parts.next().unwrap();
162 let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() }; 165 let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() };
163 let cfg = CfgExpr::parse(&cfg); 166 let cfg = CfgExpr::parse(&cfg);
164 let index = attr.index; 167 let index = attr.id;
165 let attrs = parts.filter(|a| !a.is_empty()).filter_map(|attr| { 168 let attrs = parts.filter(|a| !a.is_empty()).filter_map(|attr| {
166 let tree = Subtree { delimiter: None, token_trees: attr.to_vec() }; 169 let tree = Subtree { delimiter: None, token_trees: attr.to_vec() };
167 let attr = ast::Attr::parse(&format!("#[{}]", tree)).ok()?; 170 let attr = ast::Attr::parse(&format!("#[{}]", tree)).ok()?;
@@ -215,12 +218,11 @@ impl Attrs {
215 let mut res = ArenaMap::default(); 218 let mut res = ArenaMap::default();
216 219
217 for (id, fld) in src.value.iter() { 220 for (id, fld) in src.value.iter() {
218 let attrs = match fld { 221 let owner: &dyn AttrsOwner = match fld {
219 Either::Left(_tuple) => Attrs::default(), 222 Either::Left(tuple) => tuple,
220 Either::Right(record) => { 223 Either::Right(record) => record,
221 RawAttrs::from_attrs_owner(db, src.with_value(record)).filter(db, krate)
222 }
223 }; 224 };
225 let attrs = RawAttrs::from_attrs_owner(db, src.with_value(owner)).filter(db, krate);
224 226
225 res.insert(id, attrs); 227 res.insert(id, attrs);
226 } 228 }
@@ -404,10 +406,14 @@ impl AttrsWithOwner {
404 return AttrSourceMap { attrs }; 406 return AttrSourceMap { attrs };
405 } 407 }
406 AttrDefId::FieldId(id) => { 408 AttrDefId::FieldId(id) => {
407 id.parent.child_source(db).map(|source| match &source[id.local_id] { 409 let map = db.fields_attrs_source_map(id.parent);
408 Either::Left(field) => ast::AttrsOwnerNode::new(field.clone()), 410 let file_id = id.parent.file_id(db);
409 Either::Right(field) => ast::AttrsOwnerNode::new(field.clone()), 411 let root = db.parse_or_expand(file_id).unwrap();
410 }) 412 let owner = match &map[id.local_id] {
413 Either::Left(it) => ast::AttrsOwnerNode::new(it.to_node(&root)),
414 Either::Right(it) => ast::AttrsOwnerNode::new(it.to_node(&root)),
415 };
416 InFile::new(file_id, owner)
411 } 417 }
412 AttrDefId::AdtId(adt) => match adt { 418 AttrDefId::AdtId(adt) => match adt {
413 AdtId::StructId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 419 AdtId::StructId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
@@ -415,10 +421,12 @@ impl AttrsWithOwner {
415 AdtId::EnumId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 421 AdtId::EnumId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
416 }, 422 },
417 AttrDefId::FunctionId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 423 AttrDefId::FunctionId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
418 AttrDefId::EnumVariantId(id) => id 424 AttrDefId::EnumVariantId(id) => {
419 .parent 425 let map = db.variants_attrs_source_map(id.parent);
420 .child_source(db) 426 let file_id = id.parent.lookup(db).id.file_id();
421 .map(|source| ast::AttrsOwnerNode::new(source[id.local_id].clone())), 427 let root = db.parse_or_expand(file_id).unwrap();
428 InFile::new(file_id, ast::AttrsOwnerNode::new(map[id.local_id].to_node(&root)))
429 }
422 AttrDefId::StaticId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 430 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), 431 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), 432 AttrDefId::TraitId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
@@ -463,7 +471,7 @@ impl AttrsWithOwner {
463 ) -> Option<(Documentation, DocsRangeMap)> { 471 ) -> Option<(Documentation, DocsRangeMap)> {
464 // FIXME: code duplication in `docs` above 472 // FIXME: code duplication in `docs` above
465 let docs = self.by_key("doc").attrs().flat_map(|attr| match attr.input.as_ref()? { 473 let docs = self.by_key("doc").attrs().flat_map(|attr| match attr.input.as_ref()? {
466 AttrInput::Literal(s) => Some((s, attr.index)), 474 AttrInput::Literal(s) => Some((s, attr.id)),
467 AttrInput::TokenTree(_) => None, 475 AttrInput::TokenTree(_) => None,
468 }); 476 });
469 let indent = docs 477 let indent = docs
@@ -555,8 +563,8 @@ impl AttrSourceMap {
555 /// the attribute represented by `Attr`. 563 /// the attribute represented by `Attr`.
556 pub fn source_of(&self, attr: &Attr) -> InFile<&Either<ast::Attr, ast::Comment>> { 564 pub fn source_of(&self, attr: &Attr) -> InFile<&Either<ast::Attr, ast::Comment>> {
557 self.attrs 565 self.attrs
558 .get(attr.index as usize) 566 .get(attr.id.0 as usize)
559 .unwrap_or_else(|| panic!("cannot find `Attr` at index {}", attr.index)) 567 .unwrap_or_else(|| panic!("cannot find `Attr` at index {:?}", attr.id))
560 .as_ref() 568 .as_ref()
561 } 569 }
562} 570}
@@ -567,7 +575,7 @@ pub struct DocsRangeMap {
567 // (docstring-line-range, attr_index, attr-string-range) 575 // (docstring-line-range, attr_index, attr-string-range)
568 // a mapping from the text range of a line of the [`Documentation`] to the attribute index and 576 // a mapping from the text range of a line of the [`Documentation`] to the attribute index and
569 // the original (untrimmed) syntax doc line 577 // the original (untrimmed) syntax doc line
570 mapping: Vec<(TextRange, u32, TextRange)>, 578 mapping: Vec<(TextRange, AttrId, TextRange)>,
571} 579}
572 580
573impl DocsRangeMap { 581impl DocsRangeMap {
@@ -580,7 +588,7 @@ impl DocsRangeMap {
580 588
581 let relative_range = range - line_docs_range.start(); 589 let relative_range = range - line_docs_range.start();
582 590
583 let &InFile { file_id, value: ref source } = &self.source[idx as usize]; 591 let &InFile { file_id, value: ref source } = &self.source[idx.0 as usize];
584 match source { 592 match source {
585 Either::Left(_) => None, // FIXME, figure out a nice way to handle doc attributes here 593 Either::Left(_) => None, // FIXME, figure out a nice way to handle doc attributes here
586 // as well as for whats done in syntax highlight doc injection 594 // as well as for whats done in syntax highlight doc injection
@@ -601,7 +609,7 @@ impl DocsRangeMap {
601 609
602#[derive(Debug, Clone, PartialEq, Eq)] 610#[derive(Debug, Clone, PartialEq, Eq)]
603pub struct Attr { 611pub struct Attr {
604 index: u32, 612 pub(crate) id: AttrId,
605 pub(crate) path: Interned<ModPath>, 613 pub(crate) path: Interned<ModPath>,
606 pub(crate) input: Option<AttrInput>, 614 pub(crate) input: Option<AttrInput>,
607} 615}
@@ -615,7 +623,7 @@ pub enum AttrInput {
615} 623}
616 624
617impl Attr { 625impl Attr {
618 fn from_src(ast: ast::Attr, hygiene: &Hygiene, index: u32) -> Option<Attr> { 626 fn from_src(ast: ast::Attr, hygiene: &Hygiene, id: AttrId) -> Option<Attr> {
619 let path = Interned::new(ModPath::from_src(ast.path()?, hygiene)?); 627 let path = Interned::new(ModPath::from_src(ast.path()?, hygiene)?);
620 let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() { 628 let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() {
621 let value = match lit.kind() { 629 let value = match lit.kind() {
@@ -628,7 +636,7 @@ impl Attr {
628 } else { 636 } else {
629 None 637 None
630 }; 638 };
631 Some(Attr { index, path, input }) 639 Some(Attr { id, path, input })
632 } 640 }
633 641
634 /// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths 642 /// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths
@@ -743,7 +751,38 @@ fn collect_attrs(
743 .chain(inner_docs.into_iter().flatten()) 751 .chain(inner_docs.into_iter().flatten())
744 .map(|docs_text| (docs_text.syntax().text_range().start(), Either::Right(docs_text))); 752 .map(|docs_text| (docs_text.syntax().text_range().start(), Either::Right(docs_text)));
745 // sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved 753 // sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved
746 let attrs: Vec<_> = docs.chain(attrs).sorted_by_key(|&(offset, _)| offset).collect(); 754 docs.chain(attrs).sorted_by_key(|&(offset, _)| offset).map(|(_, attr)| attr)
755}
756
757pub(crate) fn variants_attrs_source_map(
758 db: &dyn DefDatabase,
759 def: EnumId,
760) -> Arc<ArenaMap<LocalEnumVariantId, AstPtr<ast::Variant>>> {
761 let mut res = ArenaMap::default();
762 let child_source = def.child_source(db);
763
764 for (idx, variant) in child_source.value.iter() {
765 res.insert(idx, AstPtr::new(variant));
766 }
767
768 Arc::new(res)
769}
770
771pub(crate) fn fields_attrs_source_map(
772 db: &dyn DefDatabase,
773 def: VariantId,
774) -> Arc<ArenaMap<LocalFieldId, Either<AstPtr<ast::TupleField>, AstPtr<ast::RecordField>>>> {
775 let mut res = ArenaMap::default();
776 let child_source = def.child_source(db);
777
778 for (idx, variant) in child_source.value.iter() {
779 res.insert(
780 idx,
781 variant
782 .as_ref()
783 .either(|l| Either::Left(AstPtr::new(l)), |r| Either::Right(AstPtr::new(r))),
784 );
785 }
747 786
748 attrs.into_iter().map(|(_, attr)| attr) 787 Arc::new(res)
749} 788}
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 63e89a1f4..bfb75a8a5 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -30,6 +30,7 @@ use crate::{
30 LabelId, Literal, LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, 30 LabelId, Literal, LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField,
31 Statement, 31 Statement,
32 }, 32 },
33 intern::Interned,
33 item_scope::BuiltinShadowMode, 34 item_scope::BuiltinShadowMode,
34 path::{GenericArgs, Path}, 35 path::{GenericArgs, Path},
35 type_ref::{Mutability, Rawness, TypeRef}, 36 type_ref::{Mutability, Rawness, TypeRef},
@@ -322,8 +323,10 @@ impl ExprCollector<'_> {
322 Vec::new() 323 Vec::new()
323 }; 324 };
324 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); 325 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
325 let generic_args = 326 let generic_args = e
326 e.generic_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it)); 327 .generic_arg_list()
328 .and_then(|it| GenericArgs::from_ast(&self.ctx(), it))
329 .map(Box::new);
327 self.alloc_expr( 330 self.alloc_expr(
328 Expr::MethodCall { receiver, method_name, args, generic_args }, 331 Expr::MethodCall { receiver, method_name, args, generic_args },
329 syntax_ptr, 332 syntax_ptr,
@@ -385,7 +388,7 @@ impl ExprCollector<'_> {
385 self.alloc_expr(Expr::Yield { expr }, syntax_ptr) 388 self.alloc_expr(Expr::Yield { expr }, syntax_ptr)
386 } 389 }
387 ast::Expr::RecordExpr(e) => { 390 ast::Expr::RecordExpr(e) => {
388 let path = e.path().and_then(|path| self.expander.parse_path(path)); 391 let path = e.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
389 let record_lit = if let Some(nfl) = e.record_expr_field_list() { 392 let record_lit = if let Some(nfl) = e.record_expr_field_list() {
390 let fields = nfl 393 let fields = nfl
391 .fields() 394 .fields()
@@ -430,7 +433,7 @@ impl ExprCollector<'_> {
430 } 433 }
431 ast::Expr::CastExpr(e) => { 434 ast::Expr::CastExpr(e) => {
432 let expr = self.collect_expr_opt(e.expr()); 435 let expr = self.collect_expr_opt(e.expr());
433 let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.ty()); 436 let type_ref = Interned::new(TypeRef::from_ast_opt(&self.ctx(), e.ty()));
434 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) 437 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
435 } 438 }
436 ast::Expr::RefExpr(e) => { 439 ast::Expr::RefExpr(e) => {
@@ -464,13 +467,16 @@ impl ExprCollector<'_> {
464 if let Some(pl) = e.param_list() { 467 if let Some(pl) = e.param_list() {
465 for param in pl.params() { 468 for param in pl.params() {
466 let pat = self.collect_pat_opt(param.pat()); 469 let pat = self.collect_pat_opt(param.pat());
467 let type_ref = param.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); 470 let type_ref =
471 param.ty().map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
468 args.push(pat); 472 args.push(pat);
469 arg_types.push(type_ref); 473 arg_types.push(type_ref);
470 } 474 }
471 } 475 }
472 let ret_type = 476 let ret_type = e
473 e.ret_type().and_then(|r| r.ty()).map(|it| TypeRef::from_ast(&self.ctx(), it)); 477 .ret_type()
478 .and_then(|r| r.ty())
479 .map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
474 let body = self.collect_expr_opt(e.body()); 480 let body = self.collect_expr_opt(e.body());
475 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) 481 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
476 } 482 }
@@ -625,7 +631,8 @@ impl ExprCollector<'_> {
625 return; 631 return;
626 } 632 }
627 let pat = self.collect_pat_opt(stmt.pat()); 633 let pat = self.collect_pat_opt(stmt.pat());
628 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); 634 let type_ref =
635 stmt.ty().map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
629 let initializer = stmt.initializer().map(|e| self.collect_expr(e)); 636 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
630 self.statements_in_scope.push(Statement::Let { pat, type_ref, initializer }); 637 self.statements_in_scope.push(Statement::Let { pat, type_ref, initializer });
631 } 638 }
@@ -755,7 +762,7 @@ impl ExprCollector<'_> {
755 } 762 }
756 } 763 }
757 ast::Pat::TupleStructPat(p) => { 764 ast::Pat::TupleStructPat(p) => {
758 let path = p.path().and_then(|path| self.expander.parse_path(path)); 765 let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
759 let (args, ellipsis) = self.collect_tuple_pat(p.fields()); 766 let (args, ellipsis) = self.collect_tuple_pat(p.fields());
760 Pat::TupleStruct { path, args, ellipsis } 767 Pat::TupleStruct { path, args, ellipsis }
761 } 768 }
@@ -765,7 +772,7 @@ impl ExprCollector<'_> {
765 Pat::Ref { pat, mutability } 772 Pat::Ref { pat, mutability }
766 } 773 }
767 ast::Pat::PathPat(p) => { 774 ast::Pat::PathPat(p) => {
768 let path = p.path().and_then(|path| self.expander.parse_path(path)); 775 let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
769 path.map(Pat::Path).unwrap_or(Pat::Missing) 776 path.map(Pat::Path).unwrap_or(Pat::Missing)
770 } 777 }
771 ast::Pat::OrPat(p) => { 778 ast::Pat::OrPat(p) => {
@@ -779,7 +786,7 @@ impl ExprCollector<'_> {
779 } 786 }
780 ast::Pat::WildcardPat(_) => Pat::Wild, 787 ast::Pat::WildcardPat(_) => Pat::Wild,
781 ast::Pat::RecordPat(p) => { 788 ast::Pat::RecordPat(p) => {
782 let path = p.path().and_then(|path| self.expander.parse_path(path)); 789 let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
783 let args: Vec<_> = p 790 let args: Vec<_> = p
784 .record_pat_field_list() 791 .record_pat_field_list()
785 .expect("every struct should have a field list") 792 .expect("every struct should have a field list")
diff --git a/crates/hir_def/src/body/tests.rs b/crates/hir_def/src/body/tests.rs
index faa133297..c1d3e998f 100644
--- a/crates/hir_def/src/body/tests.rs
+++ b/crates/hir_def/src/body/tests.rs
@@ -143,7 +143,7 @@ fn f() {
143 //^^^^^^^^^^^^^ could not convert tokens 143 //^^^^^^^^^^^^^ could not convert tokens
144 144
145 env!("OUT_DIR"); 145 env!("OUT_DIR");
146 //^^^^^^^^^^^^^^^ `OUT_DIR` not set, enable "load out dirs from check" to fix 146 //^^^^^^^^^^^^^^^ `OUT_DIR` not set, enable "run build scripts" to fix
147 147
148 compile_error!("compile_error works"); 148 compile_error!("compile_error works");
149 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ compile_error works 149 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ compile_error works
diff --git a/crates/hir_def/src/child_by_source.rs b/crates/hir_def/src/child_by_source.rs
index f40a7f80d..f2e809ca9 100644
--- a/crates/hir_def/src/child_by_source.rs
+++ b/crates/hir_def/src/child_by_source.rs
@@ -80,6 +80,10 @@ impl ChildBySource for ModuleId {
80impl ChildBySource for ItemScope { 80impl ChildBySource for ItemScope {
81 fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { 81 fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) {
82 self.declarations().for_each(|item| add_module_def(db, res, item)); 82 self.declarations().for_each(|item| add_module_def(db, res, item));
83 self.unnamed_consts().for_each(|konst| {
84 let src = konst.lookup(db).source(db);
85 res[keys::CONST].insert(src, konst);
86 });
83 self.impls().for_each(|imp| add_impl(db, res, imp)); 87 self.impls().for_each(|imp| add_impl(db, res, imp));
84 88
85 fn add_module_def(db: &dyn DefDatabase, map: &mut DynMap, item: ModuleDefId) { 89 fn add_module_def(db: &dyn DefDatabase, map: &mut DynMap, item: ModuleDefId) {
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/expr.rs b/crates/hir_def/src/expr.rs
index 6c7376fad..b4ad984bd 100644
--- a/crates/hir_def/src/expr.rs
+++ b/crates/hir_def/src/expr.rs
@@ -18,6 +18,7 @@ use syntax::ast::RangeOp;
18 18
19use crate::{ 19use crate::{
20 builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint}, 20 builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
21 intern::Interned,
21 path::{GenericArgs, Path}, 22 path::{GenericArgs, Path},
22 type_ref::{Mutability, Rawness, TypeRef}, 23 type_ref::{Mutability, Rawness, TypeRef},
23 BlockId, 24 BlockId,
@@ -86,7 +87,7 @@ pub enum Expr {
86 receiver: ExprId, 87 receiver: ExprId,
87 method_name: Name, 88 method_name: Name,
88 args: Vec<ExprId>, 89 args: Vec<ExprId>,
89 generic_args: Option<GenericArgs>, 90 generic_args: Option<Box<GenericArgs>>,
90 }, 91 },
91 Match { 92 Match {
92 expr: ExprId, 93 expr: ExprId,
@@ -106,7 +107,7 @@ pub enum Expr {
106 expr: Option<ExprId>, 107 expr: Option<ExprId>,
107 }, 108 },
108 RecordLit { 109 RecordLit {
109 path: Option<Path>, 110 path: Option<Box<Path>>,
110 fields: Vec<RecordLitField>, 111 fields: Vec<RecordLitField>,
111 spread: Option<ExprId>, 112 spread: Option<ExprId>,
112 }, 113 },
@@ -131,7 +132,7 @@ pub enum Expr {
131 }, 132 },
132 Cast { 133 Cast {
133 expr: ExprId, 134 expr: ExprId,
134 type_ref: TypeRef, 135 type_ref: Interned<TypeRef>,
135 }, 136 },
136 Ref { 137 Ref {
137 expr: ExprId, 138 expr: ExprId,
@@ -161,8 +162,8 @@ pub enum Expr {
161 }, 162 },
162 Lambda { 163 Lambda {
163 args: Vec<PatId>, 164 args: Vec<PatId>,
164 arg_types: Vec<Option<TypeRef>>, 165 arg_types: Vec<Option<Interned<TypeRef>>>,
165 ret_type: Option<TypeRef>, 166 ret_type: Option<Interned<TypeRef>>,
166 body: ExprId, 167 body: ExprId,
167 }, 168 },
168 Tuple { 169 Tuple {
@@ -240,7 +241,7 @@ pub struct RecordLitField {
240 241
241#[derive(Debug, Clone, Eq, PartialEq)] 242#[derive(Debug, Clone, Eq, PartialEq)]
242pub enum Statement { 243pub enum Statement {
243 Let { pat: PatId, type_ref: Option<TypeRef>, initializer: Option<ExprId> }, 244 Let { pat: PatId, type_ref: Option<Interned<TypeRef>>, initializer: Option<ExprId> },
244 Expr(ExprId), 245 Expr(ExprId),
245} 246}
246 247
@@ -412,13 +413,13 @@ pub enum Pat {
412 Wild, 413 Wild,
413 Tuple { args: Vec<PatId>, ellipsis: Option<usize> }, 414 Tuple { args: Vec<PatId>, ellipsis: Option<usize> },
414 Or(Vec<PatId>), 415 Or(Vec<PatId>),
415 Record { path: Option<Path>, args: Vec<RecordFieldPat>, ellipsis: bool }, 416 Record { path: Option<Box<Path>>, args: Vec<RecordFieldPat>, ellipsis: bool },
416 Range { start: ExprId, end: ExprId }, 417 Range { start: ExprId, end: ExprId },
417 Slice { prefix: Vec<PatId>, slice: Option<PatId>, suffix: Vec<PatId> }, 418 Slice { prefix: Vec<PatId>, slice: Option<PatId>, suffix: Vec<PatId> },
418 Path(Path), 419 Path(Box<Path>),
419 Lit(ExprId), 420 Lit(ExprId),
420 Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> }, 421 Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> },
421 TupleStruct { path: Option<Path>, args: Vec<PatId>, ellipsis: Option<usize> }, 422 TupleStruct { path: Option<Box<Path>>, args: Vec<PatId>, ellipsis: Option<usize> },
422 Ref { pat: PatId, mutability: Mutability }, 423 Ref { pat: PatId, mutability: Mutability },
423 Box { inner: PatId }, 424 Box { inner: PatId },
424 ConstBlock(ExprId), 425 ConstBlock(ExprId),
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 be9a5e1a0..d69116d51 100644
--- a/crates/hir_def/src/lib.rs
+++ b/crates/hir_def/src/lib.rs
@@ -56,12 +56,13 @@ use std::{
56 sync::Arc, 56 sync::Arc,
57}; 57};
58 58
59use adt::VariantData;
59use base_db::{impl_intern_key, salsa, CrateId}; 60use base_db::{impl_intern_key, salsa, CrateId};
60use hir_expand::{ 61use hir_expand::{
61 ast_id_map::FileAstId, 62 ast_id_map::FileAstId,
62 eager::{expand_eager_macro, ErrorEmitted, ErrorSink}, 63 eager::{expand_eager_macro, ErrorEmitted, ErrorSink},
63 hygiene::Hygiene, 64 hygiene::Hygiene,
64 AstId, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, 65 AstId, AttrId, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
65}; 66};
66use la_arena::Idx; 67use la_arena::Idx;
67use nameres::DefMap; 68use nameres::DefMap;
@@ -442,6 +443,26 @@ pub enum VariantId {
442} 443}
443impl_from!(EnumVariantId, StructId, UnionId for VariantId); 444impl_from!(EnumVariantId, StructId, UnionId for VariantId);
444 445
446impl VariantId {
447 pub fn variant_data(self, db: &dyn db::DefDatabase) -> Arc<VariantData> {
448 match self {
449 VariantId::StructId(it) => db.struct_data(it).variant_data.clone(),
450 VariantId::UnionId(it) => db.union_data(it).variant_data.clone(),
451 VariantId::EnumVariantId(it) => {
452 db.enum_data(it.parent).variants[it.local_id].variant_data.clone()
453 }
454 }
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 }
464}
465
445trait Intern { 466trait Intern {
446 type ID; 467 type ID;
447 fn intern(self, db: &dyn db::DefDatabase) -> Self::ID; 468 fn intern(self, db: &dyn db::DefDatabase) -> Self::ID;
@@ -669,13 +690,16 @@ fn macro_call_as_call_id(
669 ) 690 )
670 .map(MacroCallId::from) 691 .map(MacroCallId::from)
671 } else { 692 } else {
672 Ok(def.as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike(call.ast_id)).into()) 693 Ok(def
694 .as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike { ast_id: call.ast_id })
695 .into())
673 }; 696 };
674 Ok(res) 697 Ok(res)
675} 698}
676 699
677fn derive_macro_as_call_id( 700fn derive_macro_as_call_id(
678 item_attr: &AstIdWithPath<ast::Item>, 701 item_attr: &AstIdWithPath<ast::Item>,
702 derive_attr: AttrId,
679 db: &dyn db::DefDatabase, 703 db: &dyn db::DefDatabase,
680 krate: CrateId, 704 krate: CrateId,
681 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, 705 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
@@ -686,7 +710,11 @@ fn derive_macro_as_call_id(
686 .as_lazy_macro( 710 .as_lazy_macro(
687 db.upcast(), 711 db.upcast(),
688 krate, 712 krate,
689 MacroCallKind::Derive(item_attr.ast_id, last_segment.to_string()), 713 MacroCallKind::Derive {
714 ast_id: item_attr.ast_id,
715 derive_name: last_segment.to_string(),
716 derive_attr,
717 },
690 ) 718 )
691 .into(); 719 .into();
692 Ok(res) 720 Ok(res)
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs
index 7dd68219f..9e181751c 100644
--- a/crates/hir_def/src/nameres.rs
+++ b/crates/hir_def/src/nameres.rs
@@ -613,12 +613,12 @@ mod diagnostics {
613 DiagnosticKind::UnresolvedProcMacro { ast } => { 613 DiagnosticKind::UnresolvedProcMacro { ast } => {
614 let mut precise_location = None; 614 let mut precise_location = None;
615 let (file, ast, name) = match ast { 615 let (file, ast, name) = match ast {
616 MacroCallKind::FnLike(ast) => { 616 MacroCallKind::FnLike { ast_id } => {
617 let node = ast.to_node(db.upcast()); 617 let node = ast_id.to_node(db.upcast());
618 (ast.file_id, SyntaxNodePtr::from(AstPtr::new(&node)), None) 618 (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)), None)
619 } 619 }
620 MacroCallKind::Derive(ast, name) => { 620 MacroCallKind::Derive { ast_id, derive_name, .. } => {
621 let node = ast.to_node(db.upcast()); 621 let node = ast_id.to_node(db.upcast());
622 622
623 // Compute the precise location of the macro name's token in the derive 623 // Compute the precise location of the macro name's token in the derive
624 // list. 624 // list.
@@ -639,7 +639,7 @@ mod diagnostics {
639 }); 639 });
640 for token in tokens { 640 for token in tokens {
641 if token.kind() == SyntaxKind::IDENT 641 if token.kind() == SyntaxKind::IDENT
642 && token.text() == name.as_str() 642 && token.text() == derive_name.as_str()
643 { 643 {
644 precise_location = Some(token.text_range()); 644 precise_location = Some(token.text_range());
645 break 'outer; 645 break 'outer;
@@ -648,9 +648,9 @@ mod diagnostics {
648 } 648 }
649 649
650 ( 650 (
651 ast.file_id, 651 ast_id.file_id,
652 SyntaxNodePtr::from(AstPtr::new(&node)), 652 SyntaxNodePtr::from(AstPtr::new(&node)),
653 Some(name.clone()), 653 Some(derive_name.clone()),
654 ) 654 )
655 } 655 }
656 }; 656 };
@@ -669,13 +669,13 @@ mod diagnostics {
669 669
670 DiagnosticKind::MacroError { ast, message } => { 670 DiagnosticKind::MacroError { ast, message } => {
671 let (file, ast) = match ast { 671 let (file, ast) = match ast {
672 MacroCallKind::FnLike(ast) => { 672 MacroCallKind::FnLike { ast_id, .. } => {
673 let node = ast.to_node(db.upcast()); 673 let node = ast_id.to_node(db.upcast());
674 (ast.file_id, SyntaxNodePtr::from(AstPtr::new(&node))) 674 (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)))
675 } 675 }
676 MacroCallKind::Derive(ast, _) => { 676 MacroCallKind::Derive { ast_id, .. } => {
677 let node = ast.to_node(db.upcast()); 677 let node = ast_id.to_node(db.upcast());
678 (ast.file_id, SyntaxNodePtr::from(AstPtr::new(&node))) 678 (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)))
679 } 679 }
680 }; 680 };
681 sink.push(MacroError { file, node: ast, message: message.clone() }); 681 sink.push(MacroError { file, node: ast, message: message.clone() });
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index f42f92702..fb4ddff5e 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -13,7 +13,7 @@ use hir_expand::{
13 builtin_macro::find_builtin_macro, 13 builtin_macro::find_builtin_macro,
14 name::{AsName, Name}, 14 name::{AsName, Name},
15 proc_macro::ProcMacroExpander, 15 proc_macro::ProcMacroExpander,
16 HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, 16 AttrId, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
17}; 17};
18use hir_expand::{InFile, MacroCallLoc}; 18use hir_expand::{InFile, MacroCallLoc};
19use rustc_hash::{FxHashMap, FxHashSet}; 19use rustc_hash::{FxHashMap, FxHashSet};
@@ -216,7 +216,7 @@ struct MacroDirective {
216#[derive(Clone, Debug, Eq, PartialEq)] 216#[derive(Clone, Debug, Eq, PartialEq)]
217enum MacroDirectiveKind { 217enum MacroDirectiveKind {
218 FnLike { ast_id: AstIdWithPath<ast::MacroCall> }, 218 FnLike { ast_id: AstIdWithPath<ast::MacroCall> },
219 Derive { ast_id: AstIdWithPath<ast::Item> }, 219 Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId },
220} 220}
221 221
222struct DefData<'a> { 222struct DefData<'a> {
@@ -478,7 +478,7 @@ impl DefCollector<'_> {
478 self.def_map.edition, 478 self.def_map.edition,
479 ); 479 );
480 480
481 let res = self.def_map.resolve_name_in_extern_prelude(&extern_crate.name); 481 let res = self.def_map.resolve_name_in_extern_prelude(self.db, &extern_crate.name);
482 482
483 if let Some(ModuleDefId::ModuleId(m)) = res.take_types() { 483 if let Some(ModuleDefId::ModuleId(m)) = res.take_types() {
484 cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use); 484 cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use);
@@ -534,6 +534,7 @@ impl DefCollector<'_> {
534 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition); 534 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition);
535 if import.is_extern_crate { 535 if import.is_extern_crate {
536 let res = self.def_map.resolve_name_in_extern_prelude( 536 let res = self.def_map.resolve_name_in_extern_prelude(
537 self.db,
537 &import 538 &import
538 .path 539 .path
539 .as_ident() 540 .as_ident()
@@ -831,12 +832,16 @@ impl DefCollector<'_> {
831 Err(UnresolvedMacro) | Ok(Err(_)) => {} 832 Err(UnresolvedMacro) | Ok(Err(_)) => {}
832 } 833 }
833 } 834 }
834 MacroDirectiveKind::Derive { ast_id } => { 835 MacroDirectiveKind::Derive { ast_id, derive_attr } => {
835 match derive_macro_as_call_id(ast_id, self.db, self.def_map.krate, |path| { 836 match derive_macro_as_call_id(
836 self.resolve_derive_macro(directive.module_id, &path) 837 ast_id,
837 }) { 838 *derive_attr,
839 self.db,
840 self.def_map.krate,
841 |path| self.resolve_derive_macro(directive.module_id, &path),
842 ) {
838 Ok(call_id) => { 843 Ok(call_id) => {
839 resolved.push((directive.module_id, call_id, 0)); 844 resolved.push((directive.module_id, call_id, directive.depth));
840 res = ReachedFixedPoint::No; 845 res = ReachedFixedPoint::No;
841 return false; 846 return false;
842 } 847 }
@@ -1163,19 +1168,27 @@ impl ModCollector<'_, '_> {
1163 } 1168 }
1164 ModItem::Const(id) => { 1169 ModItem::Const(id) => {
1165 let it = &self.item_tree[id]; 1170 let it = &self.item_tree[id];
1166 1171 let const_id = ConstLoc {
1167 if let Some(name) = &it.name { 1172 container: module.into(),
1168 def = Some(DefData { 1173 id: ItemTreeId::new(self.file_id, id),
1169 id: ConstLoc { 1174 }
1170 container: module.into(), 1175 .intern(self.def_collector.db);
1171 id: ItemTreeId::new(self.file_id, id), 1176
1172 } 1177 match &it.name {
1173 .intern(self.def_collector.db) 1178 Some(name) => {
1174 .into(), 1179 def = Some(DefData {
1175 name, 1180 id: const_id.into(),
1176 visibility: &self.item_tree[it.visibility], 1181 name,
1177 has_constructor: false, 1182 visibility: &self.item_tree[it.visibility],
1178 }); 1183 has_constructor: false,
1184 });
1185 }
1186 None => {
1187 // const _: T = ...;
1188 self.def_collector.def_map.modules[self.module_id]
1189 .scope
1190 .define_unnamed_const(const_id);
1191 }
1179 } 1192 }
1180 } 1193 }
1181 ModItem::Static(id) => { 1194 ModItem::Static(id) => {
@@ -1360,7 +1373,7 @@ impl ModCollector<'_, '_> {
1360 self.def_collector.unexpanded_macros.push(MacroDirective { 1373 self.def_collector.unexpanded_macros.push(MacroDirective {
1361 module_id: self.module_id, 1374 module_id: self.module_id,
1362 depth: self.macro_depth + 1, 1375 depth: self.macro_depth + 1,
1363 kind: MacroDirectiveKind::Derive { ast_id }, 1376 kind: MacroDirectiveKind::Derive { ast_id, derive_attr: derive.id },
1364 }); 1377 });
1365 } 1378 }
1366 } 1379 }
@@ -1512,7 +1525,7 @@ impl ModCollector<'_, '_> {
1512 // Built-in macro failed eager expansion. 1525 // Built-in macro failed eager expansion.
1513 self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error( 1526 self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error(
1514 self.module_id, 1527 self.module_id,
1515 MacroCallKind::FnLike(ast_id.ast_id), 1528 MacroCallKind::FnLike { ast_id: ast_id.ast_id },
1516 error.unwrap().to_string(), 1529 error.unwrap().to_string(),
1517 )); 1530 ));
1518 return; 1531 return;
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs
index 60471937c..ccc9f22eb 100644
--- a/crates/hir_def/src/nameres/path_resolution.rs
+++ b/crates/hir_def/src/nameres/path_resolution.rs
@@ -60,12 +60,26 @@ impl ResolvePathResult {
60} 60}
61 61
62impl DefMap { 62impl DefMap {
63 pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs { 63 pub(super) fn resolve_name_in_extern_prelude(
64 &self,
65 db: &dyn DefDatabase,
66 name: &Name,
67 ) -> PerNs {
64 if name == &name!(self) { 68 if name == &name!(self) {
65 cov_mark::hit!(extern_crate_self_as); 69 cov_mark::hit!(extern_crate_self_as);
66 return PerNs::types(self.module_id(self.root).into(), Visibility::Public); 70 return PerNs::types(self.module_id(self.root).into(), Visibility::Public);
67 } 71 }
68 self.extern_prelude 72
73 let arc;
74 let root = match self.block {
75 Some(_) => {
76 arc = self.crate_root(db).def_map(db);
77 &*arc
78 }
79 None => self,
80 };
81
82 root.extern_prelude
69 .get(name) 83 .get(name)
70 .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)) 84 .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public))
71 } 85 }
@@ -191,7 +205,7 @@ impl DefMap {
191 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), 205 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
192 }; 206 };
193 log::debug!("resolving {:?} in crate root (+ extern prelude)", segment); 207 log::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
194 self.resolve_name_in_crate_root_or_extern_prelude(&segment) 208 self.resolve_name_in_crate_root_or_extern_prelude(db, &segment)
195 } 209 }
196 PathKind::Plain => { 210 PathKind::Plain => {
197 let (_, segment) = match segments.next() { 211 let (_, segment) = match segments.next() {
@@ -384,24 +398,31 @@ impl DefMap {
384 } 398 }
385 } 399 }
386 }; 400 };
387 // Give precedence to names in outer `DefMap`s over the extern prelude; only check prelude 401 let from_extern_prelude = self
388 // from the crate DefMap. 402 .extern_prelude
389 let from_extern_prelude = match self.block { 403 .get(name)
390 Some(_) => PerNs::none(), 404 .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public));
391 None => self
392 .extern_prelude
393 .get(name)
394 .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)),
395 };
396 405
397 let from_prelude = self.resolve_in_prelude(db, name); 406 let from_prelude = self.resolve_in_prelude(db, name);
398 407
399 from_legacy_macro.or(from_scope_or_builtin).or(from_extern_prelude).or(from_prelude) 408 from_legacy_macro.or(from_scope_or_builtin).or(from_extern_prelude).or(from_prelude)
400 } 409 }
401 410
402 fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs { 411 fn resolve_name_in_crate_root_or_extern_prelude(
403 let from_crate_root = self[self.root].scope.get(name); 412 &self,
404 let from_extern_prelude = self.resolve_name_in_extern_prelude(name); 413 db: &dyn DefDatabase,
414 name: &Name,
415 ) -> PerNs {
416 let arc;
417 let crate_def_map = match self.block {
418 Some(_) => {
419 arc = self.crate_root(db).def_map(db);
420 &arc
421 }
422 None => self,
423 };
424 let from_crate_root = crate_def_map[crate_def_map.root].scope.get(name);
425 let from_extern_prelude = self.resolve_name_in_extern_prelude(db, name);
405 426
406 from_crate_root.or(from_extern_prelude) 427 from_crate_root.or(from_extern_prelude)
407 } 428 }
diff --git a/crates/hir_def/src/nameres/tests/diagnostics.rs b/crates/hir_def/src/nameres/tests/diagnostics.rs
index fefdadb22..1ac88fc89 100644
--- a/crates/hir_def/src/nameres/tests/diagnostics.rs
+++ b/crates/hir_def/src/nameres/tests/diagnostics.rs
@@ -233,7 +233,7 @@ fn good_out_dir_diagnostic() {
233 macro_rules! concat { () => {} } 233 macro_rules! concat { () => {} }
234 234
235 include!(concat!(env!("OUT_DIR"), "/out.rs")); 235 include!(concat!(env!("OUT_DIR"), "/out.rs"));
236 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `OUT_DIR` not set, enable "load out dirs from check" to fix 236 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `OUT_DIR` not set, enable "run build scripts" to fix
237 "#, 237 "#,
238 ); 238 );
239} 239}
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs
index f9c8328f0..b528ff8ba 100644
--- a/crates/hir_def/src/path.rs
+++ b/crates/hir_def/src/path.rs
@@ -289,6 +289,12 @@ impl From<Name> for Path {
289 } 289 }
290} 290}
291 291
292impl From<Name> for Box<Path> {
293 fn from(name: Name) -> Box<Path> {
294 Box::new(Path::from(name))
295 }
296}
297
292impl From<Name> for ModPath { 298impl From<Name> for ModPath {
293 fn from(name: Name) -> ModPath { 299 fn from(name: Name) -> ModPath {
294 ModPath::from_segments(PathKind::Plain, iter::once(name)) 300 ModPath::from_segments(PathKind::Plain, iter::once(name))
diff --git a/crates/hir_expand/src/builtin_derive.rs b/crates/hir_expand/src/builtin_derive.rs
index 6ece4b289..537c03028 100644
--- a/crates/hir_expand/src/builtin_derive.rs
+++ b/crates/hir_expand/src/builtin_derive.rs
@@ -269,7 +269,7 @@ mod tests {
269 use expect_test::{expect, Expect}; 269 use expect_test::{expect, Expect};
270 use name::AsName; 270 use name::AsName;
271 271
272 use crate::{test_db::TestDB, AstId, MacroCallId, MacroCallKind, MacroCallLoc}; 272 use crate::{test_db::TestDB, AstId, AttrId, MacroCallId, MacroCallKind, MacroCallLoc};
273 273
274 use super::*; 274 use super::*;
275 275
@@ -308,7 +308,7 @@ $0
308 308
309 let expander = BuiltinDeriveExpander::find_by_name(&name).unwrap(); 309 let expander = BuiltinDeriveExpander::find_by_name(&name).unwrap();
310 310
311 let attr_id = AstId::new(file_id.into(), ast_id_map.ast_id(&items[0])); 311 let ast_id = AstId::new(file_id.into(), ast_id_map.ast_id(&items[0]));
312 312
313 let loc = MacroCallLoc { 313 let loc = MacroCallLoc {
314 def: MacroDefId { 314 def: MacroDefId {
@@ -317,7 +317,11 @@ $0
317 local_inner: false, 317 local_inner: false,
318 }, 318 },
319 krate: CrateId(0), 319 krate: CrateId(0),
320 kind: MacroCallKind::Derive(attr_id, name.to_string()), 320 kind: MacroCallKind::Derive {
321 ast_id,
322 derive_name: name.to_string(),
323 derive_attr: AttrId(0),
324 },
321 }; 325 };
322 326
323 let id: MacroCallId = db.intern_macro(loc).into(); 327 let id: MacroCallId = db.intern_macro(loc).into();
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs
index 75ec4196b..80365fc16 100644
--- a/crates/hir_expand/src/builtin_macro.rs
+++ b/crates/hir_expand/src/builtin_macro.rs
@@ -490,7 +490,7 @@ fn env_expand(
490 // unnecessary diagnostics for eg. `CARGO_PKG_NAME`. 490 // unnecessary diagnostics for eg. `CARGO_PKG_NAME`.
491 if key == "OUT_DIR" { 491 if key == "OUT_DIR" {
492 err = Some(mbe::ExpandError::Other( 492 err = Some(mbe::ExpandError::Other(
493 r#"`OUT_DIR` not set, enable "load out dirs from check" to fix"#.into(), 493 r#"`OUT_DIR` not set, enable "run build scripts" to fix"#.into(),
494 )); 494 ));
495 } 495 }
496 496
@@ -566,10 +566,9 @@ mod tests {
566 let loc = MacroCallLoc { 566 let loc = MacroCallLoc {
567 def, 567 def,
568 krate, 568 krate,
569 kind: MacroCallKind::FnLike(AstId::new( 569 kind: MacroCallKind::FnLike {
570 file_id.into(), 570 ast_id: AstId::new(file_id.into(), ast_id_map.ast_id(&macro_call)),
571 ast_id_map.ast_id(&macro_call), 571 },
572 )),
573 }; 572 };
574 573
575 let id: MacroCallId = db.intern_macro(loc).into(); 574 let id: MacroCallId = db.intern_macro(loc).into();
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs
index 9705526fa..ef126e4ad 100644
--- a/crates/hir_expand/src/eager.rs
+++ b/crates/hir_expand/src/eager.rs
@@ -174,8 +174,9 @@ fn lazy_expand(
174) -> ExpandResult<Option<InFile<SyntaxNode>>> { 174) -> ExpandResult<Option<InFile<SyntaxNode>>> {
175 let ast_id = db.ast_id_map(macro_call.file_id).ast_id(&macro_call.value); 175 let ast_id = db.ast_id_map(macro_call.file_id).ast_id(&macro_call.value);
176 176
177 let id: MacroCallId = 177 let id: MacroCallId = def
178 def.as_lazy_macro(db, krate, MacroCallKind::FnLike(macro_call.with_value(ast_id))).into(); 178 .as_lazy_macro(db, krate, MacroCallKind::FnLike { ast_id: macro_call.with_value(ast_id) })
179 .into();
179 180
180 let err = db.macro_expand_error(id); 181 let err = db.macro_expand_error(id);
181 let value = db.parse_or_expand(id.as_file()).map(|node| InFile::new(id.as_file(), node)); 182 let value = db.parse_or_expand(id.as_file()).map(|node| InFile::new(id.as_file(), node));
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs
index 3e332ee47..a0e6aec62 100644
--- a/crates/hir_expand/src/lib.rs
+++ b/crates/hir_expand/src/lib.rs
@@ -290,22 +290,27 @@ pub struct MacroCallLoc {
290 290
291#[derive(Debug, Clone, PartialEq, Eq, Hash)] 291#[derive(Debug, Clone, PartialEq, Eq, Hash)]
292pub enum MacroCallKind { 292pub enum MacroCallKind {
293 FnLike(AstId<ast::MacroCall>), 293 FnLike { ast_id: AstId<ast::MacroCall> },
294 Derive(AstId<ast::Item>, String), 294 Derive { ast_id: AstId<ast::Item>, derive_name: String, derive_attr: AttrId },
295} 295}
296 296
297#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
298pub struct AttrId(pub u32);
299
297impl MacroCallKind { 300impl MacroCallKind {
298 fn file_id(&self) -> HirFileId { 301 fn file_id(&self) -> HirFileId {
299 match self { 302 match self {
300 MacroCallKind::FnLike(ast_id) => ast_id.file_id, 303 MacroCallKind::FnLike { ast_id, .. } => ast_id.file_id,
301 MacroCallKind::Derive(ast_id, _) => ast_id.file_id, 304 MacroCallKind::Derive { ast_id, .. } => ast_id.file_id,
302 } 305 }
303 } 306 }
304 307
305 fn node(&self, db: &dyn db::AstDatabase) -> InFile<SyntaxNode> { 308 fn node(&self, db: &dyn db::AstDatabase) -> InFile<SyntaxNode> {
306 match self { 309 match self {
307 MacroCallKind::FnLike(ast_id) => ast_id.with_value(ast_id.to_node(db).syntax().clone()), 310 MacroCallKind::FnLike { ast_id, .. } => {
308 MacroCallKind::Derive(ast_id, _) => { 311 ast_id.with_value(ast_id.to_node(db).syntax().clone())
312 }
313 MacroCallKind::Derive { ast_id, .. } => {
309 ast_id.with_value(ast_id.to_node(db).syntax().clone()) 314 ast_id.with_value(ast_id.to_node(db).syntax().clone())
310 } 315 }
311 } 316 }
@@ -313,10 +318,10 @@ impl MacroCallKind {
313 318
314 fn arg(&self, db: &dyn db::AstDatabase) -> Option<SyntaxNode> { 319 fn arg(&self, db: &dyn db::AstDatabase) -> Option<SyntaxNode> {
315 match self { 320 match self {
316 MacroCallKind::FnLike(ast_id) => { 321 MacroCallKind::FnLike { ast_id, .. } => {
317 Some(ast_id.to_node(db).token_tree()?.syntax().clone()) 322 Some(ast_id.to_node(db).token_tree()?.syntax().clone())
318 } 323 }
319 MacroCallKind::Derive(ast_id, _) => Some(ast_id.to_node(db).syntax().clone()), 324 MacroCallKind::Derive { ast_id, .. } => Some(ast_id.to_node(db).syntax().clone()),
320 } 325 }
321 } 326 }
322} 327}
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs
index 7ca4af80e..71bc436e6 100644
--- a/crates/hir_ty/src/autoderef.rs
+++ b/crates/hir_ty/src/autoderef.rs
@@ -6,14 +6,15 @@
6use std::iter::successors; 6use std::iter::successors;
7 7
8use base_db::CrateId; 8use base_db::CrateId;
9use chalk_ir::cast::Cast; 9use chalk_ir::{cast::Cast, fold::Fold, interner::HasInterner, VariableKind};
10use hir_def::lang_item::LangItemTarget; 10use hir_def::lang_item::LangItemTarget;
11use hir_expand::name::name; 11use hir_expand::name::name;
12use log::{info, warn}; 12use log::{info, warn};
13 13
14use crate::{ 14use crate::{
15 db::HirDatabase, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, 15 db::HirDatabase, static_lifetime, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds,
16 InEnvironment, Interner, Solution, Ty, TyBuilder, TyKind, 16 DebruijnIndex, InEnvironment, Interner, ProjectionTyExt, Solution, Substitution, Ty, TyBuilder,
17 TyKind,
17}; 18};
18 19
19const AUTODEREF_RECURSION_LIMIT: usize = 10; 20const AUTODEREF_RECURSION_LIMIT: usize = 10;
@@ -35,13 +36,21 @@ pub(crate) fn deref(
35 krate: CrateId, 36 krate: CrateId,
36 ty: InEnvironment<&Canonical<Ty>>, 37 ty: InEnvironment<&Canonical<Ty>>,
37) -> Option<Canonical<Ty>> { 38) -> Option<Canonical<Ty>> {
38 if let Some(derefed) = ty.goal.value.builtin_deref() { 39 if let Some(derefed) = builtin_deref(&ty.goal.value) {
39 Some(Canonical { value: derefed, binders: ty.goal.binders.clone() }) 40 Some(Canonical { value: derefed, binders: ty.goal.binders.clone() })
40 } else { 41 } else {
41 deref_by_trait(db, krate, ty) 42 deref_by_trait(db, krate, ty)
42 } 43 }
43} 44}
44 45
46fn builtin_deref(ty: &Ty) -> Option<Ty> {
47 match ty.kind(&Interner) {
48 TyKind::Ref(.., ty) => Some(ty.clone()),
49 TyKind::Raw(.., ty) => Some(ty.clone()),
50 _ => None,
51 }
52}
53
45fn deref_by_trait( 54fn deref_by_trait(
46 db: &dyn HirDatabase, 55 db: &dyn HirDatabase,
47 krate: CrateId, 56 krate: CrateId,
@@ -95,7 +104,7 @@ fn deref_by_trait(
95 binders: CanonicalVarKinds::from_iter( 104 binders: CanonicalVarKinds::from_iter(
96 &Interner, 105 &Interner,
97 ty.goal.binders.iter(&Interner).cloned().chain(Some(chalk_ir::WithKind::new( 106 ty.goal.binders.iter(&Interner).cloned().chain(Some(chalk_ir::WithKind::new(
98 chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), 107 VariableKind::Ty(chalk_ir::TyVariableKind::General),
99 chalk_ir::UniverseIndex::ROOT, 108 chalk_ir::UniverseIndex::ROOT,
100 ))), 109 ))),
101 ), 110 ),
@@ -120,23 +129,25 @@ fn deref_by_trait(
120 // assumptions will be broken. We would need to properly introduce 129 // assumptions will be broken. We would need to properly introduce
121 // new variables in that case 130 // new variables in that case
122 131
123 for i in 1..vars.0.binders.len(&Interner) { 132 for i in 1..vars.binders.len(&Interner) {
124 if vars.0.value.at(&Interner, i - 1).assert_ty_ref(&Interner).kind(&Interner) 133 if vars.value.subst.at(&Interner, i - 1).assert_ty_ref(&Interner).kind(&Interner)
125 != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) 134 != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1))
126 { 135 {
127 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution); 136 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution);
128 return None; 137 return None;
129 } 138 }
130 } 139 }
131 Some(Canonical { 140 // FIXME: we remove lifetime variables here since they can confuse
141 // the method resolution code later
142 Some(fixup_lifetime_variables(Canonical {
132 value: vars 143 value: vars
133 .0
134 .value 144 .value
135 .at(&Interner, vars.0.value.len(&Interner) - 1) 145 .subst
146 .at(&Interner, vars.value.subst.len(&Interner) - 1)
136 .assert_ty_ref(&Interner) 147 .assert_ty_ref(&Interner)
137 .clone(), 148 .clone(),
138 binders: vars.0.binders.clone(), 149 binders: vars.binders.clone(),
139 }) 150 }))
140 } 151 }
141 Solution::Ambig(_) => { 152 Solution::Ambig(_) => {
142 info!("Ambiguous solution for derefing {:?}: {:?}", ty.goal, solution); 153 info!("Ambiguous solution for derefing {:?}: {:?}", ty.goal, solution);
@@ -144,3 +155,32 @@ fn deref_by_trait(
144 } 155 }
145 } 156 }
146} 157}
158
159fn fixup_lifetime_variables<T: Fold<Interner, Result = T> + HasInterner<Interner = Interner>>(
160 c: Canonical<T>,
161) -> Canonical<T> {
162 // Removes lifetime variables from the Canonical, replacing them by static lifetimes.
163 let mut i = 0;
164 let subst = Substitution::from_iter(
165 &Interner,
166 c.binders.iter(&Interner).map(|vk| match vk.kind {
167 VariableKind::Ty(_) => {
168 let index = i;
169 i += 1;
170 BoundVar::new(DebruijnIndex::INNERMOST, index).to_ty(&Interner).cast(&Interner)
171 }
172 VariableKind::Lifetime => static_lifetime().cast(&Interner),
173 VariableKind::Const(_) => unimplemented!(),
174 }),
175 );
176 let binders = CanonicalVarKinds::from_iter(
177 &Interner,
178 c.binders.iter(&Interner).filter(|vk| match vk.kind {
179 VariableKind::Ty(_) => true,
180 VariableKind::Lifetime => false,
181 VariableKind::Const(_) => true,
182 }),
183 );
184 let value = subst.apply(c.value, &Interner);
185 Canonical { binders, value }
186}
diff --git a/crates/hir_ty/src/builder.rs b/crates/hir_ty/src/builder.rs
index 9b2c6975a..e25ef866d 100644
--- a/crates/hir_ty/src/builder.rs
+++ b/crates/hir_ty/src/builder.rs
@@ -4,6 +4,7 @@ use std::iter;
4 4
5use chalk_ir::{ 5use chalk_ir::{
6 cast::{Cast, CastTo, Caster}, 6 cast::{Cast, CastTo, Caster},
7 fold::Fold,
7 interner::HasInterner, 8 interner::HasInterner,
8 AdtId, BoundVar, DebruijnIndex, Safety, Scalar, 9 AdtId, BoundVar, DebruijnIndex, Safety, Scalar,
9}; 10};
@@ -12,8 +13,8 @@ use smallvec::SmallVec;
12 13
13use crate::{ 14use crate::{
14 db::HirDatabase, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders, 15 db::HirDatabase, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders,
15 CallableSig, FnPointer, FnSig, GenericArg, Interner, ProjectionTy, Substitution, TraitRef, Ty, 16 CallableSig, FnPointer, FnSig, FnSubst, GenericArg, Interner, ProjectionTy, Substitution,
16 TyDefId, TyKind, TypeWalk, ValueTyDefId, 17 TraitRef, Ty, TyDefId, TyExt, TyKind, ValueTyDefId,
17}; 18};
18 19
19/// This is a builder for `Ty` or anything that needs a `Substitution`. 20/// This is a builder for `Ty` or anything that needs a `Substitution`.
@@ -32,8 +33,7 @@ impl<D> TyBuilder<D> {
32 33
33 fn build_internal(self) -> (D, Substitution) { 34 fn build_internal(self) -> (D, Substitution) {
34 assert_eq!(self.vec.len(), self.param_count); 35 assert_eq!(self.vec.len(), self.param_count);
35 // FIXME: would be good to have a way to construct a chalk_ir::Substitution from the interned form 36 let subst = Substitution::from_iter(&Interner, self.vec);
36 let subst = Substitution::intern(self.vec);
37 (self.data, subst) 37 (self.data, subst)
38 } 38 }
39 39
@@ -78,9 +78,12 @@ impl TyBuilder<()> {
78 78
79 pub fn fn_ptr(sig: CallableSig) -> Ty { 79 pub fn fn_ptr(sig: CallableSig) -> Ty {
80 TyKind::Function(FnPointer { 80 TyKind::Function(FnPointer {
81 num_args: sig.params().len(), 81 num_binders: 0,
82 sig: FnSig { abi: (), safety: Safety::Safe, variadic: sig.is_varargs }, 82 sig: FnSig { abi: (), safety: Safety::Safe, variadic: sig.is_varargs },
83 substs: Substitution::from_iter(&Interner, sig.params_and_return.iter().cloned()), 83 substitution: FnSubst(Substitution::from_iter(
84 &Interner,
85 sig.params_and_return.iter().cloned(),
86 )),
84 }) 87 })
85 .intern(&Interner) 88 .intern(&Interner)
86 } 89 }
@@ -138,7 +141,7 @@ impl TyBuilder<hir_def::AdtId> {
138 self.vec.push(fallback().cast(&Interner)); 141 self.vec.push(fallback().cast(&Interner));
139 } else { 142 } else {
140 // each default can depend on the previous parameters 143 // each default can depend on the previous parameters
141 let subst_so_far = Substitution::intern(self.vec.clone()); 144 let subst_so_far = Substitution::from_iter(&Interner, self.vec.clone());
142 self.vec 145 self.vec
143 .push(default_ty.clone().substitute(&Interner, &subst_so_far).cast(&Interner)); 146 .push(default_ty.clone().substitute(&Interner, &subst_so_far).cast(&Interner));
144 } 147 }
@@ -193,13 +196,13 @@ impl TyBuilder<TypeAliasId> {
193 } 196 }
194} 197}
195 198
196impl<T: TypeWalk + HasInterner<Interner = Interner>> TyBuilder<Binders<T>> { 199impl<T: HasInterner<Interner = Interner> + Fold<Interner>> TyBuilder<Binders<T>> {
197 fn subst_binders(b: Binders<T>) -> Self { 200 fn subst_binders(b: Binders<T>) -> Self {
198 let param_count = b.binders.len(&Interner); 201 let param_count = b.binders.len(&Interner);
199 TyBuilder::new(b, param_count) 202 TyBuilder::new(b, param_count)
200 } 203 }
201 204
202 pub fn build(self) -> T { 205 pub fn build(self) -> <T as Fold<Interner>>::Result {
203 let (b, subst) = self.build_internal(); 206 let (b, subst) = self.build_internal();
204 b.substitute(&Interner, &subst) 207 b.substitute(&Interner, &subst)
205 } 208 }
diff --git a/crates/hir_ty/src/chalk_cast.rs b/crates/hir_ty/src/chalk_cast.rs
deleted file mode 100644
index df6492113..000000000
--- a/crates/hir_ty/src/chalk_cast.rs
+++ /dev/null
@@ -1,73 +0,0 @@
1//! Implementations of the Chalk `Cast` trait for our types.
2
3use chalk_ir::{
4 cast::{Cast, CastTo},
5 interner::HasInterner,
6};
7
8use crate::{AliasEq, DomainGoal, GenericArg, GenericArgData, Interner, TraitRef, Ty, WhereClause};
9
10macro_rules! has_interner {
11 ($t:ty) => {
12 impl HasInterner for $t {
13 type Interner = crate::Interner;
14 }
15 };
16}
17
18has_interner!(WhereClause);
19has_interner!(DomainGoal);
20has_interner!(GenericArg);
21has_interner!(Ty);
22
23impl CastTo<WhereClause> for TraitRef {
24 fn cast_to(self, _interner: &Interner) -> WhereClause {
25 WhereClause::Implemented(self)
26 }
27}
28
29impl CastTo<WhereClause> for AliasEq {
30 fn cast_to(self, _interner: &Interner) -> WhereClause {
31 WhereClause::AliasEq(self)
32 }
33}
34
35impl CastTo<DomainGoal> for WhereClause {
36 fn cast_to(self, _interner: &Interner) -> DomainGoal {
37 DomainGoal::Holds(self)
38 }
39}
40
41impl CastTo<GenericArg> for Ty {
42 fn cast_to(self, interner: &Interner) -> GenericArg {
43 GenericArg::new(interner, GenericArgData::Ty(self))
44 }
45}
46
47macro_rules! transitive_impl {
48 ($a:ty, $b:ty, $c:ty) => {
49 impl CastTo<$c> for $a {
50 fn cast_to(self, interner: &Interner) -> $c {
51 self.cast::<$b>(interner).cast(interner)
52 }
53 }
54 };
55}
56
57// In Chalk, these can be done as blanket impls, but that doesn't work here
58// because of coherence
59
60transitive_impl!(TraitRef, WhereClause, DomainGoal);
61transitive_impl!(AliasEq, WhereClause, DomainGoal);
62
63macro_rules! reflexive_impl {
64 ($a:ty) => {
65 impl CastTo<$a> for $a {
66 fn cast_to(self, _interner: &Interner) -> $a {
67 self
68 }
69 }
70 };
71}
72
73reflexive_impl!(GenericArg);
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/chalk_db.rs
index dff87ef70..8f054d06b 100644
--- a/crates/hir_ty/src/traits/chalk.rs
+++ b/crates/hir_ty/src/chalk_db.rs
@@ -1,52 +1,47 @@
1//! Conversion code from/to Chalk. 1//! The implementation of `RustIrDatabase` for Chalk, which provides information
2//! about the code that Chalk needs.
2use std::sync::Arc; 3use std::sync::Arc;
3 4
4use log::debug; 5use log::debug;
5 6
6use chalk_ir::{fold::shift::Shift, CanonicalVarKinds}; 7use chalk_ir::{cast::Cast, fold::shift::Shift, CanonicalVarKinds};
7use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait}; 8use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait};
8 9
9use base_db::{salsa::InternKey, CrateId}; 10use base_db::CrateId;
10use hir_def::{ 11use hir_def::{
11 lang_item::{lang_attr, LangItemTarget}, 12 lang_item::{lang_attr, LangItemTarget},
12 AssocContainerId, AssocItemId, HasModule, Lookup, TypeAliasId, 13 AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId,
13}; 14};
14use hir_expand::name::name; 15use hir_expand::name::name;
15 16
16use super::ChalkContext;
17use crate::{ 17use crate::{
18 db::HirDatabase, 18 db::HirDatabase,
19 display::HirDisplay, 19 display::HirDisplay,
20 from_assoc_type_id, 20 from_assoc_type_id, from_chalk_trait_id, make_only_type_binders,
21 mapping::{from_chalk, ToChalk, TypeAliasAsValue},
21 method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, 22 method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
22 to_assoc_type_id, to_chalk_trait_id, 23 to_assoc_type_id, to_chalk_trait_id,
24 traits::ChalkContext,
23 utils::generics, 25 utils::generics,
24 AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, ProjectionTy, Substitution, 26 AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, Interner, ProjectionTy,
25 TraitRef, Ty, TyBuilder, TyKind, WhereClause, 27 ProjectionTyExt, QuantifiedWhereClause, Substitution, TraitRef, TraitRefExt, Ty, TyBuilder,
28 TyExt, TyKind, WhereClause,
26}; 29};
27use mapping::{
28 convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue,
29};
30
31pub use self::interner::Interner;
32pub(crate) use self::interner::*;
33 30
34pub(super) mod tls; 31pub(crate) type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>;
35mod interner; 32pub(crate) type TraitDatum = chalk_solve::rust_ir::TraitDatum<Interner>;
36mod mapping; 33pub(crate) type StructDatum = chalk_solve::rust_ir::AdtDatum<Interner>;
37 34pub(crate) type ImplDatum = chalk_solve::rust_ir::ImplDatum<Interner>;
38pub(crate) trait ToChalk { 35pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum<Interner>;
39 type Chalk; 36
40 fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk; 37pub(crate) type AssocTypeId = chalk_ir::AssocTypeId<Interner>;
41 fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self; 38pub(crate) type TraitId = chalk_ir::TraitId<Interner>;
42} 39pub(crate) type AdtId = chalk_ir::AdtId<Interner>;
43 40pub(crate) type ImplId = chalk_ir::ImplId<Interner>;
44pub(crate) fn from_chalk<T, ChalkT>(db: &dyn HirDatabase, chalk: ChalkT) -> T 41pub(crate) type AssociatedTyValueId = chalk_solve::rust_ir::AssociatedTyValueId<Interner>;
45where 42pub(crate) type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue<Interner>;
46 T: ToChalk<Chalk = ChalkT>, 43pub(crate) type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>;
47{ 44pub(crate) type Variances = chalk_ir::Variances<Interner>;
48 T::from_chalk(db, chalk)
49}
50 45
51impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { 46impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
52 fn associated_ty_data(&self, id: AssocTypeId) -> Arc<AssociatedTyDatum> { 47 fn associated_ty_data(&self, id: AssocTypeId) -> Arc<AssociatedTyDatum> {
@@ -84,9 +79,9 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
84 binders: &CanonicalVarKinds<Interner>, 79 binders: &CanonicalVarKinds<Interner>,
85 ) -> Vec<ImplId> { 80 ) -> Vec<ImplId> {
86 debug!("impls_for_trait {:?}", trait_id); 81 debug!("impls_for_trait {:?}", trait_id);
87 let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); 82 let trait_: hir_def::TraitId = from_chalk_trait_id(trait_id);
88 83
89 let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref(&Interner).clone()); 84 let ty: Ty = parameters[0].assert_ty_ref(&Interner).clone();
90 85
91 fn binder_kind( 86 fn binder_kind(
92 ty: &Ty, 87 ty: &Ty,
@@ -103,7 +98,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
103 None 98 None
104 } 99 }
105 100
106 let self_ty_fp = TyFingerprint::for_impl(&ty); 101 let self_ty_fp = TyFingerprint::for_trait_impl(&ty);
107 let fps: &[TyFingerprint] = match binder_kind(&ty, binders) { 102 let fps: &[TyFingerprint] = match binder_kind(&ty, binders) {
108 Some(chalk_ir::TyVariableKind::Integer) => &ALL_INT_FPS, 103 Some(chalk_ir::TyVariableKind::Integer) => &ALL_INT_FPS,
109 Some(chalk_ir::TyVariableKind::Float) => &ALL_FLOAT_FPS, 104 Some(chalk_ir::TyVariableKind::Float) => &ALL_FLOAT_FPS,
@@ -166,7 +161,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
166 Some(LangItemTarget::TraitId(trait_)) => trait_, 161 Some(LangItemTarget::TraitId(trait_)) => trait_,
167 _ => return None, 162 _ => return None,
168 }; 163 };
169 Some(trait_.to_chalk(self.db)) 164 Some(to_chalk_trait_id(trait_))
170 } 165 }
171 166
172 fn program_clauses_for_env( 167 fn program_clauses_for_env(
@@ -187,16 +182,11 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
187 let (datas, binders) = (*datas).as_ref().into_value_and_skipped_binders(); 182 let (datas, binders) = (*datas).as_ref().into_value_and_skipped_binders();
188 let data = &datas.impl_traits[idx as usize]; 183 let data = &datas.impl_traits[idx as usize];
189 let bound = OpaqueTyDatumBound { 184 let bound = OpaqueTyDatumBound {
190 bounds: make_binders( 185 bounds: make_only_type_binders(
191 data.bounds
192 .skip_binders()
193 .iter()
194 .cloned()
195 .map(|b| b.to_chalk(self.db))
196 .collect(),
197 1, 186 1,
187 data.bounds.skip_binders().iter().cloned().collect(),
198 ), 188 ),
199 where_clauses: make_binders(vec![], 0), 189 where_clauses: make_only_type_binders(0, vec![]),
200 }; 190 };
201 chalk_ir::Binders::new(binders, bound) 191 chalk_ir::Binders::new(binders, bound)
202 } 192 }
@@ -220,7 +210,8 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
220 let impl_bound = WhereClause::Implemented(TraitRef { 210 let impl_bound = WhereClause::Implemented(TraitRef {
221 trait_id: to_chalk_trait_id(future_trait), 211 trait_id: to_chalk_trait_id(future_trait),
222 // Self type as the first parameter. 212 // Self type as the first parameter.
223 substitution: Substitution::single( 213 substitution: Substitution::from1(
214 &Interner,
224 TyKind::BoundVar(BoundVar { 215 TyKind::BoundVar(BoundVar {
225 debruijn: DebruijnIndex::INNERMOST, 216 debruijn: DebruijnIndex::INNERMOST,
226 index: 0, 217 index: 0,
@@ -232,7 +223,8 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
232 alias: AliasTy::Projection(ProjectionTy { 223 alias: AliasTy::Projection(ProjectionTy {
233 associated_ty_id: to_assoc_type_id(future_output), 224 associated_ty_id: to_assoc_type_id(future_output),
234 // Self type as the first parameter. 225 // Self type as the first parameter.
235 substitution: Substitution::single( 226 substitution: Substitution::from1(
227 &Interner,
236 TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) 228 TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
237 .intern(&Interner), 229 .intern(&Interner),
238 ), 230 ),
@@ -242,25 +234,25 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
242 .intern(&Interner), 234 .intern(&Interner),
243 }); 235 });
244 let bound = OpaqueTyDatumBound { 236 let bound = OpaqueTyDatumBound {
245 bounds: make_binders( 237 bounds: make_only_type_binders(
238 1,
246 vec![ 239 vec![
247 wrap_in_empty_binders(impl_bound).to_chalk(self.db), 240 crate::wrap_empty_binders(impl_bound),
248 wrap_in_empty_binders(proj_bound).to_chalk(self.db), 241 crate::wrap_empty_binders(proj_bound),
249 ], 242 ],
250 1,
251 ), 243 ),
252 where_clauses: make_binders(vec![], 0), 244 where_clauses: make_only_type_binders(0, vec![]),
253 }; 245 };
254 // The opaque type has 1 parameter. 246 // The opaque type has 1 parameter.
255 make_binders(bound, 1) 247 make_only_type_binders(1, bound)
256 } else { 248 } else {
257 // If failed to find Symbol’s value as variable is void: Future::Output, return empty bounds as fallback. 249 // If failed to find Symbol’s value as variable is void: Future::Output, return empty bounds as fallback.
258 let bound = OpaqueTyDatumBound { 250 let bound = OpaqueTyDatumBound {
259 bounds: make_binders(vec![], 0), 251 bounds: make_only_type_binders(0, vec![]),
260 where_clauses: make_binders(vec![], 0), 252 where_clauses: make_only_type_binders(0, vec![]),
261 }; 253 };
262 // The opaque type has 1 parameter. 254 // The opaque type has 1 parameter.
263 make_binders(bound, 1) 255 make_only_type_binders(1, bound)
264 } 256 }
265 } 257 }
266 }; 258 };
@@ -270,7 +262,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
270 262
271 fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId<Interner>) -> chalk_ir::Ty<Interner> { 263 fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId<Interner>) -> chalk_ir::Ty<Interner> {
272 // FIXME: actually provide the hidden type; it is relevant for auto traits 264 // FIXME: actually provide the hidden type; it is relevant for auto traits
273 TyKind::Error.intern(&Interner).to_chalk(self.db) 265 TyKind::Error.intern(&Interner)
274 } 266 }
275 267
276 fn is_object_safe(&self, _trait_id: chalk_ir::TraitId<Interner>) -> bool { 268 fn is_object_safe(&self, _trait_id: chalk_ir::TraitId<Interner>) -> bool {
@@ -291,33 +283,32 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
291 _closure_id: chalk_ir::ClosureId<Interner>, 283 _closure_id: chalk_ir::ClosureId<Interner>,
292 substs: &chalk_ir::Substitution<Interner>, 284 substs: &chalk_ir::Substitution<Interner>,
293 ) -> chalk_ir::Binders<rust_ir::FnDefInputsAndOutputDatum<Interner>> { 285 ) -> chalk_ir::Binders<rust_ir::FnDefInputsAndOutputDatum<Interner>> {
294 let sig_ty: Ty = 286 let sig_ty = substs.at(&Interner, 0).assert_ty_ref(&Interner).clone();
295 from_chalk(self.db, substs.at(&Interner, 0).assert_ty_ref(&Interner).clone());
296 let sig = &sig_ty.callable_sig(self.db).expect("first closure param should be fn ptr"); 287 let sig = &sig_ty.callable_sig(self.db).expect("first closure param should be fn ptr");
297 let io = rust_ir::FnDefInputsAndOutputDatum { 288 let io = rust_ir::FnDefInputsAndOutputDatum {
298 argument_types: sig.params().iter().map(|ty| ty.clone().to_chalk(self.db)).collect(), 289 argument_types: sig.params().iter().cloned().collect(),
299 return_type: sig.ret().clone().to_chalk(self.db), 290 return_type: sig.ret().clone(),
300 }; 291 };
301 make_binders(io.shifted_in(&Interner), 0) 292 make_only_type_binders(0, io.shifted_in(&Interner))
302 } 293 }
303 fn closure_upvars( 294 fn closure_upvars(
304 &self, 295 &self,
305 _closure_id: chalk_ir::ClosureId<Interner>, 296 _closure_id: chalk_ir::ClosureId<Interner>,
306 _substs: &chalk_ir::Substitution<Interner>, 297 _substs: &chalk_ir::Substitution<Interner>,
307 ) -> chalk_ir::Binders<chalk_ir::Ty<Interner>> { 298 ) -> chalk_ir::Binders<chalk_ir::Ty<Interner>> {
308 let ty = TyBuilder::unit().to_chalk(self.db); 299 let ty = TyBuilder::unit();
309 make_binders(ty, 0) 300 make_only_type_binders(0, ty)
310 } 301 }
311 fn closure_fn_substitution( 302 fn closure_fn_substitution(
312 &self, 303 &self,
313 _closure_id: chalk_ir::ClosureId<Interner>, 304 _closure_id: chalk_ir::ClosureId<Interner>,
314 _substs: &chalk_ir::Substitution<Interner>, 305 _substs: &chalk_ir::Substitution<Interner>,
315 ) -> chalk_ir::Substitution<Interner> { 306 ) -> chalk_ir::Substitution<Interner> {
316 Substitution::empty(&Interner).to_chalk(self.db) 307 Substitution::empty(&Interner)
317 } 308 }
318 309
319 fn trait_name(&self, trait_id: chalk_ir::TraitId<Interner>) -> String { 310 fn trait_name(&self, trait_id: chalk_ir::TraitId<Interner>) -> String {
320 let id = from_chalk(self.db, trait_id); 311 let id = from_chalk_trait_id(trait_id);
321 self.db.trait_data(id).name.to_string() 312 self.db.trait_data(id).name.to_string()
322 } 313 }
323 fn adt_name(&self, chalk_ir::AdtId(adt_id): AdtId) -> String { 314 fn adt_name(&self, chalk_ir::AdtId(adt_id): AdtId) -> String {
@@ -408,10 +399,10 @@ pub(crate) fn associated_ty_data_query(
408 let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars); 399 let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars);
409 let bound_data = rust_ir::AssociatedTyDatumBound { bounds, where_clauses }; 400 let bound_data = rust_ir::AssociatedTyDatumBound { bounds, where_clauses };
410 let datum = AssociatedTyDatum { 401 let datum = AssociatedTyDatum {
411 trait_id: trait_.to_chalk(db), 402 trait_id: to_chalk_trait_id(trait_),
412 id, 403 id,
413 name: type_alias, 404 name: type_alias,
414 binders: make_binders(bound_data, generic_params.len()), 405 binders: make_only_type_binders(generic_params.len(), bound_data),
415 }; 406 };
416 Arc::new(datum) 407 Arc::new(datum)
417} 408}
@@ -422,7 +413,7 @@ pub(crate) fn trait_datum_query(
422 trait_id: TraitId, 413 trait_id: TraitId,
423) -> Arc<TraitDatum> { 414) -> Arc<TraitDatum> {
424 debug!("trait_datum {:?}", trait_id); 415 debug!("trait_datum {:?}", trait_id);
425 let trait_: hir_def::TraitId = from_chalk(db, trait_id); 416 let trait_ = from_chalk_trait_id(trait_id);
426 let trait_data = db.trait_data(trait_); 417 let trait_data = db.trait_data(trait_);
427 debug!("trait {:?} = {:?}", trait_id, trait_data.name); 418 debug!("trait {:?} = {:?}", trait_id, trait_data.name);
428 let generic_params = generics(db.upcast(), trait_.into()); 419 let generic_params = generics(db.upcast(), trait_.into());
@@ -444,7 +435,7 @@ pub(crate) fn trait_datum_query(
444 lang_attr(db.upcast(), trait_).and_then(|name| well_known_trait_from_lang_attr(&name)); 435 lang_attr(db.upcast(), trait_).and_then(|name| well_known_trait_from_lang_attr(&name));
445 let trait_datum = TraitDatum { 436 let trait_datum = TraitDatum {
446 id: trait_id, 437 id: trait_id,
447 binders: make_binders(trait_datum_bound, bound_vars.len(&Interner)), 438 binders: make_only_type_binders(bound_vars.len(&Interner), trait_datum_bound),
448 flags, 439 flags,
449 associated_ty_ids, 440 associated_ty_ids,
450 well_known, 441 well_known,
@@ -513,7 +504,7 @@ pub(crate) fn struct_datum_query(
513 // FIXME set ADT kind 504 // FIXME set ADT kind
514 kind: rust_ir::AdtKind::Struct, 505 kind: rust_ir::AdtKind::Struct,
515 id: struct_id, 506 id: struct_id,
516 binders: make_binders(struct_datum_bound, num_params), 507 binders: make_only_type_binders(num_params, struct_datum_bound),
517 flags, 508 flags,
518 }; 509 };
519 Arc::new(struct_datum) 510 Arc::new(struct_datum)
@@ -561,7 +552,6 @@ fn impl_def_datum(
561 trait_ref.display(db), 552 trait_ref.display(db),
562 where_clauses 553 where_clauses
563 ); 554 );
564 let trait_ref = trait_ref.to_chalk(db);
565 555
566 let polarity = if negative { rust_ir::Polarity::Negative } else { rust_ir::Polarity::Positive }; 556 let polarity = if negative { rust_ir::Polarity::Negative } else { rust_ir::Polarity::Positive };
567 557
@@ -583,7 +573,7 @@ fn impl_def_datum(
583 .collect(); 573 .collect();
584 debug!("impl_datum: {:?}", impl_datum_bound); 574 debug!("impl_datum: {:?}", impl_datum_bound);
585 let impl_datum = ImplDatum { 575 let impl_datum = ImplDatum {
586 binders: make_binders(impl_datum_bound, bound_vars.len(&Interner)), 576 binders: make_only_type_binders(bound_vars.len(&Interner), impl_datum_bound),
587 impl_type, 577 impl_type,
588 polarity, 578 polarity,
589 associated_ty_value_ids, 579 associated_ty_value_ids,
@@ -622,7 +612,7 @@ fn type_alias_associated_ty_value(
622 .associated_type_by_name(&type_alias_data.name) 612 .associated_type_by_name(&type_alias_data.name)
623 .expect("assoc ty value should not exist"); // validated when building the impl data as well 613 .expect("assoc ty value should not exist"); // validated when building the impl data as well
624 let (ty, binders) = db.ty(type_alias.into()).into_value_and_skipped_binders(); 614 let (ty, binders) = db.ty(type_alias.into()).into_value_and_skipped_binders();
625 let value_bound = rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) }; 615 let value_bound = rust_ir::AssociatedTyValueBound { ty };
626 let value = rust_ir::AssociatedTyValue { 616 let value = rust_ir::AssociatedTyValue {
627 impl_id: impl_id.to_chalk(db), 617 impl_id: impl_id.to_chalk(db),
628 associated_ty_id: to_assoc_type_id(assoc_ty), 618 associated_ty_id: to_assoc_type_id(assoc_ty),
@@ -643,13 +633,13 @@ pub(crate) fn fn_def_datum_query(
643 let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars); 633 let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars);
644 let bound = rust_ir::FnDefDatumBound { 634 let bound = rust_ir::FnDefDatumBound {
645 // Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway 635 // Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway
646 inputs_and_output: make_binders( 636 inputs_and_output: make_only_type_binders(
637 0,
647 rust_ir::FnDefInputsAndOutputDatum { 638 rust_ir::FnDefInputsAndOutputDatum {
648 argument_types: sig.params().iter().map(|ty| ty.clone().to_chalk(db)).collect(), 639 argument_types: sig.params().iter().cloned().collect(),
649 return_type: sig.ret().clone().to_chalk(db), 640 return_type: sig.ret().clone(),
650 } 641 }
651 .shifted_in(&Interner), 642 .shifted_in(&Interner),
652 0,
653 ), 643 ),
654 where_clauses, 644 where_clauses,
655 }; 645 };
@@ -686,42 +676,65 @@ pub(crate) fn adt_variance_query(
686 ) 676 )
687} 677}
688 678
689impl From<FnDefId> for crate::db::InternedCallableDefId { 679pub(super) fn convert_where_clauses(
690 fn from(fn_def_id: FnDefId) -> Self { 680 db: &dyn HirDatabase,
691 InternKey::from_intern_id(fn_def_id.0) 681 def: GenericDefId,
692 } 682 substs: &Substitution,
693} 683) -> Vec<chalk_ir::QuantifiedWhereClause<Interner>> {
694 684 let generic_predicates = db.generic_predicates(def);
695impl From<crate::db::InternedCallableDefId> for FnDefId { 685 let mut result = Vec::with_capacity(generic_predicates.len());
696 fn from(callable_def_id: crate::db::InternedCallableDefId) -> Self { 686 for pred in generic_predicates.iter() {
697 chalk_ir::FnDefId(callable_def_id.as_intern_id()) 687 result.push(pred.clone().substitute(&Interner, substs));
698 } 688 }
699} 689 result
700
701impl From<OpaqueTyId> for crate::db::InternedOpaqueTyId {
702 fn from(id: OpaqueTyId) -> Self {
703 InternKey::from_intern_id(id.0)
704 }
705}
706
707impl From<crate::db::InternedOpaqueTyId> for OpaqueTyId {
708 fn from(id: crate::db::InternedOpaqueTyId) -> Self {
709 chalk_ir::OpaqueTyId(id.as_intern_id())
710 }
711}
712
713impl From<chalk_ir::ClosureId<Interner>> for crate::db::InternedClosureId {
714 fn from(id: chalk_ir::ClosureId<Interner>) -> Self {
715 Self::from_intern_id(id.0)
716 }
717} 690}
718 691
719impl From<crate::db::InternedClosureId> for chalk_ir::ClosureId<Interner> { 692pub(super) fn generic_predicate_to_inline_bound(
720 fn from(id: crate::db::InternedClosureId) -> Self { 693 db: &dyn HirDatabase,
721 chalk_ir::ClosureId(id.as_intern_id()) 694 pred: &QuantifiedWhereClause,
695 self_ty: &Ty,
696) -> Option<chalk_ir::Binders<rust_ir::InlineBound<Interner>>> {
697 // An InlineBound is like a GenericPredicate, except the self type is left out.
698 // We don't have a special type for this, but Chalk does.
699 let self_ty_shifted_in = self_ty.clone().shifted_in_from(&Interner, DebruijnIndex::ONE);
700 let (pred, binders) = pred.as_ref().into_value_and_skipped_binders();
701 match pred {
702 WhereClause::Implemented(trait_ref) => {
703 if trait_ref.self_type_parameter(&Interner) != self_ty_shifted_in {
704 // we can only convert predicates back to type bounds if they
705 // have the expected self type
706 return None;
707 }
708 let args_no_self = trait_ref.substitution.as_slice(&Interner)[1..]
709 .iter()
710 .map(|ty| ty.clone().cast(&Interner))
711 .collect();
712 let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self };
713 Some(chalk_ir::Binders::new(binders, rust_ir::InlineBound::TraitBound(trait_bound)))
714 }
715 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
716 if projection_ty.self_type_parameter(&Interner) != self_ty_shifted_in {
717 return None;
718 }
719 let trait_ = projection_ty.trait_(db);
720 let args_no_self = projection_ty.substitution.as_slice(&Interner)[1..]
721 .iter()
722 .map(|ty| ty.clone().cast(&Interner))
723 .collect();
724 let alias_eq_bound = rust_ir::AliasEqBound {
725 value: ty.clone(),
726 trait_bound: rust_ir::TraitBound {
727 trait_id: to_chalk_trait_id(trait_),
728 args_no_self,
729 },
730 associated_ty_id: projection_ty.associated_ty_id,
731 parameters: Vec::new(), // FIXME we don't support generic associated types yet
732 };
733 Some(chalk_ir::Binders::new(
734 binders,
735 rust_ir::InlineBound::AliasEqBound(alias_eq_bound),
736 ))
737 }
738 _ => None,
722 } 739 }
723} 740}
724
725fn wrap_in_empty_binders<T: crate::TypeWalk>(value: T) -> crate::Binders<T> {
726 crate::Binders::wrap_empty(value)
727}
diff --git a/crates/hir_ty/src/chalk_ext.rs b/crates/hir_ty/src/chalk_ext.rs
index b7463366b..8c4542956 100644
--- a/crates/hir_ty/src/chalk_ext.rs
+++ b/crates/hir_ty/src/chalk_ext.rs
@@ -1,13 +1,305 @@
1//! Various extensions traits for Chalk types. 1//! Various extensions traits for Chalk types.
2 2
3use crate::{Interner, Ty, TyKind}; 3use chalk_ir::Mutability;
4use hir_def::{
5 type_ref::Rawness, AssocContainerId, FunctionId, GenericDefId, HasModule, Lookup, TraitId,
6};
7
8use crate::{
9 db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
10 from_placeholder_idx, to_chalk_trait_id, AdtId, AliasEq, AliasTy, Binders, CallableDefId,
11 CallableSig, FnPointer, ImplTraitId, Interner, Lifetime, ProjectionTy, QuantifiedWhereClause,
12 Substitution, TraitRef, Ty, TyBuilder, TyKind, WhereClause,
13};
4 14
5pub trait TyExt { 15pub trait TyExt {
6 fn is_unit(&self) -> bool; 16 fn is_unit(&self) -> bool;
17 fn is_never(&self) -> bool;
18 fn is_unknown(&self) -> bool;
19
20 fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)>;
21 fn as_tuple(&self) -> Option<&Substitution>;
22 fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId>;
23 fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)>;
24 fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)>;
25 fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId>;
26
27 fn callable_def(&self, db: &dyn HirDatabase) -> Option<CallableDefId>;
28 fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig>;
29
30 fn strip_references(&self) -> &Ty;
31
32 /// If this is a `dyn Trait`, returns that trait.
33 fn dyn_trait(&self) -> Option<TraitId>;
34
35 fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>>;
36 fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId>;
37
38 /// FIXME: Get rid of this, it's not a good abstraction
39 fn equals_ctor(&self, other: &Ty) -> bool;
7} 40}
8 41
9impl TyExt for Ty { 42impl TyExt for Ty {
10 fn is_unit(&self) -> bool { 43 fn is_unit(&self) -> bool {
11 matches!(self.kind(&Interner), TyKind::Tuple(0, _)) 44 matches!(self.kind(&Interner), TyKind::Tuple(0, _))
12 } 45 }
46
47 fn is_never(&self) -> bool {
48 matches!(self.kind(&Interner), TyKind::Never)
49 }
50
51 fn is_unknown(&self) -> bool {
52 matches!(self.kind(&Interner), TyKind::Error)
53 }
54
55 fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)> {
56 match self.kind(&Interner) {
57 TyKind::Adt(AdtId(adt), parameters) => Some((*adt, parameters)),
58 _ => None,
59 }
60 }
61
62 fn as_tuple(&self) -> Option<&Substitution> {
63 match self.kind(&Interner) {
64 TyKind::Tuple(_, substs) => Some(substs),
65 _ => None,
66 }
67 }
68
69 fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId> {
70 if let Some(CallableDefId::FunctionId(func)) = self.callable_def(db) {
71 Some(func)
72 } else {
73 None
74 }
75 }
76 fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)> {
77 match self.kind(&Interner) {
78 TyKind::Ref(mutability, lifetime, ty) => Some((ty, lifetime.clone(), *mutability)),
79 _ => None,
80 }
81 }
82
83 fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> {
84 match self.kind(&Interner) {
85 TyKind::Ref(mutability, _, ty) => Some((ty, Rawness::Ref, *mutability)),
86 TyKind::Raw(mutability, ty) => Some((ty, Rawness::RawPtr, *mutability)),
87 _ => None,
88 }
89 }
90
91 fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId> {
92 match *self.kind(&Interner) {
93 TyKind::Adt(AdtId(adt), ..) => Some(adt.into()),
94 TyKind::FnDef(callable, ..) => {
95 Some(db.lookup_intern_callable_def(callable.into()).into())
96 }
97 TyKind::AssociatedType(type_alias, ..) => Some(from_assoc_type_id(type_alias).into()),
98 TyKind::Foreign(type_alias, ..) => Some(from_foreign_def_id(type_alias).into()),
99 _ => None,
100 }
101 }
102
103 fn callable_def(&self, db: &dyn HirDatabase) -> Option<CallableDefId> {
104 match self.kind(&Interner) {
105 &TyKind::FnDef(def, ..) => Some(db.lookup_intern_callable_def(def.into())),
106 _ => None,
107 }
108 }
109
110 fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig> {
111 match self.kind(&Interner) {
112 TyKind::Function(fn_ptr) => Some(CallableSig::from_fn_ptr(fn_ptr)),
113 TyKind::FnDef(def, parameters) => {
114 let callable_def = db.lookup_intern_callable_def((*def).into());
115 let sig = db.callable_item_signature(callable_def);
116 Some(sig.substitute(&Interner, &parameters))
117 }
118 TyKind::Closure(.., substs) => {
119 let sig_param = substs.at(&Interner, 0).assert_ty_ref(&Interner);
120 sig_param.callable_sig(db)
121 }
122 _ => None,
123 }
124 }
125
126 fn dyn_trait(&self) -> Option<TraitId> {
127 let trait_ref = match self.kind(&Interner) {
128 TyKind::Dyn(dyn_ty) => dyn_ty.bounds.skip_binders().interned().get(0).and_then(|b| {
129 match b.skip_binders() {
130 WhereClause::Implemented(trait_ref) => Some(trait_ref),
131 _ => None,
132 }
133 }),
134 _ => None,
135 }?;
136 Some(from_chalk_trait_id(trait_ref.trait_id))
137 }
138
139 fn strip_references(&self) -> &Ty {
140 let mut t: &Ty = self;
141 while let TyKind::Ref(_mutability, _lifetime, ty) = t.kind(&Interner) {
142 t = ty;
143 }
144 t
145 }
146
147 fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>> {
148 match self.kind(&Interner) {
149 TyKind::OpaqueType(opaque_ty_id, ..) => {
150 match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) {
151 ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => {
152 let krate = def.module(db.upcast()).krate();
153 if let Some(future_trait) = db
154 .lang_item(krate, "future_trait".into())
155 .and_then(|item| item.as_trait())
156 {
157 // This is only used by type walking.
158 // Parameters will be walked outside, and projection predicate is not used.
159 // So just provide the Future trait.
160 let impl_bound = Binders::empty(
161 &Interner,
162 WhereClause::Implemented(TraitRef {
163 trait_id: to_chalk_trait_id(future_trait),
164 substitution: Substitution::empty(&Interner),
165 }),
166 );
167 Some(vec![impl_bound])
168 } else {
169 None
170 }
171 }
172 ImplTraitId::ReturnTypeImplTrait(..) => None,
173 }
174 }
175 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
176 let predicates = match db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into())
177 {
178 ImplTraitId::ReturnTypeImplTrait(func, idx) => {
179 db.return_type_impl_traits(func).map(|it| {
180 let data = (*it)
181 .as_ref()
182 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
183 data.substitute(&Interner, &opaque_ty.substitution)
184 })
185 }
186 // It always has an parameter for Future::Output type.
187 ImplTraitId::AsyncBlockTypeImplTrait(..) => unreachable!(),
188 };
189
190 predicates.map(|it| it.into_value_and_skipped_binders().0)
191 }
192 TyKind::Placeholder(idx) => {
193 let id = from_placeholder_idx(db, *idx);
194 let generic_params = db.generic_params(id.parent);
195 let param_data = &generic_params.types[id.local_id];
196 match param_data.provenance {
197 hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
198 let substs = TyBuilder::type_params_subst(db, id.parent);
199 let predicates = db
200 .generic_predicates(id.parent)
201 .into_iter()
202 .map(|pred| pred.clone().substitute(&Interner, &substs))
203 .filter(|wc| match &wc.skip_binders() {
204 WhereClause::Implemented(tr) => {
205 &tr.self_type_parameter(&Interner) == self
206 }
207 WhereClause::AliasEq(AliasEq {
208 alias: AliasTy::Projection(proj),
209 ty: _,
210 }) => &proj.self_type_parameter(&Interner) == self,
211 _ => false,
212 })
213 .collect::<Vec<_>>();
214
215 Some(predicates)
216 }
217 _ => None,
218 }
219 }
220 _ => None,
221 }
222 }
223
224 fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId> {
225 match self.kind(&Interner) {
226 TyKind::AssociatedType(id, ..) => {
227 match from_assoc_type_id(*id).lookup(db.upcast()).container {
228 AssocContainerId::TraitId(trait_id) => Some(trait_id),
229 _ => None,
230 }
231 }
232 TyKind::Alias(AliasTy::Projection(projection_ty)) => {
233 match from_assoc_type_id(projection_ty.associated_ty_id)
234 .lookup(db.upcast())
235 .container
236 {
237 AssocContainerId::TraitId(trait_id) => Some(trait_id),
238 _ => None,
239 }
240 }
241 _ => None,
242 }
243 }
244
245 fn equals_ctor(&self, other: &Ty) -> bool {
246 match (self.kind(&Interner), other.kind(&Interner)) {
247 (TyKind::Adt(adt, ..), TyKind::Adt(adt2, ..)) => adt == adt2,
248 (TyKind::Slice(_), TyKind::Slice(_)) | (TyKind::Array(_, _), TyKind::Array(_, _)) => {
249 true
250 }
251 (TyKind::FnDef(def_id, ..), TyKind::FnDef(def_id2, ..)) => def_id == def_id2,
252 (TyKind::OpaqueType(ty_id, ..), TyKind::OpaqueType(ty_id2, ..)) => ty_id == ty_id2,
253 (TyKind::AssociatedType(ty_id, ..), TyKind::AssociatedType(ty_id2, ..)) => {
254 ty_id == ty_id2
255 }
256 (TyKind::Foreign(ty_id, ..), TyKind::Foreign(ty_id2, ..)) => ty_id == ty_id2,
257 (TyKind::Closure(id1, _), TyKind::Closure(id2, _)) => id1 == id2,
258 (TyKind::Ref(mutability, ..), TyKind::Ref(mutability2, ..))
259 | (TyKind::Raw(mutability, ..), TyKind::Raw(mutability2, ..)) => {
260 mutability == mutability2
261 }
262 (
263 TyKind::Function(FnPointer { num_binders, sig, .. }),
264 TyKind::Function(FnPointer { num_binders: num_binders2, sig: sig2, .. }),
265 ) => num_binders == num_binders2 && sig == sig2,
266 (TyKind::Tuple(cardinality, _), TyKind::Tuple(cardinality2, _)) => {
267 cardinality == cardinality2
268 }
269 (TyKind::Str, TyKind::Str) | (TyKind::Never, TyKind::Never) => true,
270 (TyKind::Scalar(scalar), TyKind::Scalar(scalar2)) => scalar == scalar2,
271 _ => false,
272 }
273 }
274}
275
276pub trait ProjectionTyExt {
277 fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef;
278 fn trait_(&self, db: &dyn HirDatabase) -> TraitId;
279}
280
281impl ProjectionTyExt for ProjectionTy {
282 fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef {
283 TraitRef {
284 trait_id: to_chalk_trait_id(self.trait_(db)),
285 substitution: self.substitution.clone(),
286 }
287 }
288
289 fn trait_(&self, db: &dyn HirDatabase) -> TraitId {
290 match from_assoc_type_id(self.associated_ty_id).lookup(db.upcast()).container {
291 AssocContainerId::TraitId(it) => it,
292 _ => panic!("projection ty without parent trait"),
293 }
294 }
295}
296
297pub trait TraitRefExt {
298 fn hir_trait_id(&self) -> TraitId;
299}
300
301impl TraitRefExt for TraitRef {
302 fn hir_trait_id(&self) -> TraitId {
303 from_chalk_trait_id(self.trait_id)
304 }
13} 305}
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs
index 4300680d9..1690926ad 100644
--- a/crates/hir_ty/src/db.rs
+++ b/crates/hir_ty/src/db.rs
@@ -1,18 +1,19 @@
1//! FIXME: write short doc here 1//! The home of `HirDatabase`, which is the Salsa database containing all the
2//! type inference-related queries.
2 3
3use std::sync::Arc; 4use std::sync::Arc;
4 5
5use base_db::{impl_intern_key, salsa, CrateId, Upcast}; 6use base_db::{impl_intern_key, salsa, CrateId, Upcast};
6use hir_def::{ 7use hir_def::{
7 db::DefDatabase, expr::ExprId, ConstParamId, DefWithBodyId, FunctionId, GenericDefId, ImplId, 8 db::DefDatabase, expr::ExprId, ConstParamId, DefWithBodyId, FunctionId, GenericDefId, ImplId,
8 LocalFieldId, TypeParamId, VariantId, 9 LifetimeParamId, LocalFieldId, TypeParamId, VariantId,
9}; 10};
10use la_arena::ArenaMap; 11use la_arena::ArenaMap;
11 12
12use crate::{ 13use crate::{
14 chalk_db,
13 method_resolution::{InherentImpls, TraitImpls}, 15 method_resolution::{InherentImpls, TraitImpls},
14 traits::chalk, 16 Binders, CallableDefId, FnDefId, ImplTraitId, InferenceResult, Interner, PolyFnSig,
15 Binders, CallableDefId, FnDefId, ImplTraitId, InferenceResult, PolyFnSig,
16 QuantifiedWhereClause, ReturnTypeImplTraits, TraitRef, Ty, TyDefId, ValueTyDefId, 17 QuantifiedWhereClause, ReturnTypeImplTraits, TraitRef, Ty, TyDefId, ValueTyDefId,
17}; 18};
18use hir_expand::name::Name; 19use hir_expand::name::Name;
@@ -86,37 +87,46 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
86 #[salsa::interned] 87 #[salsa::interned]
87 fn intern_type_param_id(&self, param_id: TypeParamId) -> InternedTypeParamId; 88 fn intern_type_param_id(&self, param_id: TypeParamId) -> InternedTypeParamId;
88 #[salsa::interned] 89 #[salsa::interned]
90 fn intern_lifetime_param_id(&self, param_id: LifetimeParamId) -> InternedLifetimeParamId;
91 #[salsa::interned]
92 fn intern_const_param_id(&self, param_id: ConstParamId) -> InternedConstParamId;
93 #[salsa::interned]
89 fn intern_impl_trait_id(&self, id: ImplTraitId) -> InternedOpaqueTyId; 94 fn intern_impl_trait_id(&self, id: ImplTraitId) -> InternedOpaqueTyId;
90 #[salsa::interned] 95 #[salsa::interned]
91 fn intern_closure(&self, id: (DefWithBodyId, ExprId)) -> InternedClosureId; 96 fn intern_closure(&self, id: (DefWithBodyId, ExprId)) -> InternedClosureId;
92 97
93 #[salsa::invoke(chalk::associated_ty_data_query)] 98 #[salsa::invoke(chalk_db::associated_ty_data_query)]
94 fn associated_ty_data(&self, id: chalk::AssocTypeId) -> Arc<chalk::AssociatedTyDatum>; 99 fn associated_ty_data(&self, id: chalk_db::AssocTypeId) -> Arc<chalk_db::AssociatedTyDatum>;
95 100
96 #[salsa::invoke(chalk::trait_datum_query)] 101 #[salsa::invoke(chalk_db::trait_datum_query)]
97 fn trait_datum(&self, krate: CrateId, trait_id: chalk::TraitId) -> Arc<chalk::TraitDatum>; 102 fn trait_datum(&self, krate: CrateId, trait_id: chalk_db::TraitId)
103 -> Arc<chalk_db::TraitDatum>;
98 104
99 #[salsa::invoke(chalk::struct_datum_query)] 105 #[salsa::invoke(chalk_db::struct_datum_query)]
100 fn struct_datum(&self, krate: CrateId, struct_id: chalk::AdtId) -> Arc<chalk::StructDatum>; 106 fn struct_datum(
107 &self,
108 krate: CrateId,
109 struct_id: chalk_db::AdtId,
110 ) -> Arc<chalk_db::StructDatum>;
101 111
102 #[salsa::invoke(crate::traits::chalk::impl_datum_query)] 112 #[salsa::invoke(chalk_db::impl_datum_query)]
103 fn impl_datum(&self, krate: CrateId, impl_id: chalk::ImplId) -> Arc<chalk::ImplDatum>; 113 fn impl_datum(&self, krate: CrateId, impl_id: chalk_db::ImplId) -> Arc<chalk_db::ImplDatum>;
104 114
105 #[salsa::invoke(crate::traits::chalk::fn_def_datum_query)] 115 #[salsa::invoke(chalk_db::fn_def_datum_query)]
106 fn fn_def_datum(&self, krate: CrateId, fn_def_id: FnDefId) -> Arc<chalk::FnDefDatum>; 116 fn fn_def_datum(&self, krate: CrateId, fn_def_id: FnDefId) -> Arc<chalk_db::FnDefDatum>;
107 117
108 #[salsa::invoke(crate::traits::chalk::fn_def_variance_query)] 118 #[salsa::invoke(chalk_db::fn_def_variance_query)]
109 fn fn_def_variance(&self, krate: CrateId, fn_def_id: FnDefId) -> chalk::Variances; 119 fn fn_def_variance(&self, krate: CrateId, fn_def_id: FnDefId) -> chalk_db::Variances;
110 120
111 #[salsa::invoke(crate::traits::chalk::adt_variance_query)] 121 #[salsa::invoke(chalk_db::adt_variance_query)]
112 fn adt_variance(&self, krate: CrateId, adt_id: chalk::AdtId) -> chalk::Variances; 122 fn adt_variance(&self, krate: CrateId, adt_id: chalk_db::AdtId) -> chalk_db::Variances;
113 123
114 #[salsa::invoke(crate::traits::chalk::associated_ty_value_query)] 124 #[salsa::invoke(chalk_db::associated_ty_value_query)]
115 fn associated_ty_value( 125 fn associated_ty_value(
116 &self, 126 &self,
117 krate: CrateId, 127 krate: CrateId,
118 id: chalk::AssociatedTyValueId, 128 id: chalk_db::AssociatedTyValueId,
119 ) -> Arc<chalk::AssociatedTyValue>; 129 ) -> Arc<chalk_db::AssociatedTyValue>;
120 130
121 #[salsa::invoke(crate::traits::trait_solve_query)] 131 #[salsa::invoke(crate::traits::trait_solve_query)]
122 fn trait_solve( 132 fn trait_solve(
@@ -125,12 +135,12 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
125 goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>, 135 goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>,
126 ) -> Option<crate::Solution>; 136 ) -> Option<crate::Solution>;
127 137
128 #[salsa::invoke(crate::traits::chalk::program_clauses_for_chalk_env_query)] 138 #[salsa::invoke(chalk_db::program_clauses_for_chalk_env_query)]
129 fn program_clauses_for_chalk_env( 139 fn program_clauses_for_chalk_env(
130 &self, 140 &self,
131 krate: CrateId, 141 krate: CrateId,
132 env: chalk_ir::Environment<chalk::Interner>, 142 env: chalk_ir::Environment<Interner>,
133 ) -> chalk_ir::ProgramClauses<chalk::Interner>; 143 ) -> chalk_ir::ProgramClauses<Interner>;
134} 144}
135 145
136fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> { 146fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> {
@@ -156,6 +166,14 @@ pub struct InternedTypeParamId(salsa::InternId);
156impl_intern_key!(InternedTypeParamId); 166impl_intern_key!(InternedTypeParamId);
157 167
158#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 168#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
169pub struct InternedLifetimeParamId(salsa::InternId);
170impl_intern_key!(InternedLifetimeParamId);
171
172#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
173pub struct InternedConstParamId(salsa::InternId);
174impl_intern_key!(InternedConstParamId);
175
176#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
159pub struct InternedOpaqueTyId(salsa::InternId); 177pub struct InternedOpaqueTyId(salsa::InternId);
160impl_intern_key!(InternedOpaqueTyId); 178impl_intern_key!(InternedOpaqueTyId);
161 179
diff --git a/crates/hir_ty/src/diagnostics.rs b/crates/hir_ty/src/diagnostics.rs
index 86f937e1d..84fc8ce14 100644
--- a/crates/hir_ty/src/diagnostics.rs
+++ b/crates/hir_ty/src/diagnostics.rs
@@ -1,4 +1,4 @@
1//! FIXME: write short doc here 1//! Type inference-based diagnostics.
2mod expr; 2mod expr;
3mod match_check; 3mod match_check;
4mod unsafe_check; 4mod unsafe_check;
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs
index db278d0db..79602c3dd 100644
--- a/crates/hir_ty/src/diagnostics/expr.rs
+++ b/crates/hir_ty/src/diagnostics/expr.rs
@@ -14,7 +14,6 @@ use crate::{
14 MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkOrSomeInTailExpr, 14 MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkOrSomeInTailExpr,
15 MissingPatFields, RemoveThisSemicolon, 15 MissingPatFields, RemoveThisSemicolon,
16 }, 16 },
17 utils::variant_data,
18 AdtId, InferenceResult, Interner, TyExt, TyKind, 17 AdtId, InferenceResult, Interner, TyExt, TyKind,
19}; 18};
20 19
@@ -104,7 +103,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
104 let root = source_ptr.file_syntax(db.upcast()); 103 let root = source_ptr.file_syntax(db.upcast());
105 if let ast::Expr::RecordExpr(record_expr) = &source_ptr.value.to_node(&root) { 104 if let ast::Expr::RecordExpr(record_expr) = &source_ptr.value.to_node(&root) {
106 if let Some(_) = record_expr.record_expr_field_list() { 105 if let Some(_) = record_expr.record_expr_field_list() {
107 let variant_data = variant_data(db.upcast(), variant_def); 106 let variant_data = variant_def.variant_data(db.upcast());
108 let missed_fields = missed_fields 107 let missed_fields = missed_fields
109 .into_iter() 108 .into_iter()
110 .map(|idx| variant_data.fields()[idx].name.clone()) 109 .map(|idx| variant_data.fields()[idx].name.clone())
@@ -135,7 +134,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
135 let root = source_ptr.file_syntax(db.upcast()); 134 let root = source_ptr.file_syntax(db.upcast());
136 if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) { 135 if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) {
137 if let Some(_) = record_pat.record_pat_field_list() { 136 if let Some(_) = record_pat.record_pat_field_list() {
138 let variant_data = variant_data(db.upcast(), variant_def); 137 let variant_data = variant_def.variant_data(db.upcast());
139 let missed_fields = missed_fields 138 let missed_fields = missed_fields
140 .into_iter() 139 .into_iter()
141 .map(|idx| variant_data.fields()[idx].name.clone()) 140 .map(|idx| variant_data.fields()[idx].name.clone())
@@ -315,7 +314,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
315 if pat_ty == match_expr_ty 314 if pat_ty == match_expr_ty
316 || match_expr_ty 315 || match_expr_ty
317 .as_reference() 316 .as_reference()
318 .map(|(match_expr_ty, _)| match_expr_ty == pat_ty) 317 .map(|(match_expr_ty, ..)| match_expr_ty == pat_ty)
319 .unwrap_or(false) 318 .unwrap_or(false)
320 { 319 {
321 // If we had a NotUsefulMatchArm diagnostic, we could 320 // If we had a NotUsefulMatchArm diagnostic, we could
@@ -453,7 +452,7 @@ pub fn record_literal_missing_fields(
453 return None; 452 return None;
454 } 453 }
455 454
456 let variant_data = variant_data(db.upcast(), variant_def); 455 let variant_data = variant_def.variant_data(db.upcast());
457 456
458 let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect(); 457 let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
459 let missed_fields: Vec<LocalFieldId> = variant_data 458 let missed_fields: Vec<LocalFieldId> = variant_data
@@ -483,7 +482,7 @@ pub fn record_pattern_missing_fields(
483 return None; 482 return None;
484 } 483 }
485 484
486 let variant_data = variant_data(db.upcast(), variant_def); 485 let variant_data = variant_def.variant_data(db.upcast());
487 486
488 let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect(); 487 let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
489 let missed_fields: Vec<LocalFieldId> = variant_data 488 let missed_fields: Vec<LocalFieldId> = variant_data
diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs
index 34291578a..e9762622f 100644
--- a/crates/hir_ty/src/diagnostics/match_check.rs
+++ b/crates/hir_ty/src/diagnostics/match_check.rs
@@ -227,7 +227,7 @@ use hir_def::{
227use la_arena::Idx; 227use la_arena::Idx;
228use smallvec::{smallvec, SmallVec}; 228use smallvec::{smallvec, SmallVec};
229 229
230use crate::{db::HirDatabase, AdtId, InferenceResult, Interner, TyKind}; 230use crate::{db::HirDatabase, AdtId, InferenceResult, Interner, TyExt, TyKind};
231 231
232#[derive(Debug, Clone, Copy)] 232#[derive(Debug, Clone, Copy)]
233/// Either a pattern from the source code being analyzed, represented as 233/// Either a pattern from the source code being analyzed, represented as
diff --git a/crates/hir_ty/src/diagnostics/unsafe_check.rs b/crates/hir_ty/src/diagnostics/unsafe_check.rs
index b5efe9df5..ed97dc0e3 100644
--- a/crates/hir_ty/src/diagnostics/unsafe_check.rs
+++ b/crates/hir_ty/src/diagnostics/unsafe_check.rs
@@ -11,7 +11,9 @@ use hir_def::{
11}; 11};
12use hir_expand::diagnostics::DiagnosticSink; 12use hir_expand::diagnostics::DiagnosticSink;
13 13
14use crate::{db::HirDatabase, diagnostics::MissingUnsafe, InferenceResult, Interner, TyKind}; 14use crate::{
15 db::HirDatabase, diagnostics::MissingUnsafe, InferenceResult, Interner, TyExt, TyKind,
16};
15 17
16pub(super) struct UnsafeValidator<'a, 'b: 'a> { 18pub(super) struct UnsafeValidator<'a, 'b: 'a> {
17 owner: DefWithBodyId, 19 owner: DefWithBodyId,
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index f31e6b108..e7c9dabc2 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -1,8 +1,13 @@
1//! FIXME: write short doc here 1//! The `HirDisplay` trait, which serves two purposes: Turning various bits from
2//! HIR back into source code, and just displaying them for debugging/testing
3//! purposes.
2 4
3use std::{array, fmt}; 5use std::{
6 array,
7 fmt::{self, Debug},
8};
4 9
5use chalk_ir::Mutability; 10use chalk_ir::BoundVar;
6use hir_def::{ 11use hir_def::{
7 db::DefDatabase, 12 db::DefDatabase,
8 find_path, 13 find_path,
@@ -16,10 +21,12 @@ use hir_def::{
16use hir_expand::name::Name; 21use hir_expand::name::Name;
17 22
18use crate::{ 23use crate::{
19 db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, 24 const_from_placeholder_idx, db::HirDatabase, from_assoc_type_id, from_foreign_def_id,
20 to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, 25 from_placeholder_idx, lt_from_placeholder_idx, mapping::from_chalk, primitive, subst_prefix,
21 CallableDefId, CallableSig, DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, OpaqueTy, 26 to_assoc_type_id, utils::generics, AdtId, AliasEq, AliasTy, CallableDefId, CallableSig, Const,
22 ProjectionTy, QuantifiedWhereClause, Scalar, TraitRef, Ty, TyExt, TyKind, WhereClause, 27 ConstValue, DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, LifetimeData,
28 LifetimeOutlives, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause,
29 Scalar, TraitRef, TraitRefExt, Ty, TyExt, TyKind, WhereClause,
23}; 30};
24 31
25pub struct HirFormatter<'a> { 32pub struct HirFormatter<'a> {
@@ -46,6 +53,10 @@ pub trait HirDisplay {
46 where 53 where
47 Self: Sized, 54 Self: Sized,
48 { 55 {
56 assert!(
57 !matches!(display_target, DisplayTarget::SourceCode { .. }),
58 "HirDisplayWrapper cannot fail with DisplaySourceCodeError, use HirDisplay::hir_fmt directly instead"
59 );
49 HirDisplayWrapper { db, t: self, max_size, omit_verbose_types, display_target } 60 HirDisplayWrapper { db, t: self, max_size, omit_verbose_types, display_target }
50 } 61 }
51 62
@@ -230,7 +241,7 @@ where
230 Err(HirDisplayError::FmtError) => Err(fmt::Error), 241 Err(HirDisplayError::FmtError) => Err(fmt::Error),
231 Err(HirDisplayError::DisplaySourceCodeError(_)) => { 242 Err(HirDisplayError::DisplaySourceCodeError(_)) => {
232 // This should never happen 243 // This should never happen
233 panic!("HirDisplay failed when calling Display::fmt!") 244 panic!("HirDisplay::hir_fmt failed with DisplaySourceCodeError when calling Display::fmt!")
234 } 245 }
235 } 246 }
236 } 247 }
@@ -251,16 +262,12 @@ impl HirDisplay for ProjectionTy {
251 } 262 }
252 263
253 let trait_ = f.db.trait_data(self.trait_(f.db)); 264 let trait_ = f.db.trait_data(self.trait_(f.db));
254 let first_parameter = self.self_type_parameter(&Interner).into_displayable( 265 write!(f, "<")?;
255 f.db, 266 self.self_type_parameter(&Interner).hir_fmt(f)?;
256 f.max_size, 267 write!(f, " as {}", trait_.name)?;
257 f.omit_verbose_types,
258 f.display_target,
259 );
260 write!(f, "<{} as {}", first_parameter, trait_.name)?;
261 if self.substitution.len(&Interner) > 1 { 268 if self.substitution.len(&Interner) > 1 {
262 write!(f, "<")?; 269 write!(f, "<")?;
263 f.write_joined(&self.substitution.interned()[1..], ", ")?; 270 f.write_joined(&self.substitution.as_slice(&Interner)[1..], ", ")?;
264 write!(f, ">")?; 271 write!(f, ">")?;
265 } 272 }
266 write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?; 273 write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?;
@@ -282,10 +289,35 @@ impl HirDisplay for GenericArg {
282 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 289 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
283 match self.interned() { 290 match self.interned() {
284 crate::GenericArgData::Ty(ty) => ty.hir_fmt(f), 291 crate::GenericArgData::Ty(ty) => ty.hir_fmt(f),
292 crate::GenericArgData::Lifetime(lt) => lt.hir_fmt(f),
293 crate::GenericArgData::Const(c) => c.hir_fmt(f),
294 }
295 }
296}
297
298impl HirDisplay for Const {
299 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
300 let data = self.interned();
301 match data.value {
302 ConstValue::BoundVar(idx) => idx.hir_fmt(f),
303 ConstValue::InferenceVar(..) => write!(f, "_"),
304 ConstValue::Placeholder(idx) => {
305 let id = const_from_placeholder_idx(f.db, idx);
306 let generics = generics(f.db.upcast(), id.parent);
307 let param_data = &generics.params.consts[id.local_id];
308 write!(f, "{}", param_data.name)
309 }
310 ConstValue::Concrete(_) => write!(f, "_"),
285 } 311 }
286 } 312 }
287} 313}
288 314
315impl HirDisplay for BoundVar {
316 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
317 write!(f, "?{}.{}", self.debruijn.depth(), self.index)
318 }
319}
320
289impl HirDisplay for Ty { 321impl HirDisplay for Ty {
290 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 322 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
291 if f.should_truncate() { 323 if f.should_truncate() {
@@ -305,15 +337,14 @@ impl HirDisplay for Ty {
305 t.hir_fmt(f)?; 337 t.hir_fmt(f)?;
306 write!(f, "]")?; 338 write!(f, "]")?;
307 } 339 }
308 TyKind::Array(t) => { 340 TyKind::Array(t, c) => {
309 write!(f, "[")?; 341 write!(f, "[")?;
310 t.hir_fmt(f)?; 342 t.hir_fmt(f)?;
311 write!(f, "; _]")?; 343 write!(f, "; ")?;
344 c.hir_fmt(f)?;
345 write!(f, "]")?;
312 } 346 }
313 TyKind::Raw(m, t) | TyKind::Ref(m, t) => { 347 TyKind::Raw(m, t) | TyKind::Ref(m, _, t) => {
314 let ty_display =
315 t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target);
316
317 if matches!(self.kind(&Interner), TyKind::Raw(..)) { 348 if matches!(self.kind(&Interner), TyKind::Raw(..)) {
318 write!( 349 write!(
319 f, 350 f,
@@ -368,16 +399,16 @@ impl HirDisplay for Ty {
368 if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_) 399 if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_)
369 && predicates.len() <= 2 400 && predicates.len() <= 2
370 { 401 {
371 return write!(f, "{}", ty_display); 402 return t.hir_fmt(f);
372 } 403 }
373 } 404 }
374 405
375 if predicates.len() > 1 { 406 if predicates.len() > 1 {
376 write!(f, "(")?; 407 write!(f, "(")?;
377 write!(f, "{}", ty_display)?; 408 t.hir_fmt(f)?;
378 write!(f, ")")?; 409 write!(f, ")")?;
379 } else { 410 } else {
380 write!(f, "{}", ty_display)?; 411 t.hir_fmt(f)?;
381 } 412 }
382 } 413 }
383 TyKind::Tuple(_, substs) => { 414 TyKind::Tuple(_, substs) => {
@@ -387,7 +418,7 @@ impl HirDisplay for Ty {
387 write!(f, ",)")?; 418 write!(f, ",)")?;
388 } else { 419 } else {
389 write!(f, "(")?; 420 write!(f, "(")?;
390 f.write_joined(&*substs.interned(), ", ")?; 421 f.write_joined(&*substs.as_slice(&Interner), ", ")?;
391 write!(f, ")")?; 422 write!(f, ")")?;
392 } 423 }
393 } 424 }
@@ -415,7 +446,7 @@ impl HirDisplay for Ty {
415 // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self? 446 // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
416 if total_len > 0 { 447 if total_len > 0 {
417 write!(f, "<")?; 448 write!(f, "<")?;
418 f.write_joined(&parameters.interned()[..total_len], ", ")?; 449 f.write_joined(&parameters.as_slice(&Interner)[..total_len], ", ")?;
419 write!(f, ">")?; 450 write!(f, ">")?;
420 } 451 }
421 } 452 }
@@ -424,14 +455,8 @@ impl HirDisplay for Ty {
424 write!(f, ")")?; 455 write!(f, ")")?;
425 let ret = sig.ret(); 456 let ret = sig.ret();
426 if !ret.is_unit() { 457 if !ret.is_unit() {
427 let ret_display = ret.into_displayable( 458 write!(f, " -> ")?;
428 f.db, 459 ret.hir_fmt(f)?;
429 f.max_size,
430 f.omit_verbose_types,
431 f.display_target,
432 );
433
434 write!(f, " -> {}", ret_display)?;
435 } 460 }
436 } 461 }
437 TyKind::Adt(AdtId(def_id), parameters) => { 462 TyKind::Adt(AdtId(def_id), parameters) => {
@@ -468,7 +493,7 @@ impl HirDisplay for Ty {
468 .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) 493 .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
469 .filter(|defaults| !defaults.is_empty()) 494 .filter(|defaults| !defaults.is_empty())
470 { 495 {
471 None => parameters.interned().as_ref(), 496 None => parameters.as_slice(&Interner),
472 Some(default_parameters) => { 497 Some(default_parameters) => {
473 let mut default_from = 0; 498 let mut default_from = 0;
474 for (i, parameter) in parameters.iter(&Interner).enumerate() { 499 for (i, parameter) in parameters.iter(&Interner).enumerate() {
@@ -480,9 +505,11 @@ impl HirDisplay for Ty {
480 default_from = i + 1; 505 default_from = i + 1;
481 } 506 }
482 (_, Some(default_parameter)) => { 507 (_, Some(default_parameter)) => {
483 let actual_default = default_parameter 508 let actual_default =
484 .clone() 509 default_parameter.clone().substitute(
485 .substitute(&Interner, &parameters.prefix(i)); 510 &Interner,
511 &subst_prefix(parameters, i),
512 );
486 if parameter.assert_ty_ref(&Interner) != &actual_default 513 if parameter.assert_ty_ref(&Interner) != &actual_default
487 { 514 {
488 default_from = i + 1; 515 default_from = i + 1;
@@ -490,11 +517,11 @@ impl HirDisplay for Ty {
490 } 517 }
491 } 518 }
492 } 519 }
493 &parameters.interned()[0..default_from] 520 &parameters.as_slice(&Interner)[0..default_from]
494 } 521 }
495 } 522 }
496 } else { 523 } else {
497 parameters.interned().as_ref() 524 parameters.as_slice(&Interner)
498 }; 525 };
499 if !parameters_to_write.is_empty() { 526 if !parameters_to_write.is_empty() {
500 write!(f, "<")?; 527 write!(f, "<")?;
@@ -517,7 +544,7 @@ impl HirDisplay for Ty {
517 write!(f, "{}::{}", trait_.name, type_alias_data.name)?; 544 write!(f, "{}::{}", trait_.name, type_alias_data.name)?;
518 if parameters.len(&Interner) > 0 { 545 if parameters.len(&Interner) > 0 {
519 write!(f, "<")?; 546 write!(f, "<")?;
520 f.write_joined(&*parameters.interned(), ", ")?; 547 f.write_joined(&*parameters.as_slice(&Interner), ", ")?;
521 write!(f, ">")?; 548 write!(f, ">")?;
522 } 549 }
523 } else { 550 } else {
@@ -571,13 +598,8 @@ impl HirDisplay for Ty {
571 write!(f, "|")?; 598 write!(f, "|")?;
572 }; 599 };
573 600
574 let ret_display = sig.ret().into_displayable( 601 write!(f, " -> ")?;
575 f.db, 602 sig.ret().hir_fmt(f)?;
576 f.max_size,
577 f.omit_verbose_types,
578 f.display_target,
579 );
580 write!(f, " -> {}", ret_display)?;
581 } else { 603 } else {
582 write!(f, "{{closure}}")?; 604 write!(f, "{{closure}}")?;
583 } 605 }
@@ -598,12 +620,12 @@ impl HirDisplay for Ty {
598 .map(|pred| pred.clone().substitute(&Interner, &substs)) 620 .map(|pred| pred.clone().substitute(&Interner, &substs))
599 .filter(|wc| match &wc.skip_binders() { 621 .filter(|wc| match &wc.skip_binders() {
600 WhereClause::Implemented(tr) => { 622 WhereClause::Implemented(tr) => {
601 tr.self_type_parameter(&Interner) == self 623 &tr.self_type_parameter(&Interner) == self
602 } 624 }
603 WhereClause::AliasEq(AliasEq { 625 WhereClause::AliasEq(AliasEq {
604 alias: AliasTy::Projection(proj), 626 alias: AliasTy::Projection(proj),
605 ty: _, 627 ty: _,
606 }) => proj.self_type_parameter(&Interner) == self, 628 }) => &proj.self_type_parameter(&Interner) == self,
607 _ => false, 629 _ => false,
608 }) 630 })
609 .collect::<Vec<_>>(); 631 .collect::<Vec<_>>();
@@ -611,7 +633,7 @@ impl HirDisplay for Ty {
611 } 633 }
612 } 634 }
613 } 635 }
614 TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, 636 TyKind::BoundVar(idx) => idx.hir_fmt(f)?,
615 TyKind::Dyn(dyn_ty) => { 637 TyKind::Dyn(dyn_ty) => {
616 write_bounds_like_dyn_trait_with_prefix( 638 write_bounds_like_dyn_trait_with_prefix(
617 "dyn", 639 "dyn",
@@ -646,6 +668,8 @@ impl HirDisplay for Ty {
646 write!(f, "{{unknown}}")?; 668 write!(f, "{{unknown}}")?;
647 } 669 }
648 TyKind::InferenceVar(..) => write!(f, "_")?, 670 TyKind::InferenceVar(..) => write!(f, "_")?,
671 TyKind::Generator(..) => write!(f, "{{generator}}")?,
672 TyKind::GeneratorWitness(..) => write!(f, "{{generator witness}}")?,
649 } 673 }
650 Ok(()) 674 Ok(())
651 } 675 }
@@ -665,9 +689,8 @@ impl HirDisplay for CallableSig {
665 write!(f, ")")?; 689 write!(f, ")")?;
666 let ret = self.ret(); 690 let ret = self.ret();
667 if !ret.is_unit() { 691 if !ret.is_unit() {
668 let ret_display = 692 write!(f, " -> ")?;
669 ret.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); 693 ret.hir_fmt(f)?;
670 write!(f, " -> {}", ret_display)?;
671 } 694 }
672 Ok(()) 695 Ok(())
673 } 696 }
@@ -724,17 +747,17 @@ fn write_bounds_like_dyn_trait(
724 if !first { 747 if !first {
725 write!(f, " + ")?; 748 write!(f, " + ")?;
726 } 749 }
727 // We assume that the self type is $0 (i.e. the 750 // We assume that the self type is ^0.0 (i.e. the
728 // existential) here, which is the only thing that's 751 // existential) here, which is the only thing that's
729 // possible in actual Rust, and hence don't print it 752 // possible in actual Rust, and hence don't print it
730 write!(f, "{}", f.db.trait_data(trait_).name)?; 753 write!(f, "{}", f.db.trait_data(trait_).name)?;
731 if let [_, params @ ..] = &*trait_ref.substitution.interned() { 754 if let [_, params @ ..] = &*trait_ref.substitution.as_slice(&Interner) {
732 if is_fn_trait { 755 if is_fn_trait {
733 if let Some(args) = 756 if let Some(args) =
734 params.first().and_then(|it| it.assert_ty_ref(&Interner).as_tuple()) 757 params.first().and_then(|it| it.assert_ty_ref(&Interner).as_tuple())
735 { 758 {
736 write!(f, "(")?; 759 write!(f, "(")?;
737 f.write_joined(&*args.interned(), ", ")?; 760 f.write_joined(args.as_slice(&Interner), ", ")?;
738 write!(f, ")")?; 761 write!(f, ")")?;
739 } 762 }
740 } else if !params.is_empty() { 763 } else if !params.is_empty() {
@@ -766,6 +789,10 @@ fn write_bounds_like_dyn_trait(
766 } 789 }
767 ty.hir_fmt(f)?; 790 ty.hir_fmt(f)?;
768 } 791 }
792
793 // FIXME implement these
794 WhereClause::LifetimeOutlives(_) => {}
795 WhereClause::TypeOutlives(_) => {}
769 } 796 }
770 first = false; 797 first = false;
771 } 798 }
@@ -775,31 +802,29 @@ fn write_bounds_like_dyn_trait(
775 Ok(()) 802 Ok(())
776} 803}
777 804
778impl TraitRef { 805fn fmt_trait_ref(tr: &TraitRef, f: &mut HirFormatter, use_as: bool) -> Result<(), HirDisplayError> {
779 fn hir_fmt_ext(&self, f: &mut HirFormatter, use_as: bool) -> Result<(), HirDisplayError> { 806 if f.should_truncate() {
780 if f.should_truncate() { 807 return write!(f, "{}", TYPE_HINT_TRUNCATION);
781 return write!(f, "{}", TYPE_HINT_TRUNCATION); 808 }
782 }
783 809
784 self.self_type_parameter(&Interner).hir_fmt(f)?; 810 tr.self_type_parameter(&Interner).hir_fmt(f)?;
785 if use_as { 811 if use_as {
786 write!(f, " as ")?; 812 write!(f, " as ")?;
787 } else { 813 } else {
788 write!(f, ": ")?; 814 write!(f, ": ")?;
789 }
790 write!(f, "{}", f.db.trait_data(self.hir_trait_id()).name)?;
791 if self.substitution.len(&Interner) > 1 {
792 write!(f, "<")?;
793 f.write_joined(&self.substitution.interned()[1..], ", ")?;
794 write!(f, ">")?;
795 }
796 Ok(())
797 } 815 }
816 write!(f, "{}", f.db.trait_data(tr.hir_trait_id()).name)?;
817 if tr.substitution.len(&Interner) > 1 {
818 write!(f, "<")?;
819 f.write_joined(&tr.substitution.as_slice(&Interner)[1..], ", ")?;
820 write!(f, ">")?;
821 }
822 Ok(())
798} 823}
799 824
800impl HirDisplay for TraitRef { 825impl HirDisplay for TraitRef {
801 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 826 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
802 self.hir_fmt_ext(f, false) 827 fmt_trait_ref(self, f, false)
803 } 828 }
804} 829}
805 830
@@ -813,7 +838,7 @@ impl HirDisplay for WhereClause {
813 WhereClause::Implemented(trait_ref) => trait_ref.hir_fmt(f)?, 838 WhereClause::Implemented(trait_ref) => trait_ref.hir_fmt(f)?,
814 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { 839 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
815 write!(f, "<")?; 840 write!(f, "<")?;
816 projection_ty.trait_ref(f.db).hir_fmt_ext(f, true)?; 841 fmt_trait_ref(&projection_ty.trait_ref(f.db), f, true)?;
817 write!( 842 write!(
818 f, 843 f,
819 ">::{} = ", 844 ">::{} = ",
@@ -822,20 +847,44 @@ impl HirDisplay for WhereClause {
822 ty.hir_fmt(f)?; 847 ty.hir_fmt(f)?;
823 } 848 }
824 WhereClause::AliasEq(_) => write!(f, "{{error}}")?, 849 WhereClause::AliasEq(_) => write!(f, "{{error}}")?,
850
851 // FIXME implement these
852 WhereClause::TypeOutlives(..) => {}
853 WhereClause::LifetimeOutlives(..) => {}
825 } 854 }
826 Ok(()) 855 Ok(())
827 } 856 }
828} 857}
829 858
859impl HirDisplay for LifetimeOutlives {
860 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
861 self.a.hir_fmt(f)?;
862 write!(f, ": ")?;
863 self.b.hir_fmt(f)
864 }
865}
866
830impl HirDisplay for Lifetime { 867impl HirDisplay for Lifetime {
831 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 868 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
869 self.interned().hir_fmt(f)
870 }
871}
872
873impl HirDisplay for LifetimeData {
874 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
832 match self { 875 match self {
833 Lifetime::Parameter(id) => { 876 LifetimeData::BoundVar(idx) => idx.hir_fmt(f),
877 LifetimeData::InferenceVar(_) => write!(f, "_"),
878 LifetimeData::Placeholder(idx) => {
879 let id = lt_from_placeholder_idx(f.db, *idx);
834 let generics = generics(f.db.upcast(), id.parent); 880 let generics = generics(f.db.upcast(), id.parent);
835 let param_data = &generics.params.lifetimes[id.local_id]; 881 let param_data = &generics.params.lifetimes[id.local_id];
836 write!(f, "{}", &param_data.name) 882 write!(f, "{}", param_data.name)
837 } 883 }
838 Lifetime::Static => write!(f, "'static"), 884 LifetimeData::Static => write!(f, "'static"),
885 LifetimeData::Empty(_) => Ok(()),
886 LifetimeData::Erased => Ok(()),
887 LifetimeData::Phantom(_, _) => Ok(()),
839 } 888 }
840 } 889 }
841} 890}
@@ -846,9 +895,11 @@ impl HirDisplay for DomainGoal {
846 DomainGoal::Holds(wc) => { 895 DomainGoal::Holds(wc) => {
847 write!(f, "Holds(")?; 896 write!(f, "Holds(")?;
848 wc.hir_fmt(f)?; 897 wc.hir_fmt(f)?;
849 write!(f, ")") 898 write!(f, ")")?;
850 } 899 }
900 _ => write!(f, "?")?,
851 } 901 }
902 Ok(())
852 } 903 }
853} 904}
854 905
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index 1c3faf5cb..bf2da2d4a 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -18,7 +18,7 @@ use std::mem;
18use std::ops::Index; 18use std::ops::Index;
19use std::sync::Arc; 19use std::sync::Arc;
20 20
21use chalk_ir::{cast::Cast, Mutability}; 21use chalk_ir::{cast::Cast, DebruijnIndex, Mutability};
22use hir_def::{ 22use hir_def::{
23 body::Body, 23 body::Body,
24 data::{ConstData, FunctionData, StaticData}, 24 data::{ConstData, FunctionData, StaticData},
@@ -38,11 +38,11 @@ use syntax::SmolStr;
38 38
39use super::{ 39use super::{
40 DomainGoal, Guidance, InEnvironment, ProjectionTy, Solution, TraitEnvironment, TraitRef, Ty, 40 DomainGoal, Guidance, InEnvironment, ProjectionTy, Solution, TraitEnvironment, TraitRef, Ty,
41 TypeWalk,
42}; 41};
43use crate::{ 42use crate::{
44 db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, 43 db::HirDatabase, fold_tys, infer::diagnostics::InferenceDiagnostic,
45 to_assoc_type_id, AliasEq, AliasTy, Interner, TyBuilder, TyKind, 44 lower::ImplTraitLoweringMode, to_assoc_type_id, AliasEq, AliasTy, Canonical, Interner,
45 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,10 +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 /// For each field in record literal, records the field it resolves to. 134 /// For each struct literal or pattern, records the variant it resolves to.
135 record_field_resolutions: FxHashMap<ExprId, FieldId>,
136 record_pat_field_resolutions: FxHashMap<PatId, FieldId>,
137 /// For each struct literal, records the variant it resolves to.
138 variant_resolutions: FxHashMap<ExprOrPatId, VariantId>, 135 variant_resolutions: FxHashMap<ExprOrPatId, VariantId>,
139 /// For each associated item record what it resolves to 136 /// For each associated item record what it resolves to
140 assoc_resolutions: FxHashMap<ExprOrPatId, AssocItemId>, 137 assoc_resolutions: FxHashMap<ExprOrPatId, AssocItemId>,
@@ -153,12 +150,6 @@ impl InferenceResult {
153 pub fn field_resolution(&self, expr: ExprId) -> Option<FieldId> { 150 pub fn field_resolution(&self, expr: ExprId) -> Option<FieldId> {
154 self.field_resolutions.get(&expr).copied() 151 self.field_resolutions.get(&expr).copied()
155 } 152 }
156 pub fn record_field_resolution(&self, expr: ExprId) -> Option<FieldId> {
157 self.record_field_resolutions.get(&expr).copied()
158 }
159 pub fn record_pat_field_resolution(&self, pat: PatId) -> Option<FieldId> {
160 self.record_pat_field_resolutions.get(&pat).copied()
161 }
162 pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> { 153 pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> {
163 self.variant_resolutions.get(&id.into()).copied() 154 self.variant_resolutions.get(&id.into()).copied()
164 } 155 }
@@ -332,7 +323,7 @@ impl<'a> InferenceContext<'a> {
332 } 323 }
333 324
334 fn insert_type_vars(&mut self, ty: Ty) -> Ty { 325 fn insert_type_vars(&mut self, ty: Ty) -> Ty {
335 ty.fold(&mut |ty| self.insert_type_vars_shallow(ty)) 326 fold_tys(ty, |ty, _| self.insert_type_vars_shallow(ty), DebruijnIndex::INNERMOST)
336 } 327 }
337 328
338 fn resolve_obligations_as_possible(&mut self) { 329 fn resolve_obligations_as_possible(&mut self) {
@@ -345,17 +336,24 @@ impl<'a> InferenceContext<'a> {
345 self.last_obligations_check = Some(self.table.revision); 336 self.last_obligations_check = Some(self.table.revision);
346 let obligations = mem::replace(&mut self.obligations, Vec::new()); 337 let obligations = mem::replace(&mut self.obligations, Vec::new());
347 for obligation in obligations { 338 for obligation in obligations {
348 let in_env = InEnvironment::new(self.trait_env.env.clone(), obligation.clone()); 339 let in_env = InEnvironment::new(&self.trait_env.env, obligation.clone());
349 let canonicalized = self.canonicalizer().canonicalize_obligation(in_env); 340 let canonicalized = self.canonicalizer().canonicalize_obligation(in_env);
350 let solution = 341 let solution =
351 self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone()); 342 self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone());
352 343
353 match solution { 344 match solution {
354 Some(Solution::Unique(substs)) => { 345 Some(Solution::Unique(canonical_subst)) => {
355 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 );
356 } 354 }
357 Some(Solution::Ambig(Guidance::Definite(substs))) => { 355 Some(Solution::Ambig(Guidance::Definite(substs))) => {
358 canonicalized.apply_solution(self, substs.0); 356 canonicalized.apply_solution(self, substs);
359 self.obligations.push(obligation); 357 self.obligations.push(obligation);
360 } 358 }
361 Some(_) => { 359 Some(_) => {
@@ -436,12 +434,16 @@ impl<'a> InferenceContext<'a> {
436 /// to do it as well. 434 /// to do it as well.
437 fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { 435 fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty {
438 let ty = self.resolve_ty_as_possible(ty); 436 let ty = self.resolve_ty_as_possible(ty);
439 ty.fold(&mut |ty| match ty.kind(&Interner) { 437 fold_tys(
440 TyKind::Alias(AliasTy::Projection(proj_ty)) => { 438 ty,
441 self.normalize_projection_ty(proj_ty.clone()) 439 |ty, _| match ty.kind(&Interner) {
442 } 440 TyKind::Alias(AliasTy::Projection(proj_ty)) => {
443 _ => ty, 441 self.normalize_projection_ty(proj_ty.clone())
444 }) 442 }
443 _ => ty,
444 },
445 DebruijnIndex::INNERMOST,
446 )
445 } 447 }
446 448
447 fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { 449 fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
@@ -489,36 +491,13 @@ impl<'a> InferenceContext<'a> {
489 let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); 491 let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
490 let substs = generics.type_params_subst(self.db); 492 let substs = generics.type_params_subst(self.db);
491 let ty = self.db.impl_self_ty(impl_id).substitute(&Interner, &substs); 493 let ty = self.db.impl_self_ty(impl_id).substitute(&Interner, &substs);
492 match unresolved { 494 self.resolve_variant_on_alias(ty, unresolved, path)
493 None => {
494 let variant = ty_variant(&ty);
495 (ty, variant)
496 }
497 Some(1) => {
498 let segment = path.mod_path().segments().last().unwrap();
499 // this could be an enum variant or associated type
500 if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() {
501 let enum_data = self.db.enum_data(enum_id);
502 if let Some(local_id) = enum_data.variant(segment) {
503 let variant = EnumVariantId { parent: enum_id, local_id };
504 return (ty, Some(variant.into()));
505 }
506 }
507 // FIXME potentially resolve assoc type
508 (self.err_ty(), None)
509 }
510 Some(_) => {
511 // FIXME diagnostic
512 (self.err_ty(), None)
513 }
514 }
515 } 495 }
516 TypeNs::TypeAliasId(it) => { 496 TypeNs::TypeAliasId(it) => {
517 let ty = TyBuilder::def_ty(self.db, it.into()) 497 let ty = TyBuilder::def_ty(self.db, it.into())
518 .fill(std::iter::repeat_with(|| self.table.new_type_var())) 498 .fill(std::iter::repeat_with(|| self.table.new_type_var()))
519 .build(); 499 .build();
520 let variant = ty_variant(&ty); 500 self.resolve_variant_on_alias(ty, unresolved, path)
521 forbid_unresolved_segments((ty, variant), unresolved)
522 } 501 }
523 TypeNs::AdtSelfType(_) => { 502 TypeNs::AdtSelfType(_) => {
524 // FIXME this could happen in array size expressions, once we're checking them 503 // FIXME this could happen in array size expressions, once we're checking them
@@ -545,16 +524,43 @@ impl<'a> InferenceContext<'a> {
545 (TyKind::Error.intern(&Interner), None) 524 (TyKind::Error.intern(&Interner), None)
546 } 525 }
547 } 526 }
527 }
548 528
549 fn ty_variant(ty: &Ty) -> Option<VariantId> { 529 fn resolve_variant_on_alias(
550 ty.as_adt().and_then(|(adt_id, _)| match adt_id { 530 &mut self,
551 AdtId::StructId(s) => Some(VariantId::StructId(s)), 531 ty: Ty,
552 AdtId::UnionId(u) => Some(VariantId::UnionId(u)), 532 unresolved: Option<usize>,
553 AdtId::EnumId(_) => { 533 path: &Path,
554 // FIXME Error E0071, expected struct, variant or union type, found enum `Foo` 534 ) -> (Ty, Option<VariantId>) {
555 None 535 match unresolved {
536 None => {
537 let variant = ty.as_adt().and_then(|(adt_id, _)| match adt_id {
538 AdtId::StructId(s) => Some(VariantId::StructId(s)),
539 AdtId::UnionId(u) => Some(VariantId::UnionId(u)),
540 AdtId::EnumId(_) => {
541 // FIXME Error E0071, expected struct, variant or union type, found enum `Foo`
542 None
543 }
544 });
545 (ty, variant)
546 }
547 Some(1) => {
548 let segment = path.mod_path().segments().last().unwrap();
549 // this could be an enum variant or associated type
550 if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() {
551 let enum_data = self.db.enum_data(enum_id);
552 if let Some(local_id) = enum_data.variant(segment) {
553 let variant = EnumVariantId { parent: enum_id, local_id };
554 return (ty, Some(variant.into()));
555 }
556 } 556 }
557 }) 557 // FIXME potentially resolve assoc type
558 (self.err_ty(), None)
559 }
560 Some(_) => {
561 // FIXME diagnostic
562 (self.err_ty(), None)
563 }
558 } 564 }
559 } 565 }
560 566
@@ -692,25 +698,6 @@ impl<'a> InferenceContext<'a> {
692 } 698 }
693} 699}
694 700
695/// The kinds of placeholders we need during type inference. There's separate
696/// values for general types, and for integer and float variables. The latter
697/// two are used for inference of literal values (e.g. `100` could be one of
698/// several integer types).
699#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
700pub struct InferenceVar {
701 index: u32,
702}
703
704impl InferenceVar {
705 fn to_inner(self) -> unify::TypeVarId {
706 unify::TypeVarId(self.index)
707 }
708
709 fn from_inner(unify::TypeVarId(index): unify::TypeVarId) -> Self {
710 InferenceVar { index }
711 }
712}
713
714/// When inferring an expression, we propagate downward whatever type hint we 701/// When inferring an expression, we propagate downward whatever type hint we
715/// are able in the form of an `Expectation`. 702/// are able in the form of an `Expectation`.
716#[derive(Clone, PartialEq, Eq, Debug)] 703#[derive(Clone, PartialEq, Eq, Debug)]
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs
index 32c273afc..1f463a425 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, TyKind}; 10use crate::{autoderef, Canonical, Interner, Solution, Ty, TyBuilder, TyExt, TyKind};
11 11
12use super::{InEnvironment, InferenceContext}; 12use super::{InEnvironment, InferenceContext};
13 13
@@ -71,17 +71,19 @@ impl<'a> InferenceContext<'a> {
71 } 71 }
72 72
73 // Pointer weakening and function to pointer 73 // Pointer weakening and function to pointer
74 match (from_ty.interned_mut(), to_ty.kind(&Interner)) { 74 match (from_ty.kind(&Interner), to_ty.kind(&Interner)) {
75 // `*mut T` -> `*const T` 75 // `*mut T` -> `*const T`
76 (TyKind::Raw(_, inner), TyKind::Raw(m2 @ Mutability::Not, ..)) => {
77 from_ty = TyKind::Raw(*m2, inner.clone()).intern(&Interner);
78 }
76 // `&mut T` -> `&T` 79 // `&mut T` -> `&T`
77 (TyKind::Raw(m1, ..), TyKind::Raw(m2 @ Mutability::Not, ..)) 80 (TyKind::Ref(_, lt, inner), TyKind::Ref(m2 @ Mutability::Not, ..)) => {
78 | (TyKind::Ref(m1, ..), TyKind::Ref(m2 @ Mutability::Not, ..)) => { 81 from_ty = TyKind::Ref(*m2, lt.clone(), inner.clone()).intern(&Interner);
79 *m1 = *m2;
80 } 82 }
81 // `&T` -> `*const T` 83 // `&T` -> `*const T`
82 // `&mut T` -> `*mut T`/`*const T` 84 // `&mut T` -> `*mut T`/`*const T`
83 (TyKind::Ref(.., substs), &TyKind::Raw(m2 @ Mutability::Not, ..)) 85 (TyKind::Ref(.., substs), &TyKind::Raw(m2 @ Mutability::Not, ..))
84 | (TyKind::Ref(Mutability::Mut, substs), &TyKind::Raw(m2, ..)) => { 86 | (TyKind::Ref(Mutability::Mut, _, substs), &TyKind::Raw(m2, ..)) => {
85 from_ty = TyKind::Raw(m2, substs.clone()).intern(&Interner); 87 from_ty = TyKind::Raw(m2, substs.clone()).intern(&Interner);
86 } 88 }
87 89
@@ -111,7 +113,9 @@ impl<'a> InferenceContext<'a> {
111 // Auto Deref if cannot coerce 113 // Auto Deref if cannot coerce
112 match (from_ty.kind(&Interner), to_ty.kind(&Interner)) { 114 match (from_ty.kind(&Interner), to_ty.kind(&Interner)) {
113 // FIXME: DerefMut 115 // FIXME: DerefMut
114 (TyKind::Ref(_, st1), TyKind::Ref(_, st2)) => self.unify_autoderef_behind_ref(st1, st2), 116 (TyKind::Ref(.., st1), TyKind::Ref(.., st2)) => {
117 self.unify_autoderef_behind_ref(st1, st2)
118 }
115 119
116 // Otherwise, normal unify 120 // Otherwise, normal unify
117 _ => self.unify(&from_ty, to_ty), 121 _ => self.unify(&from_ty, to_ty),
@@ -137,7 +141,7 @@ impl<'a> InferenceContext<'a> {
137 b.push(from_ty.clone()).push(to_ty.clone()).build() 141 b.push(from_ty.clone()).push(to_ty.clone()).build()
138 }; 142 };
139 143
140 let goal = InEnvironment::new(self.trait_env.env.clone(), trait_ref.cast(&Interner)); 144 let goal = InEnvironment::new(&self.trait_env.env, trait_ref.cast(&Interner));
141 145
142 let canonicalizer = self.canonicalizer(); 146 let canonicalizer = self.canonicalizer();
143 let canonicalized = canonicalizer.canonicalize_obligation(goal); 147 let canonicalized = canonicalizer.canonicalize_obligation(goal);
@@ -146,7 +150,14 @@ impl<'a> InferenceContext<'a> {
146 150
147 match solution { 151 match solution {
148 Solution::Unique(v) => { 152 Solution::Unique(v) => {
149 canonicalized.apply_solution(self, v.0); 153 canonicalized.apply_solution(
154 self,
155 Canonical {
156 binders: v.binders,
157 // FIXME handle constraints
158 value: v.value.subst,
159 },
160 );
150 } 161 }
151 _ => return None, 162 _ => return None,
152 }; 163 };
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index 6966d26e7..50497eecb 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -3,7 +3,7 @@
3use std::iter::{repeat, repeat_with}; 3use std::iter::{repeat, repeat_with};
4use std::{mem, sync::Arc}; 4use std::{mem, sync::Arc};
5 5
6use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; 6use chalk_ir::{cast::Cast, fold::Shift, Mutability, TyVariableKind};
7use hir_def::{ 7use hir_def::{
8 expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, 8 expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
9 path::{GenericArg, GenericArgs}, 9 path::{GenericArg, GenericArgs},
@@ -15,15 +15,16 @@ use stdx::always;
15use syntax::ast::RangeOp; 15use syntax::ast::RangeOp;
16 16
17use crate::{ 17use crate::{
18 autoderef, 18 autoderef, dummy_usize_const,
19 lower::lower_to_chalk_mutability, 19 lower::lower_to_chalk_mutability,
20 mapping::from_chalk,
20 method_resolution, op, 21 method_resolution, op,
21 primitive::{self, UintTy}, 22 primitive::{self, UintTy},
22 to_chalk_trait_id, 23 static_lifetime, to_chalk_trait_id,
23 traits::{chalk::from_chalk, FnTrait}, 24 traits::FnTrait,
24 utils::{generics, variant_data, Generics}, 25 utils::{generics, Generics},
25 AdtId, Binders, CallableDefId, FnPointer, FnSig, InEnvironment, Interner, Rawness, Scalar, 26 AdtId, Binders, CallableDefId, FnPointer, FnSig, FnSubst, InEnvironment, Interner,
26 Substitution, TraitRef, Ty, TyBuilder, TyKind, 27 ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind,
27}; 28};
28 29
29use super::{ 30use super::{
@@ -180,7 +181,8 @@ impl<'a> InferenceContext<'a> {
180 let inner_ty = self.infer_expr(*body, &Expectation::none()); 181 let inner_ty = self.infer_expr(*body, &Expectation::none());
181 let impl_trait_id = crate::ImplTraitId::AsyncBlockTypeImplTrait(self.owner, *body); 182 let impl_trait_id = crate::ImplTraitId::AsyncBlockTypeImplTrait(self.owner, *body);
182 let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into(); 183 let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
183 TyKind::OpaqueType(opaque_ty_id, Substitution::single(inner_ty)).intern(&Interner) 184 TyKind::OpaqueType(opaque_ty_id, Substitution::from1(&Interner, inner_ty))
185 .intern(&Interner)
184 } 186 }
185 Expr::Loop { body, label } => { 187 Expr::Loop { body, label } => {
186 self.breakables.push(BreakableContext { 188 self.breakables.push(BreakableContext {
@@ -259,14 +261,17 @@ impl<'a> InferenceContext<'a> {
259 }; 261 };
260 sig_tys.push(ret_ty.clone()); 262 sig_tys.push(ret_ty.clone());
261 let sig_ty = TyKind::Function(FnPointer { 263 let sig_ty = TyKind::Function(FnPointer {
262 num_args: sig_tys.len() - 1, 264 num_binders: 0,
263 sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false }, 265 sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false },
264 substs: Substitution::from_iter(&Interner, sig_tys.clone()), 266 substitution: FnSubst(
267 Substitution::from_iter(&Interner, sig_tys.clone()).shifted_in(&Interner),
268 ),
265 }) 269 })
266 .intern(&Interner); 270 .intern(&Interner);
267 let closure_id = self.db.intern_closure((self.owner, tgt_expr)).into(); 271 let closure_id = self.db.intern_closure((self.owner, tgt_expr)).into();
268 let closure_ty = 272 let closure_ty =
269 TyKind::Closure(closure_id, Substitution::single(sig_ty)).intern(&Interner); 273 TyKind::Closure(closure_id, Substitution::from1(&Interner, sig_ty))
274 .intern(&Interner);
270 275
271 // Eagerly try to relate the closure type with the expected 276 // Eagerly try to relate the closure type with the expected
272 // type, otherwise we often won't have enough information to 277 // type, otherwise we often won't have enough information to
@@ -313,7 +318,13 @@ impl<'a> InferenceContext<'a> {
313 self.normalize_associated_types_in(ret_ty) 318 self.normalize_associated_types_in(ret_ty)
314 } 319 }
315 Expr::MethodCall { receiver, args, method_name, generic_args } => self 320 Expr::MethodCall { receiver, args, method_name, generic_args } => self
316 .infer_method_call(tgt_expr, *receiver, &args, &method_name, generic_args.as_ref()), 321 .infer_method_call(
322 tgt_expr,
323 *receiver,
324 &args,
325 &method_name,
326 generic_args.as_deref(),
327 ),
317 Expr::Match { expr, arms } => { 328 Expr::Match { expr, arms } => {
318 let input_ty = self.infer_expr(*expr, &Expectation::none()); 329 let input_ty = self.infer_expr(*expr, &Expectation::none());
319 330
@@ -394,16 +405,19 @@ impl<'a> InferenceContext<'a> {
394 TyKind::Never.intern(&Interner) 405 TyKind::Never.intern(&Interner)
395 } 406 }
396 Expr::RecordLit { path, fields, spread } => { 407 Expr::RecordLit { path, fields, spread } => {
397 let (ty, def_id) = self.resolve_variant(path.as_ref()); 408 let (ty, def_id) = self.resolve_variant(path.as_deref());
398 if let Some(variant) = def_id { 409 if let Some(variant) = def_id {
399 self.write_variant_resolution(tgt_expr.into(), variant); 410 self.write_variant_resolution(tgt_expr.into(), variant);
400 } 411 }
401 412
402 self.unify(&ty, &expected.ty); 413 self.unify(&ty, &expected.ty);
403 414
404 let substs = ty.substs().cloned().unwrap_or_else(|| Substitution::empty(&Interner)); 415 let substs = ty
416 .as_adt()
417 .map(|(_, s)| s.clone())
418 .unwrap_or_else(|| Substitution::empty(&Interner));
405 let field_types = def_id.map(|it| self.db.field_types(it)).unwrap_or_default(); 419 let field_types = def_id.map(|it| self.db.field_types(it)).unwrap_or_default();
406 let variant_data = def_id.map(|it| variant_data(self.db.upcast(), it)); 420 let variant_data = def_id.map(|it| it.variant_data(self.db.upcast()));
407 for field in fields.iter() { 421 for field in fields.iter() {
408 let field_def = 422 let field_def =
409 variant_data.as_ref().and_then(|it| match it.field(&field.name) { 423 variant_data.as_ref().and_then(|it| match it.field(&field.name) {
@@ -415,9 +429,6 @@ impl<'a> InferenceContext<'a> {
415 None 429 None
416 } 430 }
417 }); 431 });
418 if let Some(field_def) = field_def {
419 self.result.record_field_resolutions.insert(field.expr, field_def);
420 }
421 let field_ty = field_def.map_or(self.err_ty(), |it| { 432 let field_ty = field_def.map_or(self.err_ty(), |it| {
422 field_types[it.local_id].clone().substitute(&Interner, &substs) 433 field_types[it.local_id].clone().substitute(&Interner, &substs)
423 }); 434 });
@@ -452,7 +463,11 @@ impl<'a> InferenceContext<'a> {
452 }; 463 };
453 match canonicalized.decanonicalize_ty(derefed_ty.value).kind(&Interner) { 464 match canonicalized.decanonicalize_ty(derefed_ty.value).kind(&Interner) {
454 TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| { 465 TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| {
455 substs.interned().get(idx).map(|a| a.assert_ty_ref(&Interner)).cloned() 466 substs
467 .as_slice(&Interner)
468 .get(idx)
469 .map(|a| a.assert_ty_ref(&Interner))
470 .cloned()
456 }), 471 }),
457 TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { 472 TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => {
458 let local_id = self.db.struct_data(*s).variant_data.field(name)?; 473 let local_id = self.db.struct_data(*s).variant_data.field(name)?;
@@ -523,7 +538,7 @@ impl<'a> InferenceContext<'a> {
523 let inner_ty = self.infer_expr_inner(*expr, &expectation); 538 let inner_ty = self.infer_expr_inner(*expr, &expectation);
524 match rawness { 539 match rawness {
525 Rawness::RawPtr => TyKind::Raw(mutability, inner_ty), 540 Rawness::RawPtr => TyKind::Raw(mutability, inner_ty),
526 Rawness::Ref => TyKind::Ref(mutability, inner_ty), 541 Rawness::Ref => TyKind::Ref(mutability, static_lifetime(), inner_ty),
527 } 542 }
528 .intern(&Interner) 543 .intern(&Interner)
529 } 544 }
@@ -698,7 +713,7 @@ impl<'a> InferenceContext<'a> {
698 } 713 }
699 Expr::Array(array) => { 714 Expr::Array(array) => {
700 let elem_ty = match expected.ty.kind(&Interner) { 715 let elem_ty = match expected.ty.kind(&Interner) {
701 TyKind::Array(st) | TyKind::Slice(st) => st.clone(), 716 TyKind::Array(st, _) | TyKind::Slice(st) => st.clone(),
702 _ => self.table.new_type_var(), 717 _ => self.table.new_type_var(),
703 }; 718 };
704 719
@@ -722,17 +737,19 @@ impl<'a> InferenceContext<'a> {
722 } 737 }
723 } 738 }
724 739
725 TyKind::Array(elem_ty).intern(&Interner) 740 TyKind::Array(elem_ty, dummy_usize_const()).intern(&Interner)
726 } 741 }
727 Expr::Literal(lit) => match lit { 742 Expr::Literal(lit) => match lit {
728 Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner), 743 Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
729 Literal::String(..) => { 744 Literal::String(..) => {
730 TyKind::Ref(Mutability::Not, TyKind::Str.intern(&Interner)).intern(&Interner) 745 TyKind::Ref(Mutability::Not, static_lifetime(), TyKind::Str.intern(&Interner))
746 .intern(&Interner)
731 } 747 }
732 Literal::ByteString(..) => { 748 Literal::ByteString(..) => {
733 let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner); 749 let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner);
734 let array_type = TyKind::Array(byte_type).intern(&Interner); 750 let array_type =
735 TyKind::Ref(Mutability::Not, array_type).intern(&Interner) 751 TyKind::Array(byte_type, dummy_usize_const()).intern(&Interner);
752 TyKind::Ref(Mutability::Not, static_lifetime(), array_type).intern(&Interner)
736 } 753 }
737 Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner), 754 Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner),
738 Literal::Int(_v, ty) => match ty { 755 Literal::Int(_v, ty) => match ty {
@@ -868,7 +885,9 @@ impl<'a> InferenceContext<'a> {
868 // Apply autoref so the below unification works correctly 885 // Apply autoref so the below unification works correctly
869 // FIXME: return correct autorefs from lookup_method 886 // FIXME: return correct autorefs from lookup_method
870 let actual_receiver_ty = match expected_receiver_ty.as_reference() { 887 let actual_receiver_ty = match expected_receiver_ty.as_reference() {
871 Some((_, mutability)) => TyKind::Ref(mutability, derefed_receiver_ty).intern(&Interner), 888 Some((_, lifetime, mutability)) => {
889 TyKind::Ref(mutability, lifetime, derefed_receiver_ty).intern(&Interner)
890 }
872 _ => derefed_receiver_ty, 891 _ => derefed_receiver_ty,
873 }; 892 };
874 self.unify(&expected_receiver_ty, &actual_receiver_ty); 893 self.unify(&expected_receiver_ty, &actual_receiver_ty);
@@ -962,8 +981,10 @@ impl<'a> InferenceContext<'a> {
962 if let AssocContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container 981 if let AssocContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container
963 { 982 {
964 // construct a TraitRef 983 // construct a TraitRef
965 let substs = 984 let substs = crate::subst_prefix(
966 parameters.prefix(generics(self.db.upcast(), trait_.into()).len()); 985 &*parameters,
986 generics(self.db.upcast(), trait_.into()).len(),
987 );
967 self.push_obligation( 988 self.push_obligation(
968 TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs } 989 TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }
969 .cast(&Interner), 990 .cast(&Interner),
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index 252ae914a..aea354cde 100644
--- a/crates/hir_ty/src/infer/pat.rs
+++ b/crates/hir_ty/src/infer/pat.rs
@@ -7,14 +7,13 @@ 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
14use super::{BindingMode, Expectation, InferenceContext}; 13use super::{BindingMode, Expectation, InferenceContext};
15use crate::{ 14use crate::{
16 lower::lower_to_chalk_mutability, utils::variant_data, Interner, Substitution, Ty, TyBuilder, 15 lower::lower_to_chalk_mutability, static_lifetime, Interner, Substitution, Ty, TyBuilder,
17 TyKind, 16 TyExt, TyKind,
18}; 17};
19 18
20impl<'a> InferenceContext<'a> { 19impl<'a> InferenceContext<'a> {
@@ -28,13 +27,14 @@ impl<'a> InferenceContext<'a> {
28 ellipsis: Option<usize>, 27 ellipsis: Option<usize>,
29 ) -> Ty { 28 ) -> Ty {
30 let (ty, def) = self.resolve_variant(path); 29 let (ty, def) = self.resolve_variant(path);
31 let var_data = def.map(|it| variant_data(self.db.upcast(), it)); 30 let var_data = def.map(|it| it.variant_data(self.db.upcast()));
32 if let Some(variant) = def { 31 if let Some(variant) = def {
33 self.write_variant_resolution(id.into(), variant); 32 self.write_variant_resolution(id.into(), variant);
34 } 33 }
35 self.unify(&ty, expected); 34 self.unify(&ty, expected);
36 35
37 let substs = ty.substs().cloned().unwrap_or_else(|| Substitution::empty(&Interner)); 36 let substs =
37 ty.as_adt().map(|(_, s)| s.clone()).unwrap_or_else(|| Substitution::empty(&Interner));
38 38
39 let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); 39 let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default();
40 let (pre, post) = match ellipsis { 40 let (pre, post) = match ellipsis {
@@ -68,23 +68,19 @@ impl<'a> InferenceContext<'a> {
68 id: PatId, 68 id: PatId,
69 ) -> Ty { 69 ) -> Ty {
70 let (ty, def) = self.resolve_variant(path); 70 let (ty, def) = self.resolve_variant(path);
71 let var_data = def.map(|it| variant_data(self.db.upcast(), it)); 71 let var_data = def.map(|it| it.variant_data(self.db.upcast()));
72 if let Some(variant) = def { 72 if let Some(variant) = def {
73 self.write_variant_resolution(id.into(), variant); 73 self.write_variant_resolution(id.into(), variant);
74 } 74 }
75 75
76 self.unify(&ty, expected); 76 self.unify(&ty, expected);
77 77
78 let substs = ty.substs().cloned().unwrap_or_else(|| Substitution::empty(&Interner)); 78 let substs =
79 ty.as_adt().map(|(_, s)| s.clone()).unwrap_or_else(|| Substitution::empty(&Interner));
79 80
80 let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); 81 let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default();
81 for subpat in subpats { 82 for subpat in subpats {
82 let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name)); 83 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| { 84 let expected_ty = matching_field.map_or(self.err_ty(), |field| {
89 field_tys[field].clone().substitute(&Interner, &substs) 85 field_tys[field].clone().substitute(&Interner, &substs)
90 }); 86 });
@@ -104,7 +100,7 @@ impl<'a> InferenceContext<'a> {
104 let body = Arc::clone(&self.body); // avoid borrow checker problem 100 let body = Arc::clone(&self.body); // avoid borrow checker problem
105 101
106 if is_non_ref_pat(&body, pat) { 102 if is_non_ref_pat(&body, pat) {
107 while let Some((inner, mutability)) = expected.as_reference() { 103 while let Some((inner, _lifetime, mutability)) = expected.as_reference() {
108 expected = inner; 104 expected = inner;
109 default_bm = match default_bm { 105 default_bm = match default_bm {
110 BindingMode::Move => BindingMode::Ref(mutability), 106 BindingMode::Move => BindingMode::Ref(mutability),
@@ -126,7 +122,7 @@ impl<'a> InferenceContext<'a> {
126 let ty = match &body[pat] { 122 let ty = match &body[pat] {
127 &Pat::Tuple { ref args, ellipsis } => { 123 &Pat::Tuple { ref args, ellipsis } => {
128 let expectations = match expected.as_tuple() { 124 let expectations = match expected.as_tuple() {
129 Some(parameters) => &*parameters.interned(), 125 Some(parameters) => &*parameters.as_slice(&Interner),
130 _ => &[], 126 _ => &[],
131 }; 127 };
132 128
@@ -162,7 +158,7 @@ impl<'a> InferenceContext<'a> {
162 Pat::Ref { pat, mutability } => { 158 Pat::Ref { pat, mutability } => {
163 let mutability = lower_to_chalk_mutability(*mutability); 159 let mutability = lower_to_chalk_mutability(*mutability);
164 let expectation = match expected.as_reference() { 160 let expectation = match expected.as_reference() {
165 Some((inner_ty, exp_mut)) => { 161 Some((inner_ty, _lifetime, exp_mut)) => {
166 if mutability != exp_mut { 162 if mutability != exp_mut {
167 // FIXME: emit type error? 163 // FIXME: emit type error?
168 } 164 }
@@ -171,10 +167,10 @@ impl<'a> InferenceContext<'a> {
171 _ => self.result.standard_types.unknown.clone(), 167 _ => self.result.standard_types.unknown.clone(),
172 }; 168 };
173 let subty = self.infer_pat(*pat, &expectation, default_bm); 169 let subty = self.infer_pat(*pat, &expectation, default_bm);
174 TyKind::Ref(mutability, subty).intern(&Interner) 170 TyKind::Ref(mutability, static_lifetime(), subty).intern(&Interner)
175 } 171 }
176 Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat( 172 Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat(
177 p.as_ref(), 173 p.as_deref(),
178 subpats, 174 subpats,
179 expected, 175 expected,
180 default_bm, 176 default_bm,
@@ -182,7 +178,7 @@ impl<'a> InferenceContext<'a> {
182 *ellipsis, 178 *ellipsis,
183 ), 179 ),
184 Pat::Record { path: p, args: fields, ellipsis: _ } => { 180 Pat::Record { path: p, args: fields, ellipsis: _ } => {
185 self.infer_record_pat(p.as_ref(), fields, expected, default_bm, pat) 181 self.infer_record_pat(p.as_deref(), fields, expected, default_bm, pat)
186 } 182 }
187 Pat::Path(path) => { 183 Pat::Path(path) => {
188 // FIXME use correct resolver for the surrounding expression 184 // FIXME use correct resolver for the surrounding expression
@@ -204,7 +200,8 @@ impl<'a> InferenceContext<'a> {
204 200
205 let bound_ty = match mode { 201 let bound_ty = match mode {
206 BindingMode::Ref(mutability) => { 202 BindingMode::Ref(mutability) => {
207 TyKind::Ref(mutability, inner_ty.clone()).intern(&Interner) 203 TyKind::Ref(mutability, static_lifetime(), inner_ty.clone())
204 .intern(&Interner)
208 } 205 }
209 BindingMode::Move => inner_ty.clone(), 206 BindingMode::Move => inner_ty.clone(),
210 }; 207 };
@@ -213,17 +210,20 @@ impl<'a> InferenceContext<'a> {
213 return inner_ty; 210 return inner_ty;
214 } 211 }
215 Pat::Slice { prefix, slice, suffix } => { 212 Pat::Slice { prefix, slice, suffix } => {
216 let (container_ty, elem_ty): (fn(_) -> _, _) = match expected.kind(&Interner) { 213 let elem_ty = match expected.kind(&Interner) {
217 TyKind::Array(st) => (TyKind::Array, st.clone()), 214 TyKind::Array(st, _) | TyKind::Slice(st) => st.clone(),
218 TyKind::Slice(st) => (TyKind::Slice, st.clone()), 215 _ => self.err_ty(),
219 _ => (TyKind::Slice, self.err_ty()),
220 }; 216 };
221 217
222 for pat_id in prefix.iter().chain(suffix) { 218 for pat_id in prefix.iter().chain(suffix) {
223 self.infer_pat(*pat_id, &elem_ty, default_bm); 219 self.infer_pat(*pat_id, &elem_ty, default_bm);
224 } 220 }
225 221
226 let pat_ty = container_ty(elem_ty).intern(&Interner); 222 let pat_ty = match expected.kind(&Interner) {
223 TyKind::Array(_, const_) => TyKind::Array(elem_ty, const_.clone()),
224 _ => TyKind::Slice(elem_ty),
225 }
226 .intern(&Interner);
227 if let Some(slice_pat_id) = slice { 227 if let Some(slice_pat_id) = slice {
228 self.infer_pat(*slice_pat_id, &pat_ty, default_bm); 228 self.infer_pat(*slice_pat_id, &pat_ty, default_bm);
229 } 229 }
@@ -242,7 +242,7 @@ impl<'a> InferenceContext<'a> {
242 let (inner_ty, alloc_ty) = match expected.as_adt() { 242 let (inner_ty, alloc_ty) = match expected.as_adt() {
243 Some((adt, subst)) if adt == box_adt => ( 243 Some((adt, subst)) if adt == box_adt => (
244 subst.at(&Interner, 0).assert_ty_ref(&Interner).clone(), 244 subst.at(&Interner, 0).assert_ty_ref(&Interner).clone(),
245 subst.interned().get(1).and_then(|a| a.ty(&Interner).cloned()), 245 subst.as_slice(&Interner).get(1).and_then(|a| a.ty(&Interner).cloned()),
246 ), 246 ),
247 _ => (self.result.standard_types.unknown.clone(), None), 247 _ => (self.result.standard_types.unknown.clone(), None),
248 }; 248 };
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs
index 14f705173..495282eba 100644
--- a/crates/hir_ty/src/infer/path.rs
+++ b/crates/hir_ty/src/infer/path.rs
@@ -10,7 +10,10 @@ use hir_def::{
10}; 10};
11use hir_expand::name::Name; 11use hir_expand::name::Name;
12 12
13use crate::{method_resolution, Interner, Substitution, Ty, TyBuilder, TyKind, ValueTyDefId}; 13use crate::{
14 method_resolution, Interner, Substitution, TraitRefExt, Ty, TyBuilder, TyExt, TyKind,
15 ValueTyDefId,
16};
14 17
15use super::{ExprOrPatId, InferenceContext, TraitRef}; 18use super::{ExprOrPatId, InferenceContext, TraitRef};
16 19
@@ -98,7 +101,7 @@ impl<'a> InferenceContext<'a> {
98 let substs = ctx.substs_from_path(path, typable, true); 101 let substs = ctx.substs_from_path(path, typable, true);
99 let ty = TyBuilder::value_ty(self.db, typable) 102 let ty = TyBuilder::value_ty(self.db, typable)
100 .use_parent_substs(&parent_substs) 103 .use_parent_substs(&parent_substs)
101 .fill(substs.interned()[parent_substs.len(&Interner)..].iter().cloned()) 104 .fill(substs.as_slice(&Interner)[parent_substs.len(&Interner)..].iter().cloned())
102 .build(); 105 .build();
103 Some(ty) 106 Some(ty)
104 } 107 }
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs
index c90a16720..a887e20b0 100644
--- a/crates/hir_ty/src/infer/unify.rs
+++ b/crates/hir_ty/src/infer/unify.rs
@@ -2,13 +2,17 @@
2 2
3use std::borrow::Cow; 3use std::borrow::Cow;
4 4
5use chalk_ir::{FloatTy, IntTy, TyVariableKind, UniverseIndex, VariableKind}; 5use chalk_ir::{
6 cast::Cast, fold::Fold, interner::HasInterner, FloatTy, IntTy, TyVariableKind, UniverseIndex,
7 VariableKind,
8};
6use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; 9use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
7 10
8use super::{DomainGoal, InferenceContext}; 11use super::{DomainGoal, InferenceContext};
9use crate::{ 12use crate::{
10 AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, 13 fold_tys, static_lifetime, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds,
11 InEnvironment, InferenceVar, Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, WhereClause, 14 DebruijnIndex, FnPointer, FnSubst, InEnvironment, InferenceVar, Interner, Scalar, Substitution,
15 Ty, TyExt, TyKind, WhereClause,
12}; 16};
13 17
14impl<'a> InferenceContext<'a> { 18impl<'a> InferenceContext<'a> {
@@ -33,7 +37,10 @@ where
33} 37}
34 38
35#[derive(Debug)] 39#[derive(Debug)]
36pub(super) struct Canonicalized<T> { 40pub(super) struct Canonicalized<T>
41where
42 T: HasInterner<Interner = Interner>,
43{
37 pub(super) value: Canonical<T>, 44 pub(super) value: Canonical<T>,
38 free_vars: Vec<(InferenceVar, TyVariableKind)>, 45 free_vars: Vec<(InferenceVar, TyVariableKind)>,
39} 46}
@@ -47,11 +54,16 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
47 }) 54 })
48 } 55 }
49 56
50 fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: DebruijnIndex) -> T { 57 fn do_canonicalize<T: Fold<Interner, Result = T> + HasInterner<Interner = Interner>>(
51 t.fold_binders( 58 &mut self,
52 &mut |ty, binders| match ty.kind(&Interner) { 59 t: T,
60 binders: DebruijnIndex,
61 ) -> T {
62 fold_tys(
63 t,
64 |ty, binders| match ty.kind(&Interner) {
53 &TyKind::InferenceVar(var, kind) => { 65 &TyKind::InferenceVar(var, kind) => {
54 let inner = var.to_inner(); 66 let inner = from_inference_var(var);
55 if self.var_stack.contains(&inner) { 67 if self.var_stack.contains(&inner) {
56 // recursive type 68 // recursive type
57 return self.ctx.table.type_variable_table.fallback_value(var, kind); 69 return self.ctx.table.type_variable_table.fallback_value(var, kind);
@@ -65,7 +77,7 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
65 result 77 result
66 } else { 78 } else {
67 let root = self.ctx.table.var_unification_table.find(inner); 79 let root = self.ctx.table.var_unification_table.find(inner);
68 let position = self.add(InferenceVar::from_inner(root), kind); 80 let position = self.add(to_inference_var(root), kind);
69 TyKind::BoundVar(BoundVar::new(binders, position)).intern(&Interner) 81 TyKind::BoundVar(BoundVar::new(binders, position)).intern(&Interner)
70 } 82 }
71 } 83 }
@@ -75,7 +87,10 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
75 ) 87 )
76 } 88 }
77 89
78 fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { 90 fn into_canonicalized<T: HasInterner<Interner = Interner>>(
91 self,
92 result: T,
93 ) -> Canonicalized<T> {
79 let kinds = self 94 let kinds = self
80 .free_vars 95 .free_vars
81 .iter() 96 .iter()
@@ -102,28 +117,18 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
102 DomainGoal::Holds(wc) => { 117 DomainGoal::Holds(wc) => {
103 DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST)) 118 DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST))
104 } 119 }
120 _ => unimplemented!(),
105 }; 121 };
106 self.into_canonicalized(InEnvironment { goal: result, environment: obligation.environment }) 122 self.into_canonicalized(InEnvironment { goal: result, environment: obligation.environment })
107 } 123 }
108} 124}
109 125
110impl<T> Canonicalized<T> { 126impl<T: HasInterner<Interner = Interner>> Canonicalized<T> {
111 pub(super) fn decanonicalize_ty(&self, ty: Ty) -> Ty { 127 pub(super) fn decanonicalize_ty(&self, ty: Ty) -> Ty {
112 ty.fold_binders( 128 crate::fold_free_vars(ty, |bound, _binders| {
113 &mut |ty, binders| { 129 let (v, k) = self.free_vars[bound.index];
114 if let TyKind::BoundVar(bound) = ty.kind(&Interner) { 130 TyKind::InferenceVar(v, k).intern(&Interner)
115 if bound.debruijn >= binders { 131 })
116 let (v, k) = self.free_vars[bound.index];
117 TyKind::InferenceVar(v, k).intern(&Interner)
118 } else {
119 ty
120 }
121 } else {
122 ty
123 }
124 },
125 DebruijnIndex::INNERMOST,
126 )
127 } 132 }
128 133
129 pub(super) fn apply_solution( 134 pub(super) fn apply_solution(
@@ -135,15 +140,17 @@ impl<T> Canonicalized<T> {
135 let new_vars = Substitution::from_iter( 140 let new_vars = Substitution::from_iter(
136 &Interner, 141 &Interner,
137 solution.binders.iter(&Interner).map(|k| match k.kind { 142 solution.binders.iter(&Interner).map(|k| match k.kind {
138 VariableKind::Ty(TyVariableKind::General) => ctx.table.new_type_var(), 143 VariableKind::Ty(TyVariableKind::General) => {
139 VariableKind::Ty(TyVariableKind::Integer) => ctx.table.new_integer_var(), 144 ctx.table.new_type_var().cast(&Interner)
140 VariableKind::Ty(TyVariableKind::Float) => ctx.table.new_float_var(), 145 }
141 // HACK: Chalk can sometimes return new lifetime variables. We 146 VariableKind::Ty(TyVariableKind::Integer) => {
142 // want to just skip them, but to not mess up the indices of 147 ctx.table.new_integer_var().cast(&Interner)
143 // other variables, we'll just create a new type variable in 148 }
144 // their place instead. This should not matter (we never see the 149 VariableKind::Ty(TyVariableKind::Float) => {
145 // actual *uses* of the lifetime variable). 150 ctx.table.new_float_var().cast(&Interner)
146 VariableKind::Lifetime => ctx.table.new_type_var(), 151 }
152 // Chalk can sometimes return new lifetime variables. We just use the static lifetime everywhere
153 VariableKind::Lifetime => static_lifetime().cast(&Interner),
147 _ => panic!("const variable in solution"), 154 _ => panic!("const variable in solution"),
148 }), 155 }),
149 ); 156 );
@@ -207,16 +214,16 @@ impl TypeVariableTable {
207 } 214 }
208 215
209 pub(super) fn set_diverging(&mut self, iv: InferenceVar, diverging: bool) { 216 pub(super) fn set_diverging(&mut self, iv: InferenceVar, diverging: bool) {
210 self.inner[iv.to_inner().0 as usize].diverging = diverging; 217 self.inner[from_inference_var(iv).0 as usize].diverging = diverging;
211 } 218 }
212 219
213 fn is_diverging(&mut self, iv: InferenceVar) -> bool { 220 fn is_diverging(&mut self, iv: InferenceVar) -> bool {
214 self.inner[iv.to_inner().0 as usize].diverging 221 self.inner[from_inference_var(iv).0 as usize].diverging
215 } 222 }
216 223
217 fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty { 224 fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty {
218 match kind { 225 match kind {
219 _ if self.inner[iv.to_inner().0 as usize].diverging => TyKind::Never, 226 _ if self.inner[from_inference_var(iv).0 as usize].diverging => TyKind::Never,
220 TyVariableKind::General => TyKind::Error, 227 TyVariableKind::General => TyKind::Error,
221 TyVariableKind::Integer => TyKind::Scalar(Scalar::Int(IntTy::I32)), 228 TyVariableKind::Integer => TyKind::Scalar(Scalar::Int(IntTy::I32)),
222 TyVariableKind::Float => TyKind::Scalar(Scalar::Float(FloatTy::F64)), 229 TyVariableKind::Float => TyKind::Scalar(Scalar::Float(FloatTy::F64)),
@@ -250,7 +257,7 @@ impl InferenceTable {
250 self.type_variable_table.push(TypeVariableData { diverging }); 257 self.type_variable_table.push(TypeVariableData { diverging });
251 let key = self.var_unification_table.new_key(TypeVarValue::Unknown); 258 let key = self.var_unification_table.new_key(TypeVarValue::Unknown);
252 assert_eq!(key.0 as usize, self.type_variable_table.inner.len() - 1); 259 assert_eq!(key.0 as usize, self.type_variable_table.inner.len() - 1);
253 TyKind::InferenceVar(InferenceVar::from_inner(key), kind).intern(&Interner) 260 TyKind::InferenceVar(to_inference_var(key), kind).intern(&Interner)
254 } 261 }
255 262
256 pub(crate) fn new_type_var(&mut self) -> Ty { 263 pub(crate) fn new_type_var(&mut self) -> Ty {
@@ -308,8 +315,8 @@ impl InferenceTable {
308 (TyKind::Adt(_, substs1), TyKind::Adt(_, substs2)) 315 (TyKind::Adt(_, substs1), TyKind::Adt(_, substs2))
309 | (TyKind::FnDef(_, substs1), TyKind::FnDef(_, substs2)) 316 | (TyKind::FnDef(_, substs1), TyKind::FnDef(_, substs2))
310 | ( 317 | (
311 TyKind::Function(FnPointer { substs: substs1, .. }), 318 TyKind::Function(FnPointer { substitution: FnSubst(substs1), .. }),
312 TyKind::Function(FnPointer { substs: substs2, .. }), 319 TyKind::Function(FnPointer { substitution: FnSubst(substs2), .. }),
313 ) 320 )
314 | (TyKind::Tuple(_, substs1), TyKind::Tuple(_, substs2)) 321 | (TyKind::Tuple(_, substs1), TyKind::Tuple(_, substs2))
315 | (TyKind::OpaqueType(_, substs1), TyKind::OpaqueType(_, substs2)) 322 | (TyKind::OpaqueType(_, substs1), TyKind::OpaqueType(_, substs2))
@@ -317,9 +324,11 @@ impl InferenceTable {
317 | (TyKind::Closure(.., substs1), TyKind::Closure(.., substs2)) => { 324 | (TyKind::Closure(.., substs1), TyKind::Closure(.., substs2)) => {
318 self.unify_substs(substs1, substs2, depth + 1) 325 self.unify_substs(substs1, substs2, depth + 1)
319 } 326 }
320 (TyKind::Ref(_, ty1), TyKind::Ref(_, ty2)) 327 (TyKind::Array(ty1, c1), TyKind::Array(ty2, c2)) if c1 == c2 => {
328 self.unify_inner(ty1, ty2, depth + 1)
329 }
330 (TyKind::Ref(_, _, ty1), TyKind::Ref(_, _, ty2))
321 | (TyKind::Raw(_, ty1), TyKind::Raw(_, ty2)) 331 | (TyKind::Raw(_, ty1), TyKind::Raw(_, ty2))
322 | (TyKind::Array(ty1), TyKind::Array(ty2))
323 | (TyKind::Slice(ty1), TyKind::Slice(ty2)) => self.unify_inner(ty1, ty2, depth + 1), 332 | (TyKind::Slice(ty1), TyKind::Slice(ty2)) => self.unify_inner(ty1, ty2, depth + 1),
324 _ => true, /* we checked equals_ctor already */ 333 _ => true, /* we checked equals_ctor already */
325 } 334 }
@@ -367,8 +376,12 @@ impl InferenceTable {
367 == self.type_variable_table.is_diverging(*tv2) => 376 == self.type_variable_table.is_diverging(*tv2) =>
368 { 377 {
369 // both type vars are unknown since we tried to resolve them 378 // both type vars are unknown since we tried to resolve them
370 if !self.var_unification_table.unioned(tv1.to_inner(), tv2.to_inner()) { 379 if !self
371 self.var_unification_table.union(tv1.to_inner(), tv2.to_inner()); 380 .var_unification_table
381 .unioned(from_inference_var(*tv1), from_inference_var(*tv2))
382 {
383 self.var_unification_table
384 .union(from_inference_var(*tv1), from_inference_var(*tv2));
372 self.revision += 1; 385 self.revision += 1;
373 } 386 }
374 true 387 true
@@ -405,7 +418,7 @@ impl InferenceTable {
405 ) => { 418 ) => {
406 // the type var is unknown since we tried to resolve it 419 // the type var is unknown since we tried to resolve it
407 self.var_unification_table.union_value( 420 self.var_unification_table.union_value(
408 tv.to_inner(), 421 from_inference_var(*tv),
409 TypeVarValue::Known(other.clone().intern(&Interner)), 422 TypeVarValue::Known(other.clone().intern(&Interner)),
410 ); 423 );
411 self.revision += 1; 424 self.revision += 1;
@@ -460,7 +473,7 @@ impl InferenceTable {
460 } 473 }
461 match ty.kind(&Interner) { 474 match ty.kind(&Interner) {
462 TyKind::InferenceVar(tv, _) => { 475 TyKind::InferenceVar(tv, _) => {
463 let inner = tv.to_inner(); 476 let inner = from_inference_var(*tv);
464 match self.var_unification_table.inlined_probe_value(inner).known() { 477 match self.var_unification_table.inlined_probe_value(inner).known() {
465 Some(known_ty) => { 478 Some(known_ty) => {
466 // The known_ty can't be a type var itself 479 // The known_ty can't be a type var itself
@@ -481,55 +494,63 @@ impl InferenceTable {
481 /// be resolved as far as possible, i.e. contain no type variables with 494 /// be resolved as far as possible, i.e. contain no type variables with
482 /// known type. 495 /// known type.
483 fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { 496 fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
484 ty.fold(&mut |ty| match ty.kind(&Interner) { 497 fold_tys(
485 &TyKind::InferenceVar(tv, kind) => { 498 ty,
486 let inner = tv.to_inner(); 499 |ty, _| match ty.kind(&Interner) {
487 if tv_stack.contains(&inner) { 500 &TyKind::InferenceVar(tv, kind) => {
488 cov_mark::hit!(type_var_cycles_resolve_as_possible); 501 let inner = from_inference_var(tv);
489 // recursive type 502 if tv_stack.contains(&inner) {
490 return self.type_variable_table.fallback_value(tv, kind); 503 cov_mark::hit!(type_var_cycles_resolve_as_possible);
491 } 504 // recursive type
492 if let Some(known_ty) = 505 return self.type_variable_table.fallback_value(tv, kind);
493 self.var_unification_table.inlined_probe_value(inner).known() 506 }
494 { 507 if let Some(known_ty) =
495 // known_ty may contain other variables that are known by now 508 self.var_unification_table.inlined_probe_value(inner).known()
496 tv_stack.push(inner); 509 {
497 let result = self.resolve_ty_as_possible_inner(tv_stack, known_ty.clone()); 510 // known_ty may contain other variables that are known by now
498 tv_stack.pop(); 511 tv_stack.push(inner);
499 result 512 let result = self.resolve_ty_as_possible_inner(tv_stack, known_ty.clone());
500 } else { 513 tv_stack.pop();
501 ty 514 result
515 } else {
516 ty
517 }
502 } 518 }
503 } 519 _ => ty,
504 _ => ty, 520 },
505 }) 521 DebruijnIndex::INNERMOST,
522 )
506 } 523 }
507 524
508 /// Resolves the type completely; type variables without known type are 525 /// Resolves the type completely; type variables without known type are
509 /// replaced by TyKind::Unknown. 526 /// replaced by TyKind::Unknown.
510 fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { 527 fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
511 ty.fold(&mut |ty| match ty.kind(&Interner) { 528 fold_tys(
512 &TyKind::InferenceVar(tv, kind) => { 529 ty,
513 let inner = tv.to_inner(); 530 |ty, _| match ty.kind(&Interner) {
514 if tv_stack.contains(&inner) { 531 &TyKind::InferenceVar(tv, kind) => {
515 cov_mark::hit!(type_var_cycles_resolve_completely); 532 let inner = from_inference_var(tv);
516 // recursive type 533 if tv_stack.contains(&inner) {
517 return self.type_variable_table.fallback_value(tv, kind); 534 cov_mark::hit!(type_var_cycles_resolve_completely);
518 } 535 // recursive type
519 if let Some(known_ty) = 536 return self.type_variable_table.fallback_value(tv, kind);
520 self.var_unification_table.inlined_probe_value(inner).known() 537 }
521 { 538 if let Some(known_ty) =
522 // known_ty may contain other variables that are known by now 539 self.var_unification_table.inlined_probe_value(inner).known()
523 tv_stack.push(inner); 540 {
524 let result = self.resolve_ty_completely_inner(tv_stack, known_ty.clone()); 541 // known_ty may contain other variables that are known by now
525 tv_stack.pop(); 542 tv_stack.push(inner);
526 result 543 let result = self.resolve_ty_completely_inner(tv_stack, known_ty.clone());
527 } else { 544 tv_stack.pop();
528 self.type_variable_table.fallback_value(tv, kind) 545 result
546 } else {
547 self.type_variable_table.fallback_value(tv, kind)
548 }
529 } 549 }
530 } 550 _ => ty,
531 _ => ty, 551 },
532 }) 552 DebruijnIndex::INNERMOST,
553 )
533 } 554 }
534} 555}
535 556
@@ -553,6 +574,14 @@ impl UnifyKey for TypeVarId {
553 } 574 }
554} 575}
555 576
577fn from_inference_var(var: InferenceVar) -> TypeVarId {
578 TypeVarId(var.index())
579}
580
581fn to_inference_var(TypeVarId(index): TypeVarId) -> InferenceVar {
582 index.into()
583}
584
556/// The value of a type variable: either we already know the type, or we don't 585/// The value of a type variable: either we already know the type, or we don't
557/// know it yet. 586/// know it yet.
558#[derive(Clone, PartialEq, Eq, Debug)] 587#[derive(Clone, PartialEq, Eq, Debug)]
diff --git a/crates/hir_ty/src/traits/chalk/interner.rs b/crates/hir_ty/src/interner.rs
index bd9395b7e..a1656115d 100644
--- a/crates/hir_ty/src/traits/chalk/interner.rs
+++ b/crates/hir_ty/src/interner.rs
@@ -1,61 +1,83 @@
1//! Implementation of the Chalk `Interner` trait, which allows customizing the 1//! Implementation of the Chalk `Interner` trait, which allows customizing the
2//! representation of the various objects Chalk deals with (types, goals etc.). 2//! representation of the various objects Chalk deals with (types, goals etc.).
3 3
4use super::tls; 4use crate::{chalk_db, tls, GenericArg};
5use base_db::salsa::InternId; 5use base_db::salsa::InternId;
6use chalk_ir::{GenericArg, Goal, GoalData}; 6use chalk_ir::{Goal, GoalData};
7use hir_def::TypeAliasId; 7use hir_def::{
8 intern::{impl_internable, InternStorage, Internable, Interned},
9 TypeAliasId,
10};
8use smallvec::SmallVec; 11use smallvec::SmallVec;
9use std::{fmt, sync::Arc}; 12use std::{fmt, sync::Arc};
10 13
11#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] 14#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
12pub struct Interner; 15pub struct Interner;
13 16
14pub(crate) type AssocTypeId = chalk_ir::AssocTypeId<Interner>; 17#[derive(PartialEq, Eq, Hash, Debug)]
15pub(crate) type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>; 18pub struct InternedWrapper<T>(T);
16pub(crate) type TraitId = chalk_ir::TraitId<Interner>; 19
17pub(crate) type TraitDatum = chalk_solve::rust_ir::TraitDatum<Interner>; 20impl<T> std::ops::Deref for InternedWrapper<T> {
18pub(crate) type AdtId = chalk_ir::AdtId<Interner>; 21 type Target = T;
19pub(crate) type StructDatum = chalk_solve::rust_ir::AdtDatum<Interner>; 22
20pub(crate) type ImplId = chalk_ir::ImplId<Interner>; 23 fn deref(&self) -> &Self::Target {
21pub(crate) type ImplDatum = chalk_solve::rust_ir::ImplDatum<Interner>; 24 &self.0
22pub(crate) type AssociatedTyValueId = chalk_solve::rust_ir::AssociatedTyValueId<Interner>; 25 }
23pub(crate) type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue<Interner>; 26}
24pub(crate) type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>; 27
25pub(crate) type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; 28impl_internable!(
26pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum<Interner>; 29 InternedWrapper<Vec<chalk_ir::VariableKind<Interner>>>,
27pub(crate) type Variances = chalk_ir::Variances<Interner>; 30 InternedWrapper<SmallVec<[GenericArg; 2]>>,
31 InternedWrapper<chalk_ir::TyData<Interner>>,
32 InternedWrapper<chalk_ir::LifetimeData<Interner>>,
33 InternedWrapper<chalk_ir::ConstData<Interner>>,
34 InternedWrapper<Vec<chalk_ir::CanonicalVarKind<Interner>>>,
35 InternedWrapper<Vec<chalk_ir::ProgramClause<Interner>>>,
36 InternedWrapper<Vec<chalk_ir::QuantifiedWhereClause<Interner>>>,
37 InternedWrapper<Vec<chalk_ir::Variance>>,
38);
28 39
29impl chalk_ir::interner::Interner for Interner { 40impl chalk_ir::interner::Interner for Interner {
30 type InternedType = Arc<chalk_ir::TyData<Self>>; 41 type InternedType = Interned<InternedWrapper<chalk_ir::TyData<Interner>>>;
31 type InternedLifetime = chalk_ir::LifetimeData<Self>; 42 type InternedLifetime = Interned<InternedWrapper<chalk_ir::LifetimeData<Self>>>;
32 type InternedConst = Arc<chalk_ir::ConstData<Self>>; 43 type InternedConst = Interned<InternedWrapper<chalk_ir::ConstData<Self>>>;
33 type InternedConcreteConst = (); 44 type InternedConcreteConst = ();
34 type InternedGenericArg = chalk_ir::GenericArgData<Self>; 45 type InternedGenericArg = chalk_ir::GenericArgData<Self>;
35 type InternedGoal = Arc<GoalData<Self>>; 46 type InternedGoal = Arc<GoalData<Self>>;
36 type InternedGoals = Vec<Goal<Self>>; 47 type InternedGoals = Vec<Goal<Self>>;
37 type InternedSubstitution = SmallVec<[GenericArg<Self>; 2]>; 48 type InternedSubstitution = Interned<InternedWrapper<SmallVec<[GenericArg; 2]>>>;
38 type InternedProgramClause = Arc<chalk_ir::ProgramClauseData<Self>>; 49 type InternedProgramClause = chalk_ir::ProgramClauseData<Self>;
39 type InternedProgramClauses = Arc<[chalk_ir::ProgramClause<Self>]>; 50 type InternedProgramClauses = Interned<InternedWrapper<Vec<chalk_ir::ProgramClause<Self>>>>;
40 type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>; 51 type InternedQuantifiedWhereClauses =
41 type InternedVariableKinds = Vec<chalk_ir::VariableKind<Self>>; 52 Interned<InternedWrapper<Vec<chalk_ir::QuantifiedWhereClause<Self>>>>;
42 type InternedCanonicalVarKinds = Vec<chalk_ir::CanonicalVarKind<Self>>; 53 type InternedVariableKinds = Interned<InternedWrapper<Vec<chalk_ir::VariableKind<Interner>>>>;
54 type InternedCanonicalVarKinds =
55 Interned<InternedWrapper<Vec<chalk_ir::CanonicalVarKind<Self>>>>;
43 type InternedConstraints = Vec<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>>; 56 type InternedConstraints = Vec<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>>;
44 type InternedVariances = Arc<[chalk_ir::Variance]>; 57 type InternedVariances = Interned<InternedWrapper<Vec<chalk_ir::Variance>>>;
45 type DefId = InternId; 58 type DefId = InternId;
46 type InternedAdtId = hir_def::AdtId; 59 type InternedAdtId = hir_def::AdtId;
47 type Identifier = TypeAliasId; 60 type Identifier = TypeAliasId;
48 type FnAbi = (); 61 type FnAbi = ();
49 62
50 fn debug_adt_id(type_kind_id: AdtId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { 63 fn debug_adt_id(
64 type_kind_id: chalk_db::AdtId,
65 fmt: &mut fmt::Formatter<'_>,
66 ) -> Option<fmt::Result> {
51 tls::with_current_program(|prog| Some(prog?.debug_struct_id(type_kind_id, fmt))) 67 tls::with_current_program(|prog| Some(prog?.debug_struct_id(type_kind_id, fmt)))
52 } 68 }
53 69
54 fn debug_trait_id(type_kind_id: TraitId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { 70 fn debug_trait_id(
71 type_kind_id: chalk_db::TraitId,
72 fmt: &mut fmt::Formatter<'_>,
73 ) -> Option<fmt::Result> {
55 tls::with_current_program(|prog| Some(prog?.debug_trait_id(type_kind_id, fmt))) 74 tls::with_current_program(|prog| Some(prog?.debug_trait_id(type_kind_id, fmt)))
56 } 75 }
57 76
58 fn debug_assoc_type_id(id: AssocTypeId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { 77 fn debug_assoc_type_id(
78 id: chalk_db::AssocTypeId,
79 fmt: &mut fmt::Formatter<'_>,
80 ) -> Option<fmt::Result> {
59 tls::with_current_program(|prog| Some(prog?.debug_assoc_type_id(id, fmt))) 81 tls::with_current_program(|prog| Some(prog?.debug_assoc_type_id(id, fmt)))
60 } 82 }
61 83
@@ -99,7 +121,7 @@ impl chalk_ir::interner::Interner for Interner {
99 } 121 }
100 122
101 fn debug_generic_arg( 123 fn debug_generic_arg(
102 parameter: &GenericArg<Interner>, 124 parameter: &GenericArg,
103 fmt: &mut fmt::Formatter<'_>, 125 fmt: &mut fmt::Formatter<'_>,
104 ) -> Option<fmt::Result> { 126 ) -> Option<fmt::Result> {
105 tls::with_current_program(|prog| Some(prog?.debug_generic_arg(parameter, fmt))) 127 tls::with_current_program(|prog| Some(prog?.debug_generic_arg(parameter, fmt)))
@@ -194,30 +216,30 @@ impl chalk_ir::interner::Interner for Interner {
194 216
195 fn intern_ty(&self, kind: chalk_ir::TyKind<Self>) -> Self::InternedType { 217 fn intern_ty(&self, kind: chalk_ir::TyKind<Self>) -> Self::InternedType {
196 let flags = kind.compute_flags(self); 218 let flags = kind.compute_flags(self);
197 Arc::new(chalk_ir::TyData { kind, flags }) 219 Interned::new(InternedWrapper(chalk_ir::TyData { kind, flags }))
198 } 220 }
199 221
200 fn ty_data<'a>(&self, ty: &'a Self::InternedType) -> &'a chalk_ir::TyData<Self> { 222 fn ty_data<'a>(&self, ty: &'a Self::InternedType) -> &'a chalk_ir::TyData<Self> {
201 ty 223 &ty.0
202 } 224 }
203 225
204 fn intern_lifetime(&self, lifetime: chalk_ir::LifetimeData<Self>) -> Self::InternedLifetime { 226 fn intern_lifetime(&self, lifetime: chalk_ir::LifetimeData<Self>) -> Self::InternedLifetime {
205 lifetime 227 Interned::new(InternedWrapper(lifetime))
206 } 228 }
207 229
208 fn lifetime_data<'a>( 230 fn lifetime_data<'a>(
209 &self, 231 &self,
210 lifetime: &'a Self::InternedLifetime, 232 lifetime: &'a Self::InternedLifetime,
211 ) -> &'a chalk_ir::LifetimeData<Self> { 233 ) -> &'a chalk_ir::LifetimeData<Self> {
212 lifetime 234 &lifetime.0
213 } 235 }
214 236
215 fn intern_const(&self, constant: chalk_ir::ConstData<Self>) -> Self::InternedConst { 237 fn intern_const(&self, constant: chalk_ir::ConstData<Self>) -> Self::InternedConst {
216 Arc::new(constant) 238 Interned::new(InternedWrapper(constant))
217 } 239 }
218 240
219 fn const_data<'a>(&self, constant: &'a Self::InternedConst) -> &'a chalk_ir::ConstData<Self> { 241 fn const_data<'a>(&self, constant: &'a Self::InternedConst) -> &'a chalk_ir::ConstData<Self> {
220 constant 242 &constant.0
221 } 243 }
222 244
223 fn const_eq( 245 fn const_eq(
@@ -264,23 +286,23 @@ impl chalk_ir::interner::Interner for Interner {
264 286
265 fn intern_substitution<E>( 287 fn intern_substitution<E>(
266 &self, 288 &self,
267 data: impl IntoIterator<Item = Result<GenericArg<Self>, E>>, 289 data: impl IntoIterator<Item = Result<GenericArg, E>>,
268 ) -> Result<Self::InternedSubstitution, E> { 290 ) -> Result<Self::InternedSubstitution, E> {
269 data.into_iter().collect() 291 Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
270 } 292 }
271 293
272 fn substitution_data<'a>( 294 fn substitution_data<'a>(
273 &self, 295 &self,
274 substitution: &'a Self::InternedSubstitution, 296 substitution: &'a Self::InternedSubstitution,
275 ) -> &'a [GenericArg<Self>] { 297 ) -> &'a [GenericArg] {
276 substitution 298 &substitution.as_ref().0
277 } 299 }
278 300
279 fn intern_program_clause( 301 fn intern_program_clause(
280 &self, 302 &self,
281 data: chalk_ir::ProgramClauseData<Self>, 303 data: chalk_ir::ProgramClauseData<Self>,
282 ) -> Self::InternedProgramClause { 304 ) -> Self::InternedProgramClause {
283 Arc::new(data) 305 data
284 } 306 }
285 307
286 fn program_clause_data<'a>( 308 fn program_clause_data<'a>(
@@ -294,7 +316,7 @@ impl chalk_ir::interner::Interner for Interner {
294 &self, 316 &self,
295 data: impl IntoIterator<Item = Result<chalk_ir::ProgramClause<Self>, E>>, 317 data: impl IntoIterator<Item = Result<chalk_ir::ProgramClause<Self>, E>>,
296 ) -> Result<Self::InternedProgramClauses, E> { 318 ) -> Result<Self::InternedProgramClauses, E> {
297 data.into_iter().collect() 319 Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
298 } 320 }
299 321
300 fn program_clauses_data<'a>( 322 fn program_clauses_data<'a>(
@@ -308,7 +330,7 @@ impl chalk_ir::interner::Interner for Interner {
308 &self, 330 &self,
309 data: impl IntoIterator<Item = Result<chalk_ir::QuantifiedWhereClause<Self>, E>>, 331 data: impl IntoIterator<Item = Result<chalk_ir::QuantifiedWhereClause<Self>, E>>,
310 ) -> Result<Self::InternedQuantifiedWhereClauses, E> { 332 ) -> Result<Self::InternedQuantifiedWhereClauses, E> {
311 data.into_iter().collect() 333 Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
312 } 334 }
313 335
314 fn quantified_where_clauses_data<'a>( 336 fn quantified_where_clauses_data<'a>(
@@ -322,21 +344,21 @@ impl chalk_ir::interner::Interner for Interner {
322 &self, 344 &self,
323 data: impl IntoIterator<Item = Result<chalk_ir::VariableKind<Self>, E>>, 345 data: impl IntoIterator<Item = Result<chalk_ir::VariableKind<Self>, E>>,
324 ) -> Result<Self::InternedVariableKinds, E> { 346 ) -> Result<Self::InternedVariableKinds, E> {
325 data.into_iter().collect() 347 Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
326 } 348 }
327 349
328 fn variable_kinds_data<'a>( 350 fn variable_kinds_data<'a>(
329 &self, 351 &self,
330 parameter_kinds: &'a Self::InternedVariableKinds, 352 parameter_kinds: &'a Self::InternedVariableKinds,
331 ) -> &'a [chalk_ir::VariableKind<Self>] { 353 ) -> &'a [chalk_ir::VariableKind<Self>] {
332 &parameter_kinds 354 &parameter_kinds.as_ref().0
333 } 355 }
334 356
335 fn intern_canonical_var_kinds<E>( 357 fn intern_canonical_var_kinds<E>(
336 &self, 358 &self,
337 data: impl IntoIterator<Item = Result<chalk_ir::CanonicalVarKind<Self>, E>>, 359 data: impl IntoIterator<Item = Result<chalk_ir::CanonicalVarKind<Self>, E>>,
338 ) -> Result<Self::InternedCanonicalVarKinds, E> { 360 ) -> Result<Self::InternedCanonicalVarKinds, E> {
339 data.into_iter().collect() 361 Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
340 } 362 }
341 363
342 fn canonical_var_kinds_data<'a>( 364 fn canonical_var_kinds_data<'a>(
@@ -376,7 +398,7 @@ impl chalk_ir::interner::Interner for Interner {
376 &self, 398 &self,
377 data: impl IntoIterator<Item = Result<chalk_ir::Variance, E>>, 399 data: impl IntoIterator<Item = Result<chalk_ir::Variance, E>>,
378 ) -> Result<Self::InternedVariances, E> { 400 ) -> Result<Self::InternedVariances, E> {
379 data.into_iter().collect() 401 Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
380 } 402 }
381 403
382 fn variances_data<'a>( 404 fn variances_data<'a>(
@@ -390,3 +412,12 @@ impl chalk_ir::interner::Interner for Interner {
390impl chalk_ir::interner::HasInterner for Interner { 412impl chalk_ir::interner::HasInterner for Interner {
391 type Interner = Self; 413 type Interner = Self;
392} 414}
415
416#[macro_export]
417macro_rules! has_interner {
418 ($t:ty) => {
419 impl HasInterner for $t {
420 type Interner = crate::Interner;
421 }
422 };
423}
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index daf379ef8..113234fa4 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -1,27 +1,29 @@
1//! The type system. We currently use this to infer types for completion, hover 1//! The type system. We currently use this to infer types for completion, hover
2//! information and various assists. 2//! information and various assists.
3
3#[allow(unused)] 4#[allow(unused)]
4macro_rules! eprintln { 5macro_rules! eprintln {
5 ($($tt:tt)*) => { stdx::eprintln!($($tt)*) }; 6 ($($tt:tt)*) => { stdx::eprintln!($($tt)*) };
6} 7}
7 8
8mod autoderef; 9mod autoderef;
9pub mod primitive;
10pub mod traits;
11pub mod method_resolution;
12mod op;
13mod lower;
14pub(crate) mod infer;
15pub(crate) mod utils;
16mod chalk_cast;
17mod chalk_ext;
18mod builder; 10mod builder;
11mod chalk_db;
12mod chalk_ext;
13mod infer;
14mod interner;
15mod lower;
16mod mapping;
17mod op;
18mod tls;
19mod utils;
19mod walk; 20mod walk;
20mod types;
21
22pub mod display;
23pub mod db; 21pub mod db;
24pub mod diagnostics; 22pub mod diagnostics;
23pub mod display;
24pub mod method_resolution;
25pub mod primitive;
26pub mod traits;
25 27
26#[cfg(test)] 28#[cfg(test)]
27mod tests; 29mod tests;
@@ -30,35 +32,36 @@ mod test_db;
30 32
31use std::sync::Arc; 33use std::sync::Arc;
32 34
33use itertools::Itertools; 35use chalk_ir::{
34use smallvec::SmallVec; 36 fold::{Fold, Shift},
35 37 interner::HasInterner,
36use base_db::salsa; 38 UintTy,
37use hir_def::{
38 expr::ExprId, type_ref::Rawness, AssocContainerId, FunctionId, GenericDefId, HasModule, Lookup,
39 TraitId, TypeAliasId, TypeParamId,
40}; 39};
40use hir_def::{expr::ExprId, type_ref::Rawness, TypeParamId};
41 41
42use crate::{db::HirDatabase, display::HirDisplay, utils::generics}; 42use crate::{db::HirDatabase, display::HirDisplay, utils::generics};
43 43
44pub use autoderef::autoderef; 44pub use autoderef::autoderef;
45pub use builder::TyBuilder; 45pub use builder::TyBuilder;
46pub use chalk_ext::TyExt; 46pub use chalk_ext::*;
47pub use infer::{could_unify, InferenceResult, InferenceVar}; 47pub use infer::{could_unify, InferenceResult};
48pub use interner::Interner;
48pub use lower::{ 49pub use lower::{
49 associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, 50 associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode,
50 TyDefId, TyLoweringContext, ValueTyDefId, 51 TyDefId, TyLoweringContext, ValueTyDefId,
51}; 52};
53pub use mapping::{
54 const_from_placeholder_idx, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
55 from_placeholder_idx, lt_from_placeholder_idx, to_assoc_type_id, to_chalk_trait_id,
56 to_foreign_def_id, to_placeholder_idx,
57};
52pub use traits::TraitEnvironment; 58pub use traits::TraitEnvironment;
53pub use types::*;
54pub use walk::TypeWalk; 59pub use walk::TypeWalk;
55 60
56pub use chalk_ir::{ 61pub use chalk_ir::{
57 cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind, 62 cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind,
58}; 63};
59 64
60pub use crate::traits::chalk::Interner;
61
62pub type ForeignDefId = chalk_ir::ForeignDefId<Interner>; 65pub type ForeignDefId = chalk_ir::ForeignDefId<Interner>;
63pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>; 66pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>;
64pub type FnDefId = chalk_ir::FnDefId<Interner>; 67pub type FnDefId = chalk_ir::FnDefId<Interner>;
@@ -69,49 +72,53 @@ pub type PlaceholderIndex = chalk_ir::PlaceholderIndex;
69pub type VariableKind = chalk_ir::VariableKind<Interner>; 72pub type VariableKind = chalk_ir::VariableKind<Interner>;
70pub type VariableKinds = chalk_ir::VariableKinds<Interner>; 73pub type VariableKinds = chalk_ir::VariableKinds<Interner>;
71pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>; 74pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>;
75pub type Binders<T> = chalk_ir::Binders<T>;
76pub type Substitution = chalk_ir::Substitution<Interner>;
77pub type GenericArg = chalk_ir::GenericArg<Interner>;
78pub type GenericArgData = chalk_ir::GenericArgData<Interner>;
79
80pub type Ty = chalk_ir::Ty<Interner>;
81pub type TyKind = chalk_ir::TyKind<Interner>;
82pub type DynTy = chalk_ir::DynTy<Interner>;
83pub type FnPointer = chalk_ir::FnPointer<Interner>;
84// pub type FnSubst = chalk_ir::FnSubst<Interner>;
85pub use chalk_ir::FnSubst;
86pub type ProjectionTy = chalk_ir::ProjectionTy<Interner>;
87pub type AliasTy = chalk_ir::AliasTy<Interner>;
88pub type OpaqueTy = chalk_ir::OpaqueTy<Interner>;
89pub type InferenceVar = chalk_ir::InferenceVar;
90
91pub type Lifetime = chalk_ir::Lifetime<Interner>;
92pub type LifetimeData = chalk_ir::LifetimeData<Interner>;
93pub type LifetimeOutlives = chalk_ir::LifetimeOutlives<Interner>;
94
95pub type Const = chalk_ir::Const<Interner>;
96pub type ConstData = chalk_ir::ConstData<Interner>;
97pub type ConstValue = chalk_ir::ConstValue<Interner>;
98pub type ConcreteConst = chalk_ir::ConcreteConst<Interner>;
72 99
73pub type ChalkTraitId = chalk_ir::TraitId<Interner>; 100pub type ChalkTraitId = chalk_ir::TraitId<Interner>;
74 101pub type TraitRef = chalk_ir::TraitRef<Interner>;
75impl ProjectionTy { 102pub type QuantifiedWhereClause = Binders<WhereClause>;
76 pub fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef { 103pub type QuantifiedWhereClauses = chalk_ir::QuantifiedWhereClauses<Interner>;
77 TraitRef { 104pub type Canonical<T> = chalk_ir::Canonical<T>;
78 trait_id: to_chalk_trait_id(self.trait_(db)),
79 substitution: self.substitution.clone(),
80 }
81 }
82
83 pub fn self_type_parameter(&self, interner: &Interner) -> &Ty {
84 &self.substitution.interned()[0].assert_ty_ref(interner)
85 }
86
87 fn trait_(&self, db: &dyn HirDatabase) -> TraitId {
88 match from_assoc_type_id(self.associated_ty_id).lookup(db.upcast()).container {
89 AssocContainerId::TraitId(it) => it,
90 _ => panic!("projection ty without parent trait"),
91 }
92 }
93}
94 105
95pub type FnSig = chalk_ir::FnSig<Interner>; 106pub type FnSig = chalk_ir::FnSig<Interner>;
96 107
97impl Substitution { 108pub type InEnvironment<T> = chalk_ir::InEnvironment<T>;
98 pub fn single(ty: Ty) -> Substitution { 109pub type DomainGoal = chalk_ir::DomainGoal<Interner>;
99 Substitution::intern({ 110pub type AliasEq = chalk_ir::AliasEq<Interner>;
100 let mut v = SmallVec::new(); 111pub type Solution = chalk_solve::Solution<Interner>;
101 v.push(ty.cast(&Interner)); 112pub type ConstrainedSubst = chalk_ir::ConstrainedSubst<Interner>;
102 v 113pub type Guidance = chalk_solve::Guidance<Interner>;
103 }) 114pub type WhereClause = chalk_ir::WhereClause<Interner>;
104 } 115
105 116// FIXME: get rid of this
106 pub fn prefix(&self, n: usize) -> Substitution { 117pub fn subst_prefix(s: &Substitution, n: usize) -> Substitution {
107 Substitution::intern(self.interned()[..std::cmp::min(self.len(&Interner), n)].into()) 118 Substitution::from_iter(
108 } 119 &Interner,
109 120 s.as_slice(&Interner)[..std::cmp::min(s.len(&Interner), n)].iter().cloned(),
110 pub fn suffix(&self, n: usize) -> Substitution { 121 )
111 Substitution::intern(
112 self.interned()[self.len(&Interner) - std::cmp::min(self.len(&Interner), n)..].into(),
113 )
114 }
115} 122}
116 123
117/// Return an index of a parameter in the generic type parameter list by it's id. 124/// Return an index of a parameter in the generic type parameter list by it's id.
@@ -119,25 +126,17 @@ pub fn param_idx(db: &dyn HirDatabase, id: TypeParamId) -> Option<usize> {
119 generics(db.upcast(), id.parent).param_idx(id) 126 generics(db.upcast(), id.parent).param_idx(id)
120} 127}
121 128
122impl<T> Binders<T> { 129pub(crate) fn wrap_empty_binders<T>(value: T) -> Binders<T>
123 pub fn wrap_empty(value: T) -> Self 130where
124 where 131 T: Fold<Interner, Result = T> + HasInterner<Interner = Interner>,
125 T: TypeWalk, 132{
126 { 133 Binders::empty(&Interner, value.shifted_in_from(&Interner, DebruijnIndex::ONE))
127 Binders::empty(&Interner, value.shifted_in_from(DebruijnIndex::ONE))
128 }
129}
130
131impl<T: TypeWalk> Binders<T> {
132 /// Substitutes all variables.
133 pub fn substitute(self, interner: &Interner, subst: &Substitution) -> T {
134 let (value, binders) = self.into_value_and_skipped_binders();
135 assert_eq!(subst.len(interner), binders.len(interner));
136 value.subst_bound_vars(subst)
137 }
138} 134}
139 135
140pub fn make_only_type_binders<T>(num_vars: usize, value: T) -> Binders<T> { 136pub(crate) fn make_only_type_binders<T: HasInterner<Interner = Interner>>(
137 num_vars: usize,
138 value: T,
139) -> Binders<T> {
141 Binders::new( 140 Binders::new(
142 VariableKinds::from_iter( 141 VariableKinds::from_iter(
143 &Interner, 142 &Interner,
@@ -148,42 +147,18 @@ pub fn make_only_type_binders<T>(num_vars: usize, value: T) -> Binders<T> {
148 ) 147 )
149} 148}
150 149
151impl TraitRef { 150// FIXME: get rid of this
152 pub fn self_type_parameter(&self, interner: &Interner) -> &Ty { 151pub fn make_canonical<T: HasInterner<Interner = Interner>>(
153 &self.substitution.at(interner, 0).assert_ty_ref(interner) 152 value: T,
154 } 153 kinds: impl IntoIterator<Item = TyVariableKind>,
155 154) -> Canonical<T> {
156 pub fn hir_trait_id(&self) -> TraitId { 155 let kinds = kinds.into_iter().map(|tk| {
157 from_chalk_trait_id(self.trait_id) 156 chalk_ir::CanonicalVarKind::new(
158 } 157 chalk_ir::VariableKind::Ty(tk),
159} 158 chalk_ir::UniverseIndex::ROOT,
160 159 )
161impl WhereClause { 160 });
162 pub fn is_implemented(&self) -> bool { 161 Canonical { value, binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds) }
163 matches!(self, WhereClause::Implemented(_))
164 }
165
166 pub fn trait_ref(&self, db: &dyn HirDatabase) -> Option<TraitRef> {
167 match self {
168 WhereClause::Implemented(tr) => Some(tr.clone()),
169 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(proj), .. }) => {
170 Some(proj.trait_ref(db))
171 }
172 WhereClause::AliasEq(_) => None,
173 }
174 }
175}
176
177impl<T> Canonical<T> {
178 pub fn new(value: T, kinds: impl IntoIterator<Item = TyVariableKind>) -> Self {
179 let kinds = kinds.into_iter().map(|tk| {
180 chalk_ir::CanonicalVarKind::new(
181 chalk_ir::VariableKind::Ty(tk),
182 chalk_ir::UniverseIndex::ROOT,
183 )
184 });
185 Self { value, binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds) }
186 }
187} 162}
188 163
189/// A function signature as seen by type inference: Several parameter types and 164/// A function signature as seen by type inference: Several parameter types and
@@ -194,6 +169,8 @@ pub struct CallableSig {
194 is_varargs: bool, 169 is_varargs: bool,
195} 170}
196 171
172has_interner!(CallableSig);
173
197/// A polymorphic function signature. 174/// A polymorphic function signature.
198pub type PolyFnSig = Binders<CallableSig>; 175pub type PolyFnSig = Binders<CallableSig>;
199 176
@@ -207,11 +184,12 @@ impl CallableSig {
207 CallableSig { 184 CallableSig {
208 // FIXME: what to do about lifetime params? -> return PolyFnSig 185 // FIXME: what to do about lifetime params? -> return PolyFnSig
209 params_and_return: fn_ptr 186 params_and_return: fn_ptr
210 .substs 187 .substitution
211 .clone() 188 .clone()
212 .shifted_out_to(DebruijnIndex::ONE) 189 .shifted_out_to(&Interner, DebruijnIndex::ONE)
213 .expect("unexpected lifetime vars in fn ptr") 190 .expect("unexpected lifetime vars in fn ptr")
214 .interned() 191 .0
192 .as_slice(&Interner)
215 .iter() 193 .iter()
216 .map(|arg| arg.assert_ty_ref(&Interner).clone()) 194 .map(|arg| arg.assert_ty_ref(&Interner).clone())
217 .collect(), 195 .collect(),
@@ -228,275 +206,20 @@ impl CallableSig {
228 } 206 }
229} 207}
230 208
231impl Ty { 209impl Fold<Interner> for CallableSig {
232 pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { 210 type Result = CallableSig;
233 match self.kind(&Interner) {
234 TyKind::Ref(mutability, ty) => Some((ty, *mutability)),
235 _ => None,
236 }
237 }
238
239 pub fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> {
240 match self.kind(&Interner) {
241 TyKind::Ref(mutability, ty) => Some((ty, Rawness::Ref, *mutability)),
242 TyKind::Raw(mutability, ty) => Some((ty, Rawness::RawPtr, *mutability)),
243 _ => None,
244 }
245 }
246
247 pub fn strip_references(&self) -> &Ty {
248 let mut t: &Ty = self;
249
250 while let TyKind::Ref(_mutability, ty) = t.kind(&Interner) {
251 t = ty;
252 }
253 211
254 t 212 fn fold_with<'i>(
255 } 213 self,
256 214 folder: &mut dyn chalk_ir::fold::Folder<'i, Interner>,
257 pub fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)> { 215 outer_binder: DebruijnIndex,
258 match self.kind(&Interner) { 216 ) -> chalk_ir::Fallible<Self::Result>
259 TyKind::Adt(AdtId(adt), parameters) => Some((*adt, parameters)), 217 where
260 _ => None, 218 Interner: 'i,
261 } 219 {
262 } 220 let vec = self.params_and_return.to_vec();
263 221 let folded = vec.fold_with(folder, outer_binder)?;
264 pub fn as_tuple(&self) -> Option<&Substitution> { 222 Ok(CallableSig { params_and_return: folded.into(), is_varargs: self.is_varargs })
265 match self.kind(&Interner) {
266 TyKind::Tuple(_, substs) => Some(substs),
267 _ => None,
268 }
269 }
270
271 pub fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId> {
272 match *self.kind(&Interner) {
273 TyKind::Adt(AdtId(adt), ..) => Some(adt.into()),
274 TyKind::FnDef(callable, ..) => {
275 Some(db.lookup_intern_callable_def(callable.into()).into())
276 }
277 TyKind::AssociatedType(type_alias, ..) => Some(from_assoc_type_id(type_alias).into()),
278 TyKind::Foreign(type_alias, ..) => Some(from_foreign_def_id(type_alias).into()),
279 _ => None,
280 }
281 }
282
283 pub fn is_never(&self) -> bool {
284 matches!(self.kind(&Interner), TyKind::Never)
285 }
286
287 pub fn is_unknown(&self) -> bool {
288 matches!(self.kind(&Interner), TyKind::Error)
289 }
290
291 pub fn equals_ctor(&self, other: &Ty) -> bool {
292 match (self.kind(&Interner), other.kind(&Interner)) {
293 (TyKind::Adt(adt, ..), TyKind::Adt(adt2, ..)) => adt == adt2,
294 (TyKind::Slice(_), TyKind::Slice(_)) | (TyKind::Array(_), TyKind::Array(_)) => true,
295 (TyKind::FnDef(def_id, ..), TyKind::FnDef(def_id2, ..)) => def_id == def_id2,
296 (TyKind::OpaqueType(ty_id, ..), TyKind::OpaqueType(ty_id2, ..)) => ty_id == ty_id2,
297 (TyKind::AssociatedType(ty_id, ..), TyKind::AssociatedType(ty_id2, ..)) => {
298 ty_id == ty_id2
299 }
300 (TyKind::Foreign(ty_id, ..), TyKind::Foreign(ty_id2, ..)) => ty_id == ty_id2,
301 (TyKind::Closure(id1, _), TyKind::Closure(id2, _)) => id1 == id2,
302 (TyKind::Ref(mutability, ..), TyKind::Ref(mutability2, ..))
303 | (TyKind::Raw(mutability, ..), TyKind::Raw(mutability2, ..)) => {
304 mutability == mutability2
305 }
306 (
307 TyKind::Function(FnPointer { num_args, sig, .. }),
308 TyKind::Function(FnPointer { num_args: num_args2, sig: sig2, .. }),
309 ) => num_args == num_args2 && sig == sig2,
310 (TyKind::Tuple(cardinality, _), TyKind::Tuple(cardinality2, _)) => {
311 cardinality == cardinality2
312 }
313 (TyKind::Str, TyKind::Str) | (TyKind::Never, TyKind::Never) => true,
314 (TyKind::Scalar(scalar), TyKind::Scalar(scalar2)) => scalar == scalar2,
315 _ => false,
316 }
317 }
318
319 /// If this is a `dyn Trait` type, this returns the `Trait` part.
320 fn dyn_trait_ref(&self) -> Option<&TraitRef> {
321 match self.kind(&Interner) {
322 TyKind::Dyn(dyn_ty) => dyn_ty.bounds.skip_binders().interned().get(0).and_then(|b| {
323 match b.skip_binders() {
324 WhereClause::Implemented(trait_ref) => Some(trait_ref),
325 _ => None,
326 }
327 }),
328 _ => None,
329 }
330 }
331
332 /// If this is a `dyn Trait`, returns that trait.
333 pub fn dyn_trait(&self) -> Option<TraitId> {
334 self.dyn_trait_ref().map(|it| it.trait_id).map(from_chalk_trait_id)
335 }
336
337 fn builtin_deref(&self) -> Option<Ty> {
338 match self.kind(&Interner) {
339 TyKind::Ref(.., ty) => Some(ty.clone()),
340 TyKind::Raw(.., ty) => Some(ty.clone()),
341 _ => None,
342 }
343 }
344
345 pub fn callable_def(&self, db: &dyn HirDatabase) -> Option<CallableDefId> {
346 match self.kind(&Interner) {
347 &TyKind::FnDef(def, ..) => Some(db.lookup_intern_callable_def(def.into())),
348 _ => None,
349 }
350 }
351
352 pub fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId> {
353 if let Some(CallableDefId::FunctionId(func)) = self.callable_def(db) {
354 Some(func)
355 } else {
356 None
357 }
358 }
359
360 pub fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig> {
361 match self.kind(&Interner) {
362 TyKind::Function(fn_ptr) => Some(CallableSig::from_fn_ptr(fn_ptr)),
363 TyKind::FnDef(def, parameters) => {
364 let callable_def = db.lookup_intern_callable_def((*def).into());
365 let sig = db.callable_item_signature(callable_def);
366 Some(sig.substitute(&Interner, &parameters))
367 }
368 TyKind::Closure(.., substs) => {
369 let sig_param = substs.at(&Interner, 0).assert_ty_ref(&Interner);
370 sig_param.callable_sig(db)
371 }
372 _ => None,
373 }
374 }
375
376 /// Returns the type parameters of this type if it has some (i.e. is an ADT
377 /// or function); so if `self` is `Option<u32>`, this returns the `u32`.
378 pub fn substs(&self) -> Option<&Substitution> {
379 match self.kind(&Interner) {
380 TyKind::Adt(_, substs)
381 | TyKind::FnDef(_, substs)
382 | TyKind::Function(FnPointer { substs, .. })
383 | TyKind::Tuple(_, substs)
384 | TyKind::OpaqueType(_, substs)
385 | TyKind::AssociatedType(_, substs)
386 | TyKind::Closure(.., substs) => Some(substs),
387 _ => None,
388 }
389 }
390
391 fn substs_mut(&mut self) -> Option<&mut Substitution> {
392 match self.interned_mut() {
393 TyKind::Adt(_, substs)
394 | TyKind::FnDef(_, substs)
395 | TyKind::Function(FnPointer { substs, .. })
396 | TyKind::Tuple(_, substs)
397 | TyKind::OpaqueType(_, substs)
398 | TyKind::AssociatedType(_, substs)
399 | TyKind::Closure(.., substs) => Some(substs),
400 _ => None,
401 }
402 }
403
404 pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>> {
405 match self.kind(&Interner) {
406 TyKind::OpaqueType(opaque_ty_id, ..) => {
407 match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) {
408 ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => {
409 let krate = def.module(db.upcast()).krate();
410 if let Some(future_trait) = db
411 .lang_item(krate, "future_trait".into())
412 .and_then(|item| item.as_trait())
413 {
414 // This is only used by type walking.
415 // Parameters will be walked outside, and projection predicate is not used.
416 // So just provide the Future trait.
417 let impl_bound = Binders::empty(
418 &Interner,
419 WhereClause::Implemented(TraitRef {
420 trait_id: to_chalk_trait_id(future_trait),
421 substitution: Substitution::empty(&Interner),
422 }),
423 );
424 Some(vec![impl_bound])
425 } else {
426 None
427 }
428 }
429 ImplTraitId::ReturnTypeImplTrait(..) => None,
430 }
431 }
432 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
433 let predicates = match db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into())
434 {
435 ImplTraitId::ReturnTypeImplTrait(func, idx) => {
436 db.return_type_impl_traits(func).map(|it| {
437 let data = (*it)
438 .as_ref()
439 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
440 data.substitute(&Interner, &opaque_ty.substitution)
441 })
442 }
443 // It always has an parameter for Future::Output type.
444 ImplTraitId::AsyncBlockTypeImplTrait(..) => unreachable!(),
445 };
446
447 predicates.map(|it| it.into_value_and_skipped_binders().0)
448 }
449 TyKind::Placeholder(idx) => {
450 let id = from_placeholder_idx(db, *idx);
451 let generic_params = db.generic_params(id.parent);
452 let param_data = &generic_params.types[id.local_id];
453 match param_data.provenance {
454 hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
455 let substs = TyBuilder::type_params_subst(db, id.parent);
456 let predicates = db
457 .generic_predicates(id.parent)
458 .into_iter()
459 .map(|pred| pred.clone().substitute(&Interner, &substs))
460 .filter(|wc| match &wc.skip_binders() {
461 WhereClause::Implemented(tr) => {
462 tr.self_type_parameter(&Interner) == self
463 }
464 WhereClause::AliasEq(AliasEq {
465 alias: AliasTy::Projection(proj),
466 ty: _,
467 }) => proj.self_type_parameter(&Interner) == self,
468 _ => false,
469 })
470 .collect_vec();
471
472 Some(predicates)
473 }
474 _ => None,
475 }
476 }
477 _ => None,
478 }
479 }
480
481 pub fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId> {
482 match self.kind(&Interner) {
483 TyKind::AssociatedType(id, ..) => {
484 match from_assoc_type_id(*id).lookup(db.upcast()).container {
485 AssocContainerId::TraitId(trait_id) => Some(trait_id),
486 _ => None,
487 }
488 }
489 TyKind::Alias(AliasTy::Projection(projection_ty)) => {
490 match from_assoc_type_id(projection_ty.associated_ty_id)
491 .lookup(db.upcast())
492 .container
493 {
494 AssocContainerId::TraitId(trait_id) => Some(trait_id),
495 _ => None,
496 }
497 }
498 _ => None,
499 }
500 } 223 }
501} 224}
502 225
@@ -511,45 +234,75 @@ pub struct ReturnTypeImplTraits {
511 pub(crate) impl_traits: Vec<ReturnTypeImplTrait>, 234 pub(crate) impl_traits: Vec<ReturnTypeImplTrait>,
512} 235}
513 236
237has_interner!(ReturnTypeImplTraits);
238
514#[derive(Clone, PartialEq, Eq, Debug, Hash)] 239#[derive(Clone, PartialEq, Eq, Debug, Hash)]
515pub(crate) struct ReturnTypeImplTrait { 240pub(crate) struct ReturnTypeImplTrait {
516 pub(crate) bounds: Binders<Vec<QuantifiedWhereClause>>, 241 pub(crate) bounds: Binders<Vec<QuantifiedWhereClause>>,
517} 242}
518 243
519pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId { 244pub fn static_lifetime() -> Lifetime {
520 chalk_ir::ForeignDefId(salsa::InternKey::as_intern_id(&id)) 245 LifetimeData::Static.intern(&Interner)
521}
522
523pub fn from_foreign_def_id(id: ForeignDefId) -> TypeAliasId {
524 salsa::InternKey::from_intern_id(id.0)
525} 246}
526 247
527pub fn to_assoc_type_id(id: TypeAliasId) -> AssocTypeId { 248pub fn dummy_usize_const() -> Const {
528 chalk_ir::AssocTypeId(salsa::InternKey::as_intern_id(&id)) 249 let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner);
250 chalk_ir::ConstData {
251 ty: usize_ty,
252 value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { interned: () }),
253 }
254 .intern(&Interner)
529} 255}
530 256
531pub fn from_assoc_type_id(id: AssocTypeId) -> TypeAliasId { 257pub(crate) fn fold_free_vars<T: HasInterner<Interner = Interner> + Fold<Interner>>(
532 salsa::InternKey::from_intern_id(id.0) 258 t: T,
533} 259 f: impl FnMut(BoundVar, DebruijnIndex) -> Ty,
260) -> T::Result {
261 use chalk_ir::{fold::Folder, Fallible};
262 struct FreeVarFolder<F>(F);
263 impl<'i, F: FnMut(BoundVar, DebruijnIndex) -> Ty + 'i> Folder<'i, Interner> for FreeVarFolder<F> {
264 fn as_dyn(&mut self) -> &mut dyn Folder<'i, Interner> {
265 self
266 }
534 267
535pub fn from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> TypeParamId { 268 fn interner(&self) -> &'i Interner {
536 assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT); 269 &Interner
537 let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx)); 270 }
538 db.lookup_intern_type_param_id(interned_id)
539}
540 271
541pub fn to_placeholder_idx(db: &dyn HirDatabase, id: TypeParamId) -> PlaceholderIndex { 272 fn fold_free_var_ty(
542 let interned_id = db.intern_type_param_id(id); 273 &mut self,
543 PlaceholderIndex { 274 bound_var: BoundVar,
544 ui: chalk_ir::UniverseIndex::ROOT, 275 outer_binder: DebruijnIndex,
545 idx: salsa::InternKey::as_intern_id(&interned_id).as_usize(), 276 ) -> Fallible<Ty> {
277 Ok(self.0(bound_var, outer_binder))
278 }
546 } 279 }
280 t.fold_with(&mut FreeVarFolder(f), DebruijnIndex::INNERMOST).expect("fold failed unexpectedly")
547} 281}
548 282
549pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId { 283pub(crate) fn fold_tys<T: HasInterner<Interner = Interner> + Fold<Interner>>(
550 chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id)) 284 t: T,
551} 285 f: impl FnMut(Ty, DebruijnIndex) -> Ty,
286 binders: DebruijnIndex,
287) -> T::Result {
288 use chalk_ir::{
289 fold::{Folder, SuperFold},
290 Fallible,
291 };
292 struct TyFolder<F>(F);
293 impl<'i, F: FnMut(Ty, DebruijnIndex) -> Ty + 'i> Folder<'i, Interner> for TyFolder<F> {
294 fn as_dyn(&mut self) -> &mut dyn Folder<'i, Interner> {
295 self
296 }
552 297
553pub fn from_chalk_trait_id(id: ChalkTraitId) -> TraitId { 298 fn interner(&self) -> &'i Interner {
554 salsa::InternKey::from_intern_id(id.0) 299 &Interner
300 }
301
302 fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Fallible<Ty> {
303 let ty = ty.super_fold_with(self.as_dyn(), outer_binder)?;
304 Ok(self.0(ty, outer_binder))
305 }
306 }
307 t.fold_with(&mut TyFolder(f), binders).expect("fold failed unexpectedly")
555} 308}
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index 48c26f471..a035686bc 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -8,7 +8,7 @@
8use std::{iter, sync::Arc}; 8use std::{iter, sync::Arc};
9 9
10use base_db::CrateId; 10use base_db::CrateId;
11use chalk_ir::{cast::Cast, Mutability, Safety}; 11use chalk_ir::{cast::Cast, fold::Shift, interner::HasInterner, Mutability, Safety};
12use hir_def::{ 12use hir_def::{
13 adt::StructKind, 13 adt::StructKind,
14 builtin_type::BuiltinType, 14 builtin_type::BuiltinType,
@@ -27,16 +27,16 @@ use stdx::impl_from;
27 27
28use crate::{ 28use crate::{
29 db::HirDatabase, 29 db::HirDatabase,
30 to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx, 30 dummy_usize_const,
31 traits::chalk::{Interner, ToChalk}, 31 mapping::ToChalk,
32 static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
32 utils::{ 33 utils::{
33 all_super_trait_refs, associated_type_by_name_including_super_traits, generics, 34 all_super_trait_refs, associated_type_by_name_including_super_traits, generics, Generics,
34 variant_data, Generics,
35 }, 35 },
36 AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig, 36 AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig,
37 ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, 37 FnSubst, ImplTraitId, Interner, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause,
38 ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, Ty, 38 QuantifiedWhereClauses, ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution,
39 TyBuilder, TyKind, TypeWalk, WhereClause, 39 TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause,
40}; 40};
41 41
42#[derive(Debug)] 42#[derive(Debug)]
@@ -166,7 +166,7 @@ impl<'a> TyLoweringContext<'a> {
166 } 166 }
167 TypeRef::Array(inner) => { 167 TypeRef::Array(inner) => {
168 let inner_ty = self.lower_ty(inner); 168 let inner_ty = self.lower_ty(inner);
169 TyKind::Array(inner_ty).intern(&Interner) 169 TyKind::Array(inner_ty, dummy_usize_const()).intern(&Interner)
170 } 170 }
171 TypeRef::Slice(inner) => { 171 TypeRef::Slice(inner) => {
172 let inner_ty = self.lower_ty(inner); 172 let inner_ty = self.lower_ty(inner);
@@ -174,16 +174,19 @@ impl<'a> TyLoweringContext<'a> {
174 } 174 }
175 TypeRef::Reference(inner, _, mutability) => { 175 TypeRef::Reference(inner, _, mutability) => {
176 let inner_ty = self.lower_ty(inner); 176 let inner_ty = self.lower_ty(inner);
177 TyKind::Ref(lower_to_chalk_mutability(*mutability), inner_ty).intern(&Interner) 177 let lifetime = static_lifetime();
178 TyKind::Ref(lower_to_chalk_mutability(*mutability), lifetime, inner_ty)
179 .intern(&Interner)
178 } 180 }
179 TypeRef::Placeholder => TyKind::Error.intern(&Interner), 181 TypeRef::Placeholder => TyKind::Error.intern(&Interner),
180 TypeRef::Fn(params, is_varargs) => { 182 TypeRef::Fn(params, is_varargs) => {
181 let substs = 183 let substs = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
182 Substitution::from_iter(&Interner, params.iter().map(|tr| self.lower_ty(tr))); 184 Substitution::from_iter(&Interner, params.iter().map(|tr| ctx.lower_ty(tr)))
185 });
183 TyKind::Function(FnPointer { 186 TyKind::Function(FnPointer {
184 num_args: substs.len(&Interner) - 1, 187 num_binders: 0, // FIXME lower `for<'a> fn()` correctly
185 sig: FnSig { abi: (), safety: Safety::Safe, variadic: *is_varargs }, 188 sig: FnSig { abi: (), safety: Safety::Safe, variadic: *is_varargs },
186 substs, 189 substitution: FnSubst(substs),
187 }) 190 })
188 .intern(&Interner) 191 .intern(&Interner)
189 } 192 }
@@ -197,7 +200,7 @@ impl<'a> TyLoweringContext<'a> {
197 ) 200 )
198 }); 201 });
199 let bounds = crate::make_only_type_binders(1, bounds); 202 let bounds = crate::make_only_type_binders(1, bounds);
200 TyKind::Dyn(DynTy { bounds }).intern(&Interner) 203 TyKind::Dyn(DynTy { bounds, lifetime: static_lifetime() }).intern(&Interner)
201 } 204 }
202 TypeRef::ImplTrait(bounds) => { 205 TypeRef::ImplTrait(bounds) => {
203 match self.impl_trait_mode { 206 match self.impl_trait_mode {
@@ -384,9 +387,12 @@ impl<'a> TyLoweringContext<'a> {
384 1, 387 1,
385 QuantifiedWhereClauses::from_iter( 388 QuantifiedWhereClauses::from_iter(
386 &Interner, 389 &Interner,
387 Some(Binders::wrap_empty(WhereClause::Implemented(trait_ref))), 390 Some(crate::wrap_empty_binders(WhereClause::Implemented(
391 trait_ref,
392 ))),
388 ), 393 ),
389 ), 394 ),
395 lifetime: static_lifetime(),
390 }; 396 };
391 TyKind::Dyn(dyn_ty).intern(&Interner) 397 TyKind::Dyn(dyn_ty).intern(&Interner)
392 }; 398 };
@@ -483,7 +489,7 @@ impl<'a> TyLoweringContext<'a> {
483 }; 489 };
484 // We need to shift in the bound vars, since 490 // We need to shift in the bound vars, since
485 // associated_type_shorthand_candidates does not do that 491 // associated_type_shorthand_candidates does not do that
486 let substs = substs.shifted_in_from(self.in_binders); 492 let substs = substs.shifted_in_from(&Interner, self.in_binders);
487 // FIXME handle type parameters on the segment 493 // FIXME handle type parameters on the segment
488 return Some( 494 return Some(
489 TyKind::Alias(AliasTy::Projection(ProjectionTy { 495 TyKind::Alias(AliasTy::Projection(ProjectionTy {
@@ -720,7 +726,7 @@ impl<'a> TyLoweringContext<'a> {
720 let trait_ref = match bound { 726 let trait_ref = match bound {
721 TypeBound::Path(path) => { 727 TypeBound::Path(path) => {
722 bindings = self.lower_trait_ref_from_path(path, Some(self_ty)); 728 bindings = self.lower_trait_ref_from_path(path, Some(self_ty));
723 bindings.clone().map(WhereClause::Implemented).map(|b| Binders::wrap_empty(b)) 729 bindings.clone().map(WhereClause::Implemented).map(|b| crate::wrap_empty_binders(b))
724 } 730 }
725 TypeBound::Lifetime(_) => None, 731 TypeBound::Lifetime(_) => None,
726 TypeBound::Error => None, 732 TypeBound::Error => None,
@@ -767,7 +773,7 @@ impl<'a> TyLoweringContext<'a> {
767 let ty = self.lower_ty(type_ref); 773 let ty = self.lower_ty(type_ref);
768 let alias_eq = 774 let alias_eq =
769 AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty }; 775 AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty };
770 preds.push(Binders::wrap_empty(WhereClause::AliasEq(alias_eq))); 776 preds.push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq)));
771 } 777 }
772 for bound in &binding.bounds { 778 for bound in &binding.bounds {
773 preds.extend(self.lower_type_bound( 779 preds.extend(self.lower_type_bound(
@@ -842,7 +848,7 @@ pub fn associated_type_shorthand_candidates<R>(
842 // FIXME: how to correctly handle higher-ranked bounds here? 848 // FIXME: how to correctly handle higher-ranked bounds here?
843 WhereClause::Implemented(tr) => search( 849 WhereClause::Implemented(tr) => search(
844 tr.clone() 850 tr.clone()
845 .shifted_out_to(DebruijnIndex::ONE) 851 .shifted_out_to(&Interner, DebruijnIndex::ONE)
846 .expect("FIXME unexpected higher-ranked trait bound"), 852 .expect("FIXME unexpected higher-ranked trait bound"),
847 ), 853 ),
848 _ => None, 854 _ => None,
@@ -873,7 +879,7 @@ pub(crate) fn field_types_query(
873 db: &dyn HirDatabase, 879 db: &dyn HirDatabase,
874 variant_id: VariantId, 880 variant_id: VariantId,
875) -> Arc<ArenaMap<LocalFieldId, Binders<Ty>>> { 881) -> Arc<ArenaMap<LocalFieldId, Binders<Ty>>> {
876 let var_data = variant_data(db.upcast(), variant_id); 882 let var_data = variant_id.variant_data(db.upcast());
877 let (resolver, def): (_, GenericDefId) = match variant_id { 883 let (resolver, def): (_, GenericDefId) = match variant_id {
878 VariantId::StructId(it) => (it.resolver(db.upcast()), it.into()), 884 VariantId::StructId(it) => (it.resolver(db.upcast()), it.into()),
879 VariantId::UnionId(it) => (it.resolver(db.upcast()), it.into()), 885 VariantId::UnionId(it) => (it.resolver(db.upcast()), it.into()),
@@ -945,8 +951,7 @@ pub(crate) fn trait_environment_query(
945 traits_in_scope 951 traits_in_scope
946 .push((tr.self_type_parameter(&Interner).clone(), tr.hir_trait_id())); 952 .push((tr.self_type_parameter(&Interner).clone(), tr.hir_trait_id()));
947 } 953 }
948 let program_clause: chalk_ir::ProgramClause<Interner> = 954 let program_clause: chalk_ir::ProgramClause<Interner> = pred.clone().cast(&Interner);
949 pred.clone().to_chalk(db).cast(&Interner);
950 clauses.push(program_clause.into_from_env_clause(&Interner)); 955 clauses.push(program_clause.into_from_env_clause(&Interner));
951 } 956 }
952 } 957 }
@@ -969,7 +974,7 @@ pub(crate) fn trait_environment_query(
969 let substs = TyBuilder::type_params_subst(db, trait_id); 974 let substs = TyBuilder::type_params_subst(db, trait_id);
970 let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution: substs }; 975 let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution: substs };
971 let pred = WhereClause::Implemented(trait_ref); 976 let pred = WhereClause::Implemented(trait_ref);
972 let program_clause: chalk_ir::ProgramClause<Interner> = pred.to_chalk(db).cast(&Interner); 977 let program_clause: chalk_ir::ProgramClause<Interner> = pred.cast(&Interner);
973 clauses.push(program_clause.into_from_env_clause(&Interner)); 978 clauses.push(program_clause.into_from_env_clause(&Interner));
974 } 979 }
975 980
@@ -1011,22 +1016,16 @@ pub(crate) fn generic_defaults_query(
1011 p.default.as_ref().map_or(TyKind::Error.intern(&Interner), |t| ctx.lower_ty(t)); 1016 p.default.as_ref().map_or(TyKind::Error.intern(&Interner), |t| ctx.lower_ty(t));
1012 1017
1013 // Each default can only refer to previous parameters. 1018 // Each default can only refer to previous parameters.
1014 ty = ty.fold_binders( 1019 ty = crate::fold_free_vars(ty, |bound, binders| {
1015 &mut |ty, binders| match ty.kind(&Interner) { 1020 if bound.index >= idx && bound.debruijn == DebruijnIndex::INNERMOST {
1016 TyKind::BoundVar(BoundVar { debruijn, index }) if *debruijn == binders => { 1021 // type variable default referring to parameter coming
1017 if *index >= idx { 1022 // after it. This is forbidden (FIXME: report
1018 // type variable default referring to parameter coming 1023 // diagnostic)
1019 // after it. This is forbidden (FIXME: report 1024 TyKind::Error.intern(&Interner)
1020 // diagnostic) 1025 } else {
1021 TyKind::Error.intern(&Interner) 1026 bound.shifted_in_from(binders).to_ty(&Interner)
1022 } else { 1027 }
1023 ty 1028 });
1024 }
1025 }
1026 _ => ty,
1027 },
1028 DebruijnIndex::INNERMOST,
1029 );
1030 1029
1031 crate::make_only_type_binders(idx, ty) 1030 crate::make_only_type_binders(idx, ty)
1032 }) 1031 })
@@ -1302,6 +1301,6 @@ pub(crate) fn lower_to_chalk_mutability(m: hir_def::type_ref::Mutability) -> Mut
1302 } 1301 }
1303} 1302}
1304 1303
1305fn make_binders<T>(generics: &Generics, value: T) -> Binders<T> { 1304fn make_binders<T: HasInterner<Interner = Interner>>(generics: &Generics, value: T) -> Binders<T> {
1306 crate::make_only_type_binders(generics.len(), value) 1305 crate::make_only_type_binders(generics.len(), value)
1307} 1306}
diff --git a/crates/hir_ty/src/mapping.rs b/crates/hir_ty/src/mapping.rs
new file mode 100644
index 000000000..5e86fafe5
--- /dev/null
+++ b/crates/hir_ty/src/mapping.rs
@@ -0,0 +1,154 @@
1//! This module contains the implementations of the `ToChalk` trait, which
2//! handles conversion between our data types and their corresponding types in
3//! Chalk (in both directions); plus some helper functions for more specialized
4//! conversions.
5
6use chalk_solve::rust_ir;
7
8use base_db::salsa::{self, InternKey};
9use hir_def::{ConstParamId, LifetimeParamId, TraitId, TypeAliasId, TypeParamId};
10
11use crate::{
12 chalk_db, db::HirDatabase, AssocTypeId, CallableDefId, ChalkTraitId, FnDefId, ForeignDefId,
13 Interner, OpaqueTyId, PlaceholderIndex,
14};
15
16pub(crate) trait ToChalk {
17 type Chalk;
18 fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk;
19 fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self;
20}
21
22pub(crate) fn from_chalk<T, ChalkT>(db: &dyn HirDatabase, chalk: ChalkT) -> T
23where
24 T: ToChalk<Chalk = ChalkT>,
25{
26 T::from_chalk(db, chalk)
27}
28
29impl ToChalk for hir_def::ImplId {
30 type Chalk = chalk_db::ImplId;
31
32 fn to_chalk(self, _db: &dyn HirDatabase) -> chalk_db::ImplId {
33 chalk_ir::ImplId(self.as_intern_id())
34 }
35
36 fn from_chalk(_db: &dyn HirDatabase, impl_id: chalk_db::ImplId) -> hir_def::ImplId {
37 InternKey::from_intern_id(impl_id.0)
38 }
39}
40
41impl ToChalk for CallableDefId {
42 type Chalk = FnDefId;
43
44 fn to_chalk(self, db: &dyn HirDatabase) -> FnDefId {
45 db.intern_callable_def(self).into()
46 }
47
48 fn from_chalk(db: &dyn HirDatabase, fn_def_id: FnDefId) -> CallableDefId {
49 db.lookup_intern_callable_def(fn_def_id.into())
50 }
51}
52
53pub(crate) struct TypeAliasAsValue(pub(crate) TypeAliasId);
54
55impl ToChalk for TypeAliasAsValue {
56 type Chalk = chalk_db::AssociatedTyValueId;
57
58 fn to_chalk(self, _db: &dyn HirDatabase) -> chalk_db::AssociatedTyValueId {
59 rust_ir::AssociatedTyValueId(self.0.as_intern_id())
60 }
61
62 fn from_chalk(
63 _db: &dyn HirDatabase,
64 assoc_ty_value_id: chalk_db::AssociatedTyValueId,
65 ) -> TypeAliasAsValue {
66 TypeAliasAsValue(TypeAliasId::from_intern_id(assoc_ty_value_id.0))
67 }
68}
69
70impl From<FnDefId> for crate::db::InternedCallableDefId {
71 fn from(fn_def_id: FnDefId) -> Self {
72 InternKey::from_intern_id(fn_def_id.0)
73 }
74}
75
76impl From<crate::db::InternedCallableDefId> for FnDefId {
77 fn from(callable_def_id: crate::db::InternedCallableDefId) -> Self {
78 chalk_ir::FnDefId(callable_def_id.as_intern_id())
79 }
80}
81
82impl From<OpaqueTyId> for crate::db::InternedOpaqueTyId {
83 fn from(id: OpaqueTyId) -> Self {
84 InternKey::from_intern_id(id.0)
85 }
86}
87
88impl From<crate::db::InternedOpaqueTyId> for OpaqueTyId {
89 fn from(id: crate::db::InternedOpaqueTyId) -> Self {
90 chalk_ir::OpaqueTyId(id.as_intern_id())
91 }
92}
93
94impl From<chalk_ir::ClosureId<Interner>> for crate::db::InternedClosureId {
95 fn from(id: chalk_ir::ClosureId<Interner>) -> Self {
96 Self::from_intern_id(id.0)
97 }
98}
99
100impl From<crate::db::InternedClosureId> for chalk_ir::ClosureId<Interner> {
101 fn from(id: crate::db::InternedClosureId) -> Self {
102 chalk_ir::ClosureId(id.as_intern_id())
103 }
104}
105
106pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId {
107 chalk_ir::ForeignDefId(salsa::InternKey::as_intern_id(&id))
108}
109
110pub fn from_foreign_def_id(id: ForeignDefId) -> TypeAliasId {
111 salsa::InternKey::from_intern_id(id.0)
112}
113
114pub fn to_assoc_type_id(id: TypeAliasId) -> AssocTypeId {
115 chalk_ir::AssocTypeId(salsa::InternKey::as_intern_id(&id))
116}
117
118pub fn from_assoc_type_id(id: AssocTypeId) -> TypeAliasId {
119 salsa::InternKey::from_intern_id(id.0)
120}
121
122pub fn from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> TypeParamId {
123 assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
124 let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx));
125 db.lookup_intern_type_param_id(interned_id)
126}
127
128pub fn to_placeholder_idx(db: &dyn HirDatabase, id: TypeParamId) -> PlaceholderIndex {
129 let interned_id = db.intern_type_param_id(id);
130 PlaceholderIndex {
131 ui: chalk_ir::UniverseIndex::ROOT,
132 idx: salsa::InternKey::as_intern_id(&interned_id).as_usize(),
133 }
134}
135
136pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> LifetimeParamId {
137 assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
138 let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx));
139 db.lookup_intern_lifetime_param_id(interned_id)
140}
141
142pub fn const_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> ConstParamId {
143 assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
144 let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx));
145 db.lookup_intern_const_param_id(interned_id)
146}
147
148pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId {
149 chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id))
150}
151
152pub fn from_chalk_trait_id(id: ChalkTraitId) -> TraitId {
153 salsa::InternKey::from_intern_id(id.0)
154}
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index 19a1fa793..ece884241 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -8,62 +8,103 @@ 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};
16use stdx::always;
16 17
17use crate::{ 18use crate::{
18 autoderef, 19 autoderef,
19 db::HirDatabase, 20 db::HirDatabase,
20 from_foreign_def_id, 21 from_foreign_def_id,
21 primitive::{self, FloatTy, IntTy, UintTy}, 22 primitive::{self, FloatTy, IntTy, UintTy},
23 static_lifetime,
22 utils::all_super_traits, 24 utils::all_super_traits,
23 AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, FnSig, ForeignDefId, 25 AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, ForeignDefId, InEnvironment, Interner,
24 InEnvironment, Interner, Scalar, Substitution, TraitEnvironment, Ty, TyBuilder, TyKind, 26 Scalar, Substitution, TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyExt, TyKind,
25 TypeWalk,
26}; 27};
27 28
28/// This is used as a key for indexing impls. 29/// This is used as a key for indexing impls.
29#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 30#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
30pub enum TyFingerprint { 31pub enum TyFingerprint {
32 // These are lang item impls:
31 Str, 33 Str,
32 Slice, 34 Slice,
33 Array, 35 Array,
34 Never, 36 Never,
35 RawPtr(Mutability), 37 RawPtr(Mutability),
36 Scalar(Scalar), 38 Scalar(Scalar),
39 // These can have user-defined impls:
37 Adt(hir_def::AdtId), 40 Adt(hir_def::AdtId),
38 Dyn(TraitId), 41 Dyn(TraitId),
39 Tuple(usize),
40 ForeignType(ForeignDefId), 42 ForeignType(ForeignDefId),
41 FnPtr(usize, FnSig), 43 // These only exist for trait impls
44 Unit,
45 Unnameable,
46 Function(u32),
42} 47}
43 48
44impl TyFingerprint { 49impl TyFingerprint {
45 /// Creates a TyFingerprint for looking up an impl. Only certain types can 50 /// Creates a TyFingerprint for looking up an inherent impl. Only certain
46 /// have impls: if we have some `struct S`, we can have an `impl S`, but not 51 /// types can have inherent impls: if we have some `struct S`, we can have
47 /// `impl &S`. Hence, this will return `None` for reference types and such. 52 /// an `impl S`, but not `impl &S`. Hence, this will return `None` for
48 pub fn for_impl(ty: &Ty) -> Option<TyFingerprint> { 53 /// reference types and such.
49 let fp = match *ty.kind(&Interner) { 54 pub fn for_inherent_impl(ty: &Ty) -> Option<TyFingerprint> {
55 let fp = match ty.kind(&Interner) {
50 TyKind::Str => TyFingerprint::Str, 56 TyKind::Str => TyFingerprint::Str,
51 TyKind::Never => TyFingerprint::Never, 57 TyKind::Never => TyFingerprint::Never,
52 TyKind::Slice(..) => TyFingerprint::Slice, 58 TyKind::Slice(..) => TyFingerprint::Slice,
53 TyKind::Array(..) => TyFingerprint::Array, 59 TyKind::Array(..) => TyFingerprint::Array,
54 TyKind::Scalar(scalar) => TyFingerprint::Scalar(scalar), 60 TyKind::Scalar(scalar) => TyFingerprint::Scalar(*scalar),
55 TyKind::Adt(AdtId(adt), _) => TyFingerprint::Adt(adt), 61 TyKind::Adt(AdtId(adt), _) => TyFingerprint::Adt(*adt),
56 TyKind::Tuple(cardinality, _) => TyFingerprint::Tuple(cardinality), 62 TyKind::Raw(mutability, ..) => TyFingerprint::RawPtr(*mutability),
57 TyKind::Raw(mutability, ..) => TyFingerprint::RawPtr(mutability), 63 TyKind::Foreign(alias_id, ..) => TyFingerprint::ForeignType(*alias_id),
58 TyKind::Foreign(alias_id, ..) => TyFingerprint::ForeignType(alias_id),
59 TyKind::Function(FnPointer { num_args, sig, .. }) => {
60 TyFingerprint::FnPtr(num_args, sig)
61 }
62 TyKind::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_))?, 64 TyKind::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_))?,
63 _ => return None, 65 _ => return None,
64 }; 66 };
65 Some(fp) 67 Some(fp)
66 } 68 }
69
70 /// Creates a TyFingerprint for looking up a trait impl.
71 pub fn for_trait_impl(ty: &Ty) -> Option<TyFingerprint> {
72 let fp = match ty.kind(&Interner) {
73 TyKind::Str => TyFingerprint::Str,
74 TyKind::Never => TyFingerprint::Never,
75 TyKind::Slice(..) => TyFingerprint::Slice,
76 TyKind::Array(..) => TyFingerprint::Array,
77 TyKind::Scalar(scalar) => TyFingerprint::Scalar(*scalar),
78 TyKind::Adt(AdtId(adt), _) => TyFingerprint::Adt(*adt),
79 TyKind::Raw(mutability, ..) => TyFingerprint::RawPtr(*mutability),
80 TyKind::Foreign(alias_id, ..) => TyFingerprint::ForeignType(*alias_id),
81 TyKind::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_))?,
82 TyKind::Ref(_, _, ty) => return TyFingerprint::for_trait_impl(ty),
83 TyKind::Tuple(_, subst) => {
84 let first_ty = subst.interned().get(0).map(|arg| arg.assert_ty_ref(&Interner));
85 if let Some(ty) = first_ty {
86 return TyFingerprint::for_trait_impl(ty);
87 } else {
88 TyFingerprint::Unit
89 }
90 }
91 TyKind::AssociatedType(_, _)
92 | TyKind::OpaqueType(_, _)
93 | TyKind::FnDef(_, _)
94 | TyKind::Closure(_, _)
95 | TyKind::Generator(..)
96 | TyKind::GeneratorWitness(..) => TyFingerprint::Unnameable,
97 TyKind::Function(fn_ptr) => {
98 TyFingerprint::Function(fn_ptr.substitution.0.len(&Interner) as u32)
99 }
100 TyKind::Alias(_)
101 | TyKind::Placeholder(_)
102 | TyKind::BoundVar(_)
103 | TyKind::InferenceVar(_, _)
104 | TyKind::Error => return None,
105 };
106 Some(fp)
107 }
67} 108}
68 109
69pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [ 110pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [
@@ -99,25 +140,38 @@ impl TraitImpls {
99 let mut impls = Self { map: FxHashMap::default() }; 140 let mut impls = Self { map: FxHashMap::default() };
100 141
101 let crate_def_map = db.crate_def_map(krate); 142 let crate_def_map = db.crate_def_map(krate);
102 for (_module_id, module_data) in crate_def_map.modules() { 143 collect_def_map(db, &crate_def_map, &mut impls);
103 for impl_id in module_data.scope.impls() { 144
104 let target_trait = match db.impl_trait(impl_id) { 145 return Arc::new(impls);
105 Some(tr) => tr.skip_binders().hir_trait_id(), 146
106 None => continue, 147 fn collect_def_map(db: &dyn HirDatabase, def_map: &DefMap, impls: &mut TraitImpls) {
107 }; 148 for (_module_id, module_data) in def_map.modules() {
108 let self_ty = db.impl_self_ty(impl_id); 149 for impl_id in module_data.scope.impls() {
109 let self_ty_fp = TyFingerprint::for_impl(self_ty.skip_binders()); 150 let target_trait = match db.impl_trait(impl_id) {
110 impls 151 Some(tr) => tr.skip_binders().hir_trait_id(),
111 .map 152 None => continue,
112 .entry(target_trait) 153 };
113 .or_default() 154 let self_ty = db.impl_self_ty(impl_id);
114 .entry(self_ty_fp) 155 let self_ty_fp = TyFingerprint::for_trait_impl(self_ty.skip_binders());
115 .or_default() 156 impls
116 .push(impl_id); 157 .map
158 .entry(target_trait)
159 .or_default()
160 .entry(self_ty_fp)
161 .or_default()
162 .push(impl_id);
163 }
164
165 // To better support custom derives, collect impls in all unnamed const items.
166 // const _: () = { ... };
167 for konst in module_data.scope.unnamed_consts() {
168 let body = db.body(konst.into());
169 for (_, block_def_map) in body.blocks(db.upcast()) {
170 collect_def_map(db, &block_def_map, impls);
171 }
172 }
117 } 173 }
118 } 174 }
119
120 Arc::new(impls)
121 } 175 }
122 176
123 pub(crate) fn trait_impls_in_deps_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> { 177 pub(crate) fn trait_impls_in_deps_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> {
@@ -143,10 +197,13 @@ impl TraitImpls {
143 } 197 }
144 198
145 /// Queries all trait impls for the given type. 199 /// Queries all trait impls for the given type.
146 pub fn for_self_ty(&self, fp: TyFingerprint) -> impl Iterator<Item = ImplId> + '_ { 200 pub fn for_self_ty_without_blanket_impls(
201 &self,
202 fp: TyFingerprint,
203 ) -> impl Iterator<Item = ImplId> + '_ {
147 self.map 204 self.map
148 .values() 205 .values()
149 .flat_map(move |impls| impls.get(&None).into_iter().chain(impls.get(&Some(fp)))) 206 .flat_map(move |impls| impls.get(&Some(fp)).into_iter())
150 .flat_map(|it| it.iter().copied()) 207 .flat_map(|it| it.iter().copied())
151 } 208 }
152 209
@@ -201,17 +258,22 @@ impl InherentImpls {
201 } 258 }
202 259
203 let self_ty = db.impl_self_ty(impl_id); 260 let self_ty = db.impl_self_ty(impl_id);
204 if let Some(fp) = TyFingerprint::for_impl(self_ty.skip_binders()) { 261 let fp = TyFingerprint::for_inherent_impl(self_ty.skip_binders());
262 always!(fp.is_some());
263 if let Some(fp) = fp {
205 map.entry(fp).or_default().push(impl_id); 264 map.entry(fp).or_default().push(impl_id);
206 } 265 }
207 } 266 }
208 } 267 }
209 268
269 // NOTE: We're not collecting inherent impls from unnamed consts here, we intentionally only
270 // support trait impls there.
271
210 Arc::new(Self { map }) 272 Arc::new(Self { map })
211 } 273 }
212 274
213 pub fn for_self_ty(&self, self_ty: &Ty) -> &[ImplId] { 275 pub fn for_self_ty(&self, self_ty: &Ty) -> &[ImplId] {
214 match TyFingerprint::for_impl(self_ty) { 276 match TyFingerprint::for_inherent_impl(self_ty) {
215 Some(fp) => self.map.get(&fp).map(|vec| vec.as_ref()).unwrap_or(&[]), 277 Some(fp) => self.map.get(&fp).map(|vec| vec.as_ref()).unwrap_or(&[]),
216 None => &[], 278 None => &[],
217 } 279 }
@@ -222,15 +284,14 @@ impl InherentImpls {
222 } 284 }
223} 285}
224 286
225impl Ty { 287pub fn def_crates(
226 pub fn def_crates( 288 db: &dyn HirDatabase,
227 &self, 289 ty: &Ty,
228 db: &dyn HirDatabase, 290 cur_crate: CrateId,
229 cur_crate: CrateId, 291) -> Option<ArrayVec<CrateId, 2>> {
230 ) -> Option<ArrayVec<CrateId, 2>> { 292 // Types like slice can have inherent impls in several crates, (core and alloc).
231 // Types like slice can have inherent impls in several crates, (core and alloc). 293 // The corresponding impls are marked with lang items, so we can use them to find the required crates.
232 // The corresponding impls are marked with lang items, so we can use them to find the required crates. 294 macro_rules! lang_item_crate {
233 macro_rules! lang_item_crate {
234 ($($name:expr),+ $(,)?) => {{ 295 ($($name:expr),+ $(,)?) => {{
235 let mut v = ArrayVec::<LangItemTarget, 2>::new(); 296 let mut v = ArrayVec::<LangItemTarget, 2>::new();
236 $( 297 $(
@@ -240,51 +301,50 @@ impl Ty {
240 }}; 301 }};
241 } 302 }
242 303
243 let mod_to_crate_ids = |module: ModuleId| Some(std::iter::once(module.krate()).collect()); 304 let mod_to_crate_ids = |module: ModuleId| Some(std::iter::once(module.krate()).collect());
244 305
245 let lang_item_targets = match self.kind(&Interner) { 306 let lang_item_targets = match ty.kind(&Interner) {
246 TyKind::Adt(AdtId(def_id), _) => { 307 TyKind::Adt(AdtId(def_id), _) => {
247 return mod_to_crate_ids(def_id.module(db.upcast())); 308 return mod_to_crate_ids(def_id.module(db.upcast()));
248 } 309 }
249 TyKind::Foreign(id) => { 310 TyKind::Foreign(id) => {
250 return mod_to_crate_ids( 311 return mod_to_crate_ids(
251 from_foreign_def_id(*id).lookup(db.upcast()).module(db.upcast()), 312 from_foreign_def_id(*id).lookup(db.upcast()).module(db.upcast()),
252 ); 313 );
253 } 314 }
254 TyKind::Scalar(Scalar::Bool) => lang_item_crate!("bool"), 315 TyKind::Scalar(Scalar::Bool) => lang_item_crate!("bool"),
255 TyKind::Scalar(Scalar::Char) => lang_item_crate!("char"), 316 TyKind::Scalar(Scalar::Char) => lang_item_crate!("char"),
256 TyKind::Scalar(Scalar::Float(f)) => match f { 317 TyKind::Scalar(Scalar::Float(f)) => match f {
257 // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime) 318 // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime)
258 FloatTy::F32 => lang_item_crate!("f32", "f32_runtime"), 319 FloatTy::F32 => lang_item_crate!("f32", "f32_runtime"),
259 FloatTy::F64 => lang_item_crate!("f64", "f64_runtime"), 320 FloatTy::F64 => lang_item_crate!("f64", "f64_runtime"),
260 }, 321 },
261 &TyKind::Scalar(Scalar::Int(t)) => { 322 &TyKind::Scalar(Scalar::Int(t)) => {
262 lang_item_crate!(primitive::int_ty_to_string(t)) 323 lang_item_crate!(primitive::int_ty_to_string(t))
263 } 324 }
264 &TyKind::Scalar(Scalar::Uint(t)) => { 325 &TyKind::Scalar(Scalar::Uint(t)) => {
265 lang_item_crate!(primitive::uint_ty_to_string(t)) 326 lang_item_crate!(primitive::uint_ty_to_string(t))
266 } 327 }
267 TyKind::Str => lang_item_crate!("str_alloc", "str"), 328 TyKind::Str => lang_item_crate!("str_alloc", "str"),
268 TyKind::Slice(_) => lang_item_crate!("slice_alloc", "slice"), 329 TyKind::Slice(_) => lang_item_crate!("slice_alloc", "slice"),
269 TyKind::Raw(Mutability::Not, _) => lang_item_crate!("const_ptr"), 330 TyKind::Raw(Mutability::Not, _) => lang_item_crate!("const_ptr"),
270 TyKind::Raw(Mutability::Mut, _) => lang_item_crate!("mut_ptr"), 331 TyKind::Raw(Mutability::Mut, _) => lang_item_crate!("mut_ptr"),
271 TyKind::Dyn(_) => { 332 TyKind::Dyn(_) => {
272 return self.dyn_trait().and_then(|trait_| { 333 return ty.dyn_trait().and_then(|trait_| {
273 mod_to_crate_ids(GenericDefId::TraitId(trait_).module(db.upcast())) 334 mod_to_crate_ids(GenericDefId::TraitId(trait_).module(db.upcast()))
274 }); 335 });
275 } 336 }
276 _ => return None, 337 _ => return None,
277 }; 338 };
278 let res = lang_item_targets 339 let res = lang_item_targets
279 .into_iter() 340 .into_iter()
280 .filter_map(|it| match it { 341 .filter_map(|it| match it {
281 LangItemTarget::ImplDefId(it) => Some(it), 342 LangItemTarget::ImplDefId(it) => Some(it),
282 _ => None, 343 _ => None,
283 }) 344 })
284 .map(|it| it.lookup(db.upcast()).container.krate()) 345 .map(|it| it.lookup(db.upcast()).container.krate())
285 .collect(); 346 .collect();
286 Some(res) 347 Some(res)
287 }
288} 348}
289 349
290/// Look up the method with the given name, returning the actual autoderefed 350/// Look up the method with the given name, returning the actual autoderefed
@@ -453,7 +513,8 @@ fn iterate_method_candidates_with_autoref(
453 } 513 }
454 let refed = Canonical { 514 let refed = Canonical {
455 binders: deref_chain[0].binders.clone(), 515 binders: deref_chain[0].binders.clone(),
456 value: TyKind::Ref(Mutability::Not, deref_chain[0].value.clone()).intern(&Interner), 516 value: TyKind::Ref(Mutability::Not, static_lifetime(), deref_chain[0].value.clone())
517 .intern(&Interner),
457 }; 518 };
458 if iterate_method_candidates_by_receiver( 519 if iterate_method_candidates_by_receiver(
459 &refed, 520 &refed,
@@ -470,7 +531,8 @@ fn iterate_method_candidates_with_autoref(
470 } 531 }
471 let ref_muted = Canonical { 532 let ref_muted = Canonical {
472 binders: deref_chain[0].binders.clone(), 533 binders: deref_chain[0].binders.clone(),
473 value: TyKind::Ref(Mutability::Mut, deref_chain[0].value.clone()).intern(&Interner), 534 value: TyKind::Ref(Mutability::Mut, static_lifetime(), deref_chain[0].value.clone())
535 .intern(&Interner),
474 }; 536 };
475 if iterate_method_candidates_by_receiver( 537 if iterate_method_candidates_by_receiver(
476 &ref_muted, 538 &ref_muted,
@@ -592,6 +654,7 @@ fn iterate_trait_method_candidates(
592 } 654 }
593 } 655 }
594 known_implemented = true; 656 known_implemented = true;
657 // FIXME: we shouldn't be ignoring the binders here
595 if callback(&self_ty.value, *item) { 658 if callback(&self_ty.value, *item) {
596 return true; 659 return true;
597 } 660 }
@@ -609,7 +672,7 @@ fn iterate_inherent_methods(
609 visible_from_module: Option<ModuleId>, 672 visible_from_module: Option<ModuleId>,
610 callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, 673 callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool,
611) -> bool { 674) -> bool {
612 let def_crates = match self_ty.value.def_crates(db, krate) { 675 let def_crates = match def_crates(db, &self_ty.value, krate) {
613 Some(k) => k, 676 Some(k) => k,
614 None => return false, 677 None => return false,
615 }; 678 };
@@ -709,8 +772,9 @@ pub(crate) fn inherent_impl_substs(
709) -> Option<Substitution> { 772) -> Option<Substitution> {
710 // we create a var for each type parameter of the impl; we need to keep in 773 // we create a var for each type parameter of the impl; we need to keep in
711 // mind here that `self_ty` might have vars of its own 774 // mind here that `self_ty` might have vars of its own
775 let self_ty_vars = self_ty.binders.len(&Interner);
712 let vars = TyBuilder::subst_for_def(db, impl_id) 776 let vars = TyBuilder::subst_for_def(db, impl_id)
713 .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.binders.len(&Interner)) 777 .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty_vars)
714 .build(); 778 .build();
715 let self_ty_with_vars = db.impl_self_ty(impl_id).substitute(&Interner, &vars); 779 let self_ty_with_vars = db.impl_self_ty(impl_id).substitute(&Interner, &vars);
716 let mut kinds = self_ty.binders.interned().to_vec(); 780 let mut kinds = self_ty.binders.interned().to_vec();
@@ -725,33 +789,27 @@ pub(crate) fn inherent_impl_substs(
725 binders: CanonicalVarKinds::from_iter(&Interner, kinds), 789 binders: CanonicalVarKinds::from_iter(&Interner, kinds),
726 value: (self_ty_with_vars, self_ty.value.clone()), 790 value: (self_ty_with_vars, self_ty.value.clone()),
727 }; 791 };
728 let substs = super::infer::unify(&tys); 792 let substs = super::infer::unify(&tys)?;
729 // We only want the substs for the vars we added, not the ones from self_ty. 793 // We only want the substs for the vars we added, not the ones from self_ty.
730 // Also, if any of the vars we added are still in there, we replace them by 794 // Also, if any of the vars we added are still in there, we replace them by
731 // Unknown. I think this can only really happen if self_ty contained 795 // Unknown. I think this can only really happen if self_ty contained
732 // Unknown, and in that case we want the result to contain Unknown in those 796 // Unknown, and in that case we want the result to contain Unknown in those
733 // places again. 797 // places again.
734 substs 798 let suffix =
735 .map(|s| fallback_bound_vars(s.suffix(vars.len(&Interner)), self_ty.binders.len(&Interner))) 799 Substitution::from_iter(&Interner, substs.iter(&Interner).cloned().skip(self_ty_vars));
800 Some(fallback_bound_vars(suffix, self_ty_vars))
736} 801}
737 802
738/// This replaces any 'free' Bound vars in `s` (i.e. those with indices past 803/// This replaces any 'free' Bound vars in `s` (i.e. those with indices past
739/// num_vars_to_keep) by `TyKind::Unknown`. 804/// num_vars_to_keep) by `TyKind::Unknown`.
740fn fallback_bound_vars(s: Substitution, num_vars_to_keep: usize) -> Substitution { 805fn fallback_bound_vars(s: Substitution, num_vars_to_keep: usize) -> Substitution {
741 s.fold_binders( 806 crate::fold_free_vars(s, |bound, binders| {
742 &mut |ty, binders| { 807 if bound.index >= num_vars_to_keep && bound.debruijn == DebruijnIndex::INNERMOST {
743 if let TyKind::BoundVar(bound) = ty.kind(&Interner) { 808 TyKind::Error.intern(&Interner)
744 if bound.index >= num_vars_to_keep && bound.debruijn >= binders { 809 } else {
745 TyKind::Error.intern(&Interner) 810 bound.shifted_in_from(binders).to_ty(&Interner)
746 } else { 811 }
747 ty 812 })
748 }
749 } else {
750 ty
751 }
752 },
753 DebruijnIndex::INNERMOST,
754 )
755} 813}
756 814
757fn transform_receiver_ty( 815fn transform_receiver_ty(
@@ -826,7 +884,7 @@ fn generic_implements_goal(
826 let obligation = trait_ref.cast(&Interner); 884 let obligation = trait_ref.cast(&Interner);
827 Canonical { 885 Canonical {
828 binders: CanonicalVarKinds::from_iter(&Interner, kinds), 886 binders: CanonicalVarKinds::from_iter(&Interner, kinds),
829 value: InEnvironment::new(env.env.clone(), obligation), 887 value: InEnvironment::new(&env.env, obligation),
830 } 888 }
831} 889}
832 890
@@ -837,7 +895,9 @@ fn autoderef_method_receiver(
837) -> Vec<Canonical<Ty>> { 895) -> Vec<Canonical<Ty>> {
838 let mut deref_chain: Vec<_> = autoderef::autoderef(db, Some(krate), ty).collect(); 896 let mut deref_chain: Vec<_> = autoderef::autoderef(db, Some(krate), ty).collect();
839 // As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!) 897 // As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!)
840 if let Some(TyKind::Array(parameters)) = deref_chain.last().map(|ty| ty.value.kind(&Interner)) { 898 if let Some(TyKind::Array(parameters, _)) =
899 deref_chain.last().map(|ty| ty.value.kind(&Interner))
900 {
841 let kinds = deref_chain.last().unwrap().binders.clone(); 901 let kinds = deref_chain.last().unwrap().binders.clone();
842 let unsized_ty = TyKind::Slice(parameters.clone()).intern(&Interner); 902 let unsized_ty = TyKind::Slice(parameters.clone()).intern(&Interner);
843 deref_chain.push(Canonical { value: unsized_ty, binders: kinds }) 903 deref_chain.push(Canonical { value: unsized_ty, binders: kinds })
diff --git a/crates/hir_ty/src/op.rs b/crates/hir_ty/src/op.rs
index 0491c5cb4..0222de2bc 100644
--- a/crates/hir_ty/src/op.rs
+++ b/crates/hir_ty/src/op.rs
@@ -9,21 +9,55 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty {
9 BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => TyKind::Scalar(Scalar::Bool).intern(&Interner), 9 BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
10 BinaryOp::Assignment { .. } => TyBuilder::unit(), 10 BinaryOp::Assignment { .. } => TyBuilder::unit(),
11 BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => { 11 BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => {
12 match lhs_ty.kind(&Interner) { 12 // all integer combinations are valid here
13 if matches!(
14 lhs_ty.kind(&Interner),
13 TyKind::Scalar(Scalar::Int(_)) 15 TyKind::Scalar(Scalar::Int(_))
14 | TyKind::Scalar(Scalar::Uint(_)) 16 | TyKind::Scalar(Scalar::Uint(_))
15 | TyKind::Scalar(Scalar::Float(_)) => lhs_ty, 17 | TyKind::InferenceVar(_, TyVariableKind::Integer)
16 TyKind::InferenceVar(_, TyVariableKind::Integer) 18 ) && matches!(
17 | TyKind::InferenceVar(_, TyVariableKind::Float) => lhs_ty, 19 rhs_ty.kind(&Interner),
18 _ => TyKind::Error.intern(&Interner), 20 TyKind::Scalar(Scalar::Int(_))
21 | TyKind::Scalar(Scalar::Uint(_))
22 | TyKind::InferenceVar(_, TyVariableKind::Integer)
23 ) {
24 lhs_ty
25 } else {
26 TyKind::Error.intern(&Interner)
19 } 27 }
20 } 28 }
21 BinaryOp::ArithOp(_) => match rhs_ty.kind(&Interner) { 29 BinaryOp::ArithOp(_) => match (lhs_ty.kind(&Interner), rhs_ty.kind(&Interner)) {
22 TyKind::Scalar(Scalar::Int(_)) 30 // (int, int) | (uint, uint) | (float, float)
23 | TyKind::Scalar(Scalar::Uint(_)) 31 (TyKind::Scalar(Scalar::Int(_)), TyKind::Scalar(Scalar::Int(_)))
24 | TyKind::Scalar(Scalar::Float(_)) => rhs_ty, 32 | (TyKind::Scalar(Scalar::Uint(_)), TyKind::Scalar(Scalar::Uint(_)))
25 TyKind::InferenceVar(_, TyVariableKind::Integer) 33 | (TyKind::Scalar(Scalar::Float(_)), TyKind::Scalar(Scalar::Float(_))) => rhs_ty,
26 | TyKind::InferenceVar(_, TyVariableKind::Float) => rhs_ty, 34 // ({int}, int) | ({int}, uint)
35 (TyKind::InferenceVar(_, TyVariableKind::Integer), TyKind::Scalar(Scalar::Int(_)))
36 | (TyKind::InferenceVar(_, TyVariableKind::Integer), TyKind::Scalar(Scalar::Uint(_))) => {
37 rhs_ty
38 }
39 // (int, {int}) | (uint, {int})
40 (TyKind::Scalar(Scalar::Int(_)), TyKind::InferenceVar(_, TyVariableKind::Integer))
41 | (TyKind::Scalar(Scalar::Uint(_)), TyKind::InferenceVar(_, TyVariableKind::Integer)) => {
42 lhs_ty
43 }
44 // ({float} | float)
45 (TyKind::InferenceVar(_, TyVariableKind::Float), TyKind::Scalar(Scalar::Float(_))) => {
46 rhs_ty
47 }
48 // (float, {float})
49 (TyKind::Scalar(Scalar::Float(_)), TyKind::InferenceVar(_, TyVariableKind::Float)) => {
50 lhs_ty
51 }
52 // ({int}, {int}) | ({float}, {float})
53 (
54 TyKind::InferenceVar(_, TyVariableKind::Integer),
55 TyKind::InferenceVar(_, TyVariableKind::Integer),
56 )
57 | (
58 TyKind::InferenceVar(_, TyVariableKind::Float),
59 TyKind::InferenceVar(_, TyVariableKind::Float),
60 ) => rhs_ty,
27 _ => TyKind::Error.intern(&Interner), 61 _ => TyKind::Error.intern(&Interner),
28 }, 62 },
29 } 63 }
diff --git a/crates/hir_ty/src/primitive.rs b/crates/hir_ty/src/primitive.rs
index 2449addfb..d7f48c69a 100644
--- a/crates/hir_ty/src/primitive.rs
+++ b/crates/hir_ty/src/primitive.rs
@@ -1,7 +1,4 @@
1//! Defines primitive types, which have a couple of peculiarities: 1//! A few helper functions for dealing with primitives.
2//!
3//! * during type inference, they can be uncertain (ie, `let x = 92;`)
4//! * they don't belong to any particular crate.
5 2
6pub use chalk_ir::{FloatTy, IntTy, UintTy}; 3pub use chalk_ir::{FloatTy, IntTy, UintTy};
7pub use hir_def::builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint}; 4pub use hir_def::builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint};
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/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs
index b69f86050..9cd9f473d 100644
--- a/crates/hir_ty/src/tests/regression.rs
+++ b/crates/hir_ty/src/tests/regression.rs
@@ -974,3 +974,41 @@ fn param_overrides_fn() {
974 "#, 974 "#,
975 ) 975 )
976} 976}
977
978#[test]
979fn lifetime_from_chalk_during_deref() {
980 check_types(
981 r#"
982 #[lang = "deref"]
983 pub trait Deref {
984 type Target;
985 }
986
987 struct Box<T: ?Sized> {}
988 impl<T> Deref for Box<T> {
989 type Target = T;
990
991 fn deref(&self) -> &Self::Target {
992 loop {}
993 }
994 }
995
996 trait Iterator {
997 type Item;
998 }
999
1000 pub struct Iter<'a, T: 'a> {
1001 inner: Box<dyn IterTrait<'a, T, Item = &'a T> + 'a>,
1002 }
1003
1004 trait IterTrait<'a, T: 'a>: Iterator<Item = &'a T> {
1005 fn clone_box(&self);
1006 }
1007
1008 fn clone_iter<T>(s: Iter<T>) {
1009 s.inner.clone_box();
1010 //^^^^^^^^^^^^^^^^^^^ ()
1011 }
1012 "#,
1013 )
1014}
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs
index 361cd6302..84c5c05fd 100644
--- a/crates/hir_ty/src/tests/simple.rs
+++ b/crates/hir_ty/src/tests/simple.rs
@@ -2564,3 +2564,36 @@ fn f() {
2564 "#, 2564 "#,
2565 ) 2565 )
2566} 2566}
2567
2568#[test]
2569fn infer_type_alias_variant() {
2570 check_infer(
2571 r#"
2572type Qux = Foo;
2573enum Foo {
2574 Bar(i32),
2575 Baz { baz: f32 }
2576}
2577
2578fn f() {
2579 match Foo::Bar(3) {
2580 Qux::Bar(bar) => (),
2581 Qux::Baz { baz } => (),
2582 }
2583}
2584 "#,
2585 expect![[r#"
2586 72..166 '{ ... } }': ()
2587 78..164 'match ... }': ()
2588 84..92 'Foo::Bar': Bar(i32) -> Foo
2589 84..95 'Foo::Bar(3)': Foo
2590 93..94 '3': i32
2591 106..119 'Qux::Bar(bar)': Foo
2592 115..118 'bar': i32
2593 123..125 '()': ()
2594 135..151 'Qux::B... baz }': Foo
2595 146..149 'baz': f32
2596 155..157 '()': ()
2597 "#]],
2598 )
2599}
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs
index 65b71fdfa..ffc7c8ef4 100644
--- a/crates/hir_ty/src/tests/traits.rs
+++ b/crates/hir_ty/src/tests/traits.rs
@@ -263,15 +263,14 @@ mod ops {
263fn infer_from_bound_1() { 263fn infer_from_bound_1() {
264 check_infer( 264 check_infer(
265 r#" 265 r#"
266 trait Trait<T> {} 266trait Trait<T> {}
267 struct S<T>(T); 267struct S<T>(T);
268 impl<U> Trait<U> for S<U> {} 268impl<U> Trait<U> for S<U> {}
269 fn foo<T: Trait<u32>>(t: T) {} 269fn foo<T: Trait<u32>>(t: T) {}
270 fn test() { 270fn test() {
271 let s = S(unknown); 271 let s = S(unknown);
272 foo(s); 272 foo(s);
273 } 273}"#,
274 "#,
275 expect![[r#" 274 expect![[r#"
276 85..86 't': T 275 85..86 't': T
277 91..93 '{}': () 276 91..93 '{}': ()
@@ -291,15 +290,14 @@ fn infer_from_bound_1() {
291fn infer_from_bound_2() { 290fn infer_from_bound_2() {
292 check_infer( 291 check_infer(
293 r#" 292 r#"
294 trait Trait<T> {} 293trait Trait<T> {}
295 struct S<T>(T); 294struct S<T>(T);
296 impl<U> Trait<U> for S<U> {} 295impl<U> Trait<U> for S<U> {}
297 fn foo<U, T: Trait<U>>(t: T) -> U {} 296fn foo<U, T: Trait<U>>(t: T) -> U {}
298 fn test() { 297fn test() {
299 let s = S(unknown); 298 let s = S(unknown);
300 let x: u32 = foo(s); 299 let x: u32 = foo(s);
301 } 300}"#,
302 "#,
303 expect![[r#" 301 expect![[r#"
304 86..87 't': T 302 86..87 't': T
305 97..99 '{}': () 303 97..99 '{}': ()
@@ -321,13 +319,12 @@ fn trait_default_method_self_bound_implements_trait() {
321 cov_mark::check!(trait_self_implements_self); 319 cov_mark::check!(trait_self_implements_self);
322 check_infer( 320 check_infer(
323 r#" 321 r#"
324 trait Trait { 322trait Trait {
325 fn foo(&self) -> i64; 323 fn foo(&self) -> i64;
326 fn bar(&self) -> { 324 fn bar(&self) -> {
327 let x = self.foo(); 325 let x = self.foo();
328 } 326 }
329 } 327}"#,
330 "#,
331 expect![[r#" 328 expect![[r#"
332 26..30 'self': &Self 329 26..30 'self': &Self
333 52..56 'self': &Self 330 52..56 'self': &Self
@@ -343,15 +340,14 @@ fn trait_default_method_self_bound_implements_trait() {
343fn trait_default_method_self_bound_implements_super_trait() { 340fn trait_default_method_self_bound_implements_super_trait() {
344 check_infer( 341 check_infer(
345 r#" 342 r#"
346 trait SuperTrait { 343trait SuperTrait {
347 fn foo(&self) -> i64; 344 fn foo(&self) -> i64;
348 } 345}
349 trait Trait: SuperTrait { 346trait Trait: SuperTrait {
350 fn bar(&self) -> { 347 fn bar(&self) -> {
351 let x = self.foo(); 348 let x = self.foo();
352 } 349 }
353 } 350}"#,
354 "#,
355 expect![[r#" 351 expect![[r#"
356 31..35 'self': &Self 352 31..35 'self': &Self
357 85..89 'self': &Self 353 85..89 'self': &Self
@@ -367,18 +363,17 @@ fn trait_default_method_self_bound_implements_super_trait() {
367fn infer_project_associated_type() { 363fn infer_project_associated_type() {
368 check_infer( 364 check_infer(
369 r#" 365 r#"
370 trait Iterable { 366trait Iterable {
371 type Item; 367 type Item;
372 } 368}
373 struct S; 369struct S;
374 impl Iterable for S { type Item = u32; } 370impl Iterable for S { type Item = u32; }
375 fn test<T: Iterable>() { 371fn test<T: Iterable>() {
376 let x: <S as Iterable>::Item = 1; 372 let x: <S as Iterable>::Item = 1;
377 let y: <T as Iterable>::Item = no_matter; 373 let y: <T as Iterable>::Item = no_matter;
378 let z: T::Item = no_matter; 374 let z: T::Item = no_matter;
379 let a: <T>::Item = no_matter; 375 let a: <T>::Item = no_matter;
380 } 376}"#,
381 "#,
382 expect![[r#" 377 expect![[r#"
383 108..261 '{ ...ter; }': () 378 108..261 '{ ...ter; }': ()
384 118..119 'x': u32 379 118..119 'x': u32
@@ -397,20 +392,19 @@ fn infer_project_associated_type() {
397fn infer_return_associated_type() { 392fn infer_return_associated_type() {
398 check_infer( 393 check_infer(
399 r#" 394 r#"
400 trait Iterable { 395trait Iterable {
401 type Item; 396 type Item;
402 } 397}
403 struct S; 398struct S;
404 impl Iterable for S { type Item = u32; } 399impl Iterable for S { type Item = u32; }
405 fn foo1<T: Iterable>(t: T) -> T::Item {} 400fn foo1<T: Iterable>(t: T) -> T::Item {}
406 fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item {} 401fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item {}
407 fn foo3<T: Iterable>(t: T) -> <T>::Item {} 402fn foo3<T: Iterable>(t: T) -> <T>::Item {}
408 fn test() { 403fn test() {
409 let x = foo1(S); 404 let x = foo1(S);
410 let y = foo2(S); 405 let y = foo2(S);
411 let z = foo3(S); 406 let z = foo3(S);
412 } 407}"#,
413 "#,
414 expect![[r#" 408 expect![[r#"
415 106..107 't': T 409 106..107 't': T
416 123..125 '{}': () 410 123..125 '{}': ()
@@ -439,13 +433,12 @@ fn infer_return_associated_type() {
439fn infer_associated_type_bound() { 433fn infer_associated_type_bound() {
440 check_infer( 434 check_infer(
441 r#" 435 r#"
442 trait Iterable { 436trait Iterable {
443 type Item; 437 type Item;
444 } 438}
445 fn test<T: Iterable<Item=u32>>() { 439fn test<T: Iterable<Item=u32>>() {
446 let y: T::Item = unknown; 440 let y: T::Item = unknown;
447 } 441}"#,
448 "#,
449 expect![[r#" 442 expect![[r#"
450 67..100 '{ ...own; }': () 443 67..100 '{ ...own; }': ()
451 77..78 'y': u32 444 77..78 'y': u32
@@ -458,9 +451,8 @@ fn infer_associated_type_bound() {
458fn infer_const_body() { 451fn infer_const_body() {
459 check_infer( 452 check_infer(
460 r#" 453 r#"
461 const A: u32 = 1 + 1; 454const A: u32 = 1 + 1;
462 static B: u64 = { let x = 1; x }; 455static B: u64 = { let x = 1; x };"#,
463 "#,
464 expect![[r#" 456 expect![[r#"
465 15..16 '1': u32 457 15..16 '1': u32
466 15..20 '1 + 1': u32 458 15..20 '1 + 1': u32
@@ -477,13 +469,12 @@ fn infer_const_body() {
477fn tuple_struct_fields() { 469fn tuple_struct_fields() {
478 check_infer( 470 check_infer(
479 r#" 471 r#"
480 struct S(i32, u64); 472struct S(i32, u64);
481 fn test() -> u64 { 473fn test() -> u64 {
482 let a = S(4, 6); 474 let a = S(4, 6);
483 let b = a.0; 475 let b = a.0;
484 a.1 476 a.1
485 } 477}"#,
486 "#,
487 expect![[r#" 478 expect![[r#"
488 37..86 '{ ... a.1 }': u64 479 37..86 '{ ... a.1 }': u64
489 47..48 'a': S 480 47..48 'a': S
@@ -504,13 +495,12 @@ fn tuple_struct_fields() {
504fn tuple_struct_with_fn() { 495fn tuple_struct_with_fn() {
505 check_infer( 496 check_infer(
506 r#" 497 r#"
507 struct S(fn(u32) -> u64); 498struct S(fn(u32) -> u64);
508 fn test() -> u64 { 499fn test() -> u64 {
509 let a = S(|i| 2*i); 500 let a = S(|i| 2*i);
510 let b = a.0(4); 501 let b = a.0(4);
511 a.0(2) 502 a.0(2)
512 } 503}"#,
513 "#,
514 expect![[r#" 504 expect![[r#"
515 43..101 '{ ...0(2) }': u64 505 43..101 '{ ...0(2) }': u64
516 53..54 'a': S 506 53..54 'a': S
@@ -949,27 +939,26 @@ fn test<T: ApplyL>(t: T) {
949fn argument_impl_trait() { 939fn argument_impl_trait() {
950 check_infer_with_mismatches( 940 check_infer_with_mismatches(
951 r#" 941 r#"
952 trait Trait<T> { 942trait Trait<T> {
953 fn foo(&self) -> T; 943 fn foo(&self) -> T;
954 fn foo2(&self) -> i64; 944 fn foo2(&self) -> i64;
955 } 945}
956 fn bar(x: impl Trait<u16>) {} 946fn bar(x: impl Trait<u16>) {}
957 struct S<T>(T); 947struct S<T>(T);
958 impl<T> Trait<T> for S<T> {} 948impl<T> Trait<T> for S<T> {}
959 949
960 fn test(x: impl Trait<u64>, y: &impl Trait<u32>) { 950fn test(x: impl Trait<u64>, y: &impl Trait<u32>) {
961 x; 951 x;
962 y; 952 y;
963 let z = S(1); 953 let z = S(1);
964 bar(z); 954 bar(z);
965 x.foo(); 955 x.foo();
966 y.foo(); 956 y.foo();
967 z.foo(); 957 z.foo();
968 x.foo2(); 958 x.foo2();
969 y.foo2(); 959 y.foo2();
970 z.foo2(); 960 z.foo2();
971 } 961}"#,
972 "#,
973 expect![[r#" 962 expect![[r#"
974 29..33 'self': &Self 963 29..33 'self': &Self
975 54..58 'self': &Self 964 54..58 'self': &Self
@@ -1007,30 +996,29 @@ fn argument_impl_trait() {
1007fn argument_impl_trait_type_args_1() { 996fn argument_impl_trait_type_args_1() {
1008 check_infer_with_mismatches( 997 check_infer_with_mismatches(
1009 r#" 998 r#"
1010 trait Trait {} 999trait Trait {}
1011 trait Foo { 1000trait Foo {
1012 // this function has an implicit Self param, an explicit type param, 1001 // this function has an implicit Self param, an explicit type param,
1013 // and an implicit impl Trait param! 1002 // and an implicit impl Trait param!
1014 fn bar<T>(x: impl Trait) -> T { loop {} } 1003 fn bar<T>(x: impl Trait) -> T { loop {} }
1015 } 1004}
1016 fn foo<T>(x: impl Trait) -> T { loop {} } 1005fn foo<T>(x: impl Trait) -> T { loop {} }
1017 struct S; 1006struct S;
1018 impl Trait for S {} 1007impl Trait for S {}
1019 struct F; 1008struct F;
1020 impl Foo for F {} 1009impl Foo for F {}
1021 1010
1022 fn test() { 1011fn test() {
1023 Foo::bar(S); 1012 Foo::bar(S);
1024 <F as Foo>::bar(S); 1013 <F as Foo>::bar(S);
1025 F::bar(S); 1014 F::bar(S);
1026 Foo::bar::<u32>(S); 1015 Foo::bar::<u32>(S);
1027 <F as Foo>::bar::<u32>(S); 1016 <F as Foo>::bar::<u32>(S);
1028 1017
1029 foo(S); 1018 foo(S);
1030 foo::<u32>(S); 1019 foo::<u32>(S);
1031 foo::<u32, i32>(S); // we should ignore the extraneous i32 1020 foo::<u32, i32>(S); // we should ignore the extraneous i32
1032 } 1021}"#,
1033 "#,
1034 expect![[r#" 1022 expect![[r#"
1035 155..156 'x': impl Trait 1023 155..156 'x': impl Trait
1036 175..186 '{ loop {} }': T 1024 175..186 '{ loop {} }': T
@@ -1073,21 +1061,20 @@ fn argument_impl_trait_type_args_1() {
1073fn argument_impl_trait_type_args_2() { 1061fn argument_impl_trait_type_args_2() {
1074 check_infer_with_mismatches( 1062 check_infer_with_mismatches(
1075 r#" 1063 r#"
1076 trait Trait {} 1064trait Trait {}
1077 struct S; 1065struct S;
1078 impl Trait for S {} 1066impl Trait for S {}
1079 struct F<T>; 1067struct F<T>;
1080 impl<T> F<T> { 1068impl<T> F<T> {
1081 fn foo<U>(self, x: impl Trait) -> (T, U) { loop {} } 1069 fn foo<U>(self, x: impl Trait) -> (T, U) { loop {} }
1082 } 1070}
1083 1071
1084 fn test() { 1072fn test() {
1085 F.foo(S); 1073 F.foo(S);
1086 F::<u32>.foo(S); 1074 F::<u32>.foo(S);
1087 F::<u32>.foo::<i32>(S); 1075 F::<u32>.foo::<i32>(S);
1088 F::<u32>.foo::<i32, u32>(S); // extraneous argument should be ignored 1076 F::<u32>.foo::<i32, u32>(S); // extraneous argument should be ignored
1089 } 1077}"#,
1090 "#,
1091 expect![[r#" 1078 expect![[r#"
1092 87..91 'self': F<T> 1079 87..91 'self': F<T>
1093 93..94 'x': impl Trait 1080 93..94 'x': impl Trait
@@ -1115,15 +1102,14 @@ fn argument_impl_trait_type_args_2() {
1115fn argument_impl_trait_to_fn_pointer() { 1102fn argument_impl_trait_to_fn_pointer() {
1116 check_infer_with_mismatches( 1103 check_infer_with_mismatches(
1117 r#" 1104 r#"
1118 trait Trait {} 1105trait Trait {}
1119 fn foo(x: impl Trait) { loop {} } 1106fn foo(x: impl Trait) { loop {} }
1120 struct S; 1107struct S;
1121 impl Trait for S {} 1108impl Trait for S {}
1122 1109
1123 fn test() { 1110fn test() {
1124 let f: fn(S) -> () = foo; 1111 let f: fn(S) -> () = foo;
1125 } 1112}"#,
1126 "#,
1127 expect![[r#" 1113 expect![[r#"
1128 22..23 'x': impl Trait 1114 22..23 'x': impl Trait
1129 37..48 '{ loop {} }': () 1115 37..48 '{ loop {} }': ()
@@ -1140,24 +1126,23 @@ fn argument_impl_trait_to_fn_pointer() {
1140fn impl_trait() { 1126fn impl_trait() {
1141 check_infer( 1127 check_infer(
1142 r#" 1128 r#"
1143 trait Trait<T> { 1129trait Trait<T> {
1144 fn foo(&self) -> T; 1130 fn foo(&self) -> T;
1145 fn foo2(&self) -> i64; 1131 fn foo2(&self) -> i64;
1146 } 1132}
1147 fn bar() -> impl Trait<u64> {} 1133fn bar() -> impl Trait<u64> {}
1148 1134
1149 fn test(x: impl Trait<u64>, y: &impl Trait<u64>) { 1135fn test(x: impl Trait<u64>, y: &impl Trait<u64>) {
1150 x; 1136 x;
1151 y; 1137 y;
1152 let z = bar(); 1138 let z = bar();
1153 x.foo(); 1139 x.foo();
1154 y.foo(); 1140 y.foo();
1155 z.foo(); 1141 z.foo();
1156 x.foo2(); 1142 x.foo2();
1157 y.foo2(); 1143 y.foo2();
1158 z.foo2(); 1144 z.foo2();
1159 } 1145}"#,
1160 "#,
1161 expect![[r#" 1146 expect![[r#"
1162 29..33 'self': &Self 1147 29..33 'self': &Self
1163 54..58 'self': &Self 1148 54..58 'self': &Self
@@ -1191,16 +1176,15 @@ fn simple_return_pos_impl_trait() {
1191 cov_mark::check!(lower_rpit); 1176 cov_mark::check!(lower_rpit);
1192 check_infer( 1177 check_infer(
1193 r#" 1178 r#"
1194 trait Trait<T> { 1179trait Trait<T> {
1195 fn foo(&self) -> T; 1180 fn foo(&self) -> T;
1196 } 1181}
1197 fn bar() -> impl Trait<u64> { loop {} } 1182fn bar() -> impl Trait<u64> { loop {} }
1198 1183
1199 fn test() { 1184fn test() {
1200 let a = bar(); 1185 let a = bar();
1201 a.foo(); 1186 a.foo();
1202 } 1187}"#,
1203 "#,
1204 expect![[r#" 1188 expect![[r#"
1205 29..33 'self': &Self 1189 29..33 'self': &Self
1206 71..82 '{ loop {} }': ! 1190 71..82 '{ loop {} }': !
@@ -1220,25 +1204,24 @@ fn simple_return_pos_impl_trait() {
1220fn more_return_pos_impl_trait() { 1204fn more_return_pos_impl_trait() {
1221 check_infer( 1205 check_infer(
1222 r#" 1206 r#"
1223 trait Iterator { 1207trait Iterator {
1224 type Item; 1208 type Item;
1225 fn next(&mut self) -> Self::Item; 1209 fn next(&mut self) -> Self::Item;
1226 } 1210}
1227 trait Trait<T> { 1211trait Trait<T> {
1228 fn foo(&self) -> T; 1212 fn foo(&self) -> T;
1229 } 1213}
1230 fn bar() -> (impl Iterator<Item = impl Trait<u32>>, impl Trait<u64>) { loop {} } 1214fn bar() -> (impl Iterator<Item = impl Trait<u32>>, impl Trait<u64>) { loop {} }
1231 fn baz<T>(t: T) -> (impl Iterator<Item = impl Trait<T>>, impl Trait<T>) { loop {} } 1215fn baz<T>(t: T) -> (impl Iterator<Item = impl Trait<T>>, impl Trait<T>) { loop {} }
1232 1216
1233 fn test() { 1217fn test() {
1234 let (a, b) = bar(); 1218 let (a, b) = bar();
1235 a.next().foo(); 1219 a.next().foo();
1236 b.foo(); 1220 b.foo();
1237 let (c, d) = baz(1u128); 1221 let (c, d) = baz(1u128);
1238 c.next().foo(); 1222 c.next().foo();
1239 d.foo(); 1223 d.foo();
1240 } 1224}"#,
1241 "#,
1242 expect![[r#" 1225 expect![[r#"
1243 49..53 'self': &mut Self 1226 49..53 'self': &mut Self
1244 101..105 'self': &Self 1227 101..105 'self': &Self
@@ -1279,24 +1262,23 @@ fn more_return_pos_impl_trait() {
1279fn dyn_trait() { 1262fn dyn_trait() {
1280 check_infer( 1263 check_infer(
1281 r#" 1264 r#"
1282 trait Trait<T> { 1265trait Trait<T> {
1283 fn foo(&self) -> T; 1266 fn foo(&self) -> T;
1284 fn foo2(&self) -> i64; 1267 fn foo2(&self) -> i64;
1285 } 1268}
1286 fn bar() -> dyn Trait<u64> {} 1269fn bar() -> dyn Trait<u64> {}
1287 1270
1288 fn test(x: dyn Trait<u64>, y: &dyn Trait<u64>) { 1271fn test(x: dyn Trait<u64>, y: &dyn Trait<u64>) {
1289 x; 1272 x;
1290 y; 1273 y;
1291 let z = bar(); 1274 let z = bar();
1292 x.foo(); 1275 x.foo();
1293 y.foo(); 1276 y.foo();
1294 z.foo(); 1277 z.foo();
1295 x.foo2(); 1278 x.foo2();
1296 y.foo2(); 1279 y.foo2();
1297 z.foo2(); 1280 z.foo2();
1298 } 1281}"#,
1299 "#,
1300 expect![[r#" 1282 expect![[r#"
1301 29..33 'self': &Self 1283 29..33 'self': &Self
1302 54..58 'self': &Self 1284 54..58 'self': &Self
@@ -1329,22 +1311,21 @@ fn dyn_trait() {
1329fn dyn_trait_in_impl() { 1311fn dyn_trait_in_impl() {
1330 check_infer( 1312 check_infer(
1331 r#" 1313 r#"
1332 trait Trait<T, U> { 1314trait Trait<T, U> {
1333 fn foo(&self) -> (T, U); 1315 fn foo(&self) -> (T, U);
1334 } 1316}
1335 struct S<T, U> {} 1317struct S<T, U> {}
1336 impl<T, U> S<T, U> { 1318impl<T, U> S<T, U> {
1337 fn bar(&self) -> &dyn Trait<T, U> { loop {} } 1319 fn bar(&self) -> &dyn Trait<T, U> { loop {} }
1338 } 1320}
1339 trait Trait2<T, U> { 1321trait Trait2<T, U> {
1340 fn baz(&self) -> (T, U); 1322 fn baz(&self) -> (T, U);
1341 } 1323}
1342 impl<T, U> Trait2<T, U> for dyn Trait<T, U> { } 1324impl<T, U> Trait2<T, U> for dyn Trait<T, U> { }
1343 1325
1344 fn test(s: S<u32, i32>) { 1326fn test(s: S<u32, i32>) {
1345 s.bar().baz(); 1327 s.bar().baz();
1346 } 1328}"#,
1347 "#,
1348 expect![[r#" 1329 expect![[r#"
1349 32..36 'self': &Self 1330 32..36 'self': &Self
1350 102..106 'self': &S<T, U> 1331 102..106 'self': &S<T, U>
@@ -1365,20 +1346,19 @@ fn dyn_trait_in_impl() {
1365fn dyn_trait_bare() { 1346fn dyn_trait_bare() {
1366 check_infer( 1347 check_infer(
1367 r#" 1348 r#"
1368 trait Trait { 1349trait Trait {
1369 fn foo(&self) -> u64; 1350 fn foo(&self) -> u64;
1370 } 1351}
1371 fn bar() -> Trait {} 1352fn bar() -> Trait {}
1372 1353
1373 fn test(x: Trait, y: &Trait) -> u64 { 1354fn test(x: Trait, y: &Trait) -> u64 {
1374 x; 1355 x;
1375 y; 1356 y;
1376 let z = bar(); 1357 let z = bar();
1377 x.foo(); 1358 x.foo();
1378 y.foo(); 1359 y.foo();
1379 z.foo(); 1360 z.foo();
1380 } 1361}"#,
1381 "#,
1382 expect![[r#" 1362 expect![[r#"
1383 26..30 'self': &Self 1363 26..30 'self': &Self
1384 60..62 '{}': () 1364 60..62 '{}': ()
@@ -1404,17 +1384,24 @@ fn dyn_trait_bare() {
1404fn weird_bounds() { 1384fn weird_bounds() {
1405 check_infer( 1385 check_infer(
1406 r#" 1386 r#"
1407 trait Trait {} 1387trait Trait {}
1408 fn test(a: impl Trait + 'lifetime, b: impl 'lifetime, c: impl (Trait), d: impl ('lifetime), e: impl ?Sized, f: impl Trait + ?Sized) {} 1388fn test(
1409 "#, 1389 a: impl Trait + 'lifetime,
1390 b: impl 'lifetime,
1391 c: impl (Trait),
1392 d: impl ('lifetime),
1393 e: impl ?Sized,
1394 f: impl Trait + ?Sized
1395) {}
1396"#,
1410 expect![[r#" 1397 expect![[r#"
1411 23..24 'a': impl Trait 1398 28..29 'a': impl Trait
1412 50..51 'b': impl 1399 59..60 'b': impl
1413 69..70 'c': impl Trait 1400 82..83 'c': impl Trait
1414 86..87 'd': impl 1401 103..104 'd': impl
1415 107..108 'e': impl 1402 128..129 'e': impl
1416 123..124 'f': impl Trait 1403 148..149 'f': impl Trait
1417 147..149 '{}': () 1404 173..175 '{}': ()
1418 "#]], 1405 "#]],
1419 ); 1406 );
1420} 1407}
@@ -1439,27 +1426,26 @@ fn test(x: (impl Trait + UnknownTrait)) {
1439fn assoc_type_bindings() { 1426fn assoc_type_bindings() {
1440 check_infer( 1427 check_infer(
1441 r#" 1428 r#"
1442 trait Trait { 1429trait Trait {
1443 type Type; 1430 type Type;
1444 } 1431}
1445 1432
1446 fn get<T: Trait>(t: T) -> <T as Trait>::Type {} 1433fn get<T: Trait>(t: T) -> <T as Trait>::Type {}
1447 fn get2<U, T: Trait<Type = U>>(t: T) -> U {} 1434fn get2<U, T: Trait<Type = U>>(t: T) -> U {}
1448 fn set<T: Trait<Type = u64>>(t: T) -> T {t} 1435fn set<T: Trait<Type = u64>>(t: T) -> T {t}
1449 1436
1450 struct S<T>; 1437struct S<T>;
1451 impl<T> Trait for S<T> { type Type = T; } 1438impl<T> Trait for S<T> { type Type = T; }
1452 1439
1453 fn test<T: Trait<Type = u32>>(x: T, y: impl Trait<Type = i64>) { 1440fn test<T: Trait<Type = u32>>(x: T, y: impl Trait<Type = i64>) {
1454 get(x); 1441 get(x);
1455 get2(x); 1442 get2(x);
1456 get(y); 1443 get(y);
1457 get2(y); 1444 get2(y);
1458 get(set(S)); 1445 get(set(S));
1459 get2(set(S)); 1446 get2(set(S));
1460 get2(S::<str>); 1447 get2(S::<str>);
1461 } 1448}"#,
1462 "#,
1463 expect![[r#" 1449 expect![[r#"
1464 49..50 't': T 1450 49..50 't': T
1465 77..79 '{}': () 1451 77..79 '{}': ()
@@ -1546,18 +1532,17 @@ mod iter {
1546fn projection_eq_within_chalk() { 1532fn projection_eq_within_chalk() {
1547 check_infer( 1533 check_infer(
1548 r#" 1534 r#"
1549 trait Trait1 { 1535trait Trait1 {
1550 type Type; 1536 type Type;
1551 } 1537}
1552 trait Trait2<T> { 1538trait Trait2<T> {
1553 fn foo(self) -> T; 1539 fn foo(self) -> T;
1554 } 1540}
1555 impl<T, U> Trait2<T> for U where U: Trait1<Type = T> {} 1541impl<T, U> Trait2<T> for U where U: Trait1<Type = T> {}
1556 1542
1557 fn test<T: Trait1<Type = u32>>(x: T) { 1543fn test<T: Trait1<Type = u32>>(x: T) {
1558 x.foo(); 1544 x.foo();
1559 } 1545}"#,
1560 "#,
1561 expect![[r#" 1546 expect![[r#"
1562 61..65 'self': Self 1547 61..65 'self': Self
1563 163..164 'x': T 1548 163..164 'x': T
@@ -1589,19 +1574,18 @@ fn test<T: foo::Trait>(x: T) {
1589fn super_trait_method_resolution() { 1574fn super_trait_method_resolution() {
1590 check_infer( 1575 check_infer(
1591 r#" 1576 r#"
1592 mod foo { 1577mod foo {
1593 trait SuperTrait { 1578 trait SuperTrait {
1594 fn foo(&self) -> u32 {} 1579 fn foo(&self) -> u32 {}
1595 } 1580 }
1596 } 1581}
1597 trait Trait1: foo::SuperTrait {} 1582trait Trait1: foo::SuperTrait {}
1598 trait Trait2 where Self: foo::SuperTrait {} 1583trait Trait2 where Self: foo::SuperTrait {}
1599 1584
1600 fn test<T: Trait1, U: Trait2>(x: T, y: U) { 1585fn test<T: Trait1, U: Trait2>(x: T, y: U) {
1601 x.foo(); 1586 x.foo();
1602 y.foo(); 1587 y.foo();
1603 } 1588}"#,
1604 "#,
1605 expect![[r#" 1589 expect![[r#"
1606 49..53 'self': &Self 1590 49..53 'self': &Self
1607 62..64 '{}': () 1591 62..64 '{}': ()
@@ -1620,17 +1604,16 @@ fn super_trait_method_resolution() {
1620fn super_trait_impl_trait_method_resolution() { 1604fn super_trait_impl_trait_method_resolution() {
1621 check_infer( 1605 check_infer(
1622 r#" 1606 r#"
1623 mod foo { 1607mod foo {
1624 trait SuperTrait { 1608 trait SuperTrait {
1625 fn foo(&self) -> u32 {} 1609 fn foo(&self) -> u32 {}
1626 } 1610 }
1627 } 1611}
1628 trait Trait1: foo::SuperTrait {} 1612trait Trait1: foo::SuperTrait {}
1629 1613
1630 fn test(x: &impl Trait1) { 1614fn test(x: &impl Trait1) {
1631 x.foo(); 1615 x.foo();
1632 } 1616}"#,
1633 "#,
1634 expect![[r#" 1617 expect![[r#"
1635 49..53 'self': &Self 1618 49..53 'self': &Self
1636 62..64 '{}': () 1619 62..64 '{}': ()
@@ -1667,20 +1650,19 @@ fn super_trait_cycle() {
1667fn super_trait_assoc_type_bounds() { 1650fn super_trait_assoc_type_bounds() {
1668 check_infer( 1651 check_infer(
1669 r#" 1652 r#"
1670 trait SuperTrait { type Type; } 1653trait SuperTrait { type Type; }
1671 trait Trait where Self: SuperTrait {} 1654trait Trait where Self: SuperTrait {}
1672 1655
1673 fn get2<U, T: Trait<Type = U>>(t: T) -> U {} 1656fn get2<U, T: Trait<Type = U>>(t: T) -> U {}
1674 fn set<T: Trait<Type = u64>>(t: T) -> T {t} 1657fn set<T: Trait<Type = u64>>(t: T) -> T {t}
1675 1658
1676 struct S<T>; 1659struct S<T>;
1677 impl<T> SuperTrait for S<T> { type Type = T; } 1660impl<T> SuperTrait for S<T> { type Type = T; }
1678 impl<T> Trait for S<T> {} 1661impl<T> Trait for S<T> {}
1679 1662
1680 fn test() { 1663fn test() {
1681 get2(set(S)); 1664 get2(set(S));
1682 } 1665}"#,
1683 "#,
1684 expect![[r#" 1666 expect![[r#"
1685 102..103 't': T 1667 102..103 't': T
1686 113..115 '{}': () 1668 113..115 '{}': ()
@@ -1701,16 +1683,15 @@ fn super_trait_assoc_type_bounds() {
1701fn fn_trait() { 1683fn fn_trait() {
1702 check_infer_with_mismatches( 1684 check_infer_with_mismatches(
1703 r#" 1685 r#"
1704 trait FnOnce<Args> { 1686trait FnOnce<Args> {
1705 type Output; 1687 type Output;
1706 1688
1707 fn call_once(self, args: Args) -> <Self as FnOnce<Args>>::Output; 1689 fn call_once(self, args: Args) -> <Self as FnOnce<Args>>::Output;
1708 } 1690}
1709 1691
1710 fn test<F: FnOnce(u32, u64) -> u128>(f: F) { 1692fn test<F: FnOnce(u32, u64) -> u128>(f: F) {
1711 f.call_once((1, 2)); 1693 f.call_once((1, 2));
1712 } 1694}"#,
1713 "#,
1714 expect![[r#" 1695 expect![[r#"
1715 56..60 'self': Self 1696 56..60 'self': Self
1716 62..66 'args': Args 1697 62..66 'args': Args
@@ -1729,37 +1710,36 @@ fn fn_trait() {
1729fn fn_ptr_and_item() { 1710fn fn_ptr_and_item() {
1730 check_infer_with_mismatches( 1711 check_infer_with_mismatches(
1731 r#" 1712 r#"
1732 #[lang="fn_once"] 1713#[lang="fn_once"]
1733 trait FnOnce<Args> { 1714trait FnOnce<Args> {
1734 type Output; 1715 type Output;
1735 1716
1736 fn call_once(self, args: Args) -> Self::Output; 1717 fn call_once(self, args: Args) -> Self::Output;
1737 } 1718}
1738 1719
1739 trait Foo<T> { 1720trait Foo<T> {
1740 fn foo(&self) -> T; 1721 fn foo(&self) -> T;
1741 } 1722}
1742 1723
1743 struct Bar<T>(T); 1724struct Bar<T>(T);
1744 1725
1745 impl<A1, R, F: FnOnce(A1) -> R> Foo<(A1, R)> for Bar<F> { 1726impl<A1, R, F: FnOnce(A1) -> R> Foo<(A1, R)> for Bar<F> {
1746 fn foo(&self) -> (A1, R) { loop {} } 1727 fn foo(&self) -> (A1, R) { loop {} }
1747 } 1728}
1748 1729
1749 enum Opt<T> { None, Some(T) } 1730enum Opt<T> { None, Some(T) }
1750 impl<T> Opt<T> { 1731impl<T> Opt<T> {
1751 fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Opt<U> { loop {} } 1732 fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Opt<U> { loop {} }
1752 } 1733}
1753 1734
1754 fn test() { 1735fn test() {
1755 let bar: Bar<fn(u8) -> u32>; 1736 let bar: Bar<fn(u8) -> u32>;
1756 bar.foo(); 1737 bar.foo();
1757 1738
1758 let opt: Opt<u8>; 1739 let opt: Opt<u8>;
1759 let f: fn(u8) -> u32; 1740 let f: fn(u8) -> u32;
1760 opt.map(f); 1741 opt.map(f);
1761 } 1742}"#,
1762 "#,
1763 expect![[r#" 1743 expect![[r#"
1764 74..78 'self': Self 1744 74..78 'self': Self
1765 80..84 'args': Args 1745 80..84 'args': Args
@@ -1790,46 +1770,45 @@ fn fn_ptr_and_item() {
1790fn fn_trait_deref_with_ty_default() { 1770fn fn_trait_deref_with_ty_default() {
1791 check_infer( 1771 check_infer(
1792 r#" 1772 r#"
1793 #[lang = "deref"] 1773#[lang = "deref"]
1794 trait Deref { 1774trait Deref {
1795 type Target; 1775 type Target;
1796 1776
1797 fn deref(&self) -> &Self::Target; 1777 fn deref(&self) -> &Self::Target;
1798 } 1778}
1799 1779
1800 #[lang="fn_once"] 1780#[lang="fn_once"]
1801 trait FnOnce<Args> { 1781trait FnOnce<Args> {
1802 type Output; 1782 type Output;
1803 1783
1804 fn call_once(self, args: Args) -> Self::Output; 1784 fn call_once(self, args: Args) -> Self::Output;
1805 } 1785}
1806 1786
1807 struct Foo; 1787struct Foo;
1808 1788
1809 impl Foo { 1789impl Foo {
1810 fn foo(&self) -> usize {} 1790 fn foo(&self) -> usize {}
1811 } 1791}
1812 1792
1813 struct Lazy<T, F = fn() -> T>(F); 1793struct Lazy<T, F = fn() -> T>(F);
1814 1794
1815 impl<T, F> Lazy<T, F> { 1795impl<T, F> Lazy<T, F> {
1816 pub fn new(f: F) -> Lazy<T, F> {} 1796 pub fn new(f: F) -> Lazy<T, F> {}
1817 } 1797}
1818 1798
1819 impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> { 1799impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
1820 type Target = T; 1800 type Target = T;
1821 } 1801}
1822 1802
1823 fn test() { 1803fn test() {
1824 let lazy1: Lazy<Foo, _> = Lazy::new(|| Foo); 1804 let lazy1: Lazy<Foo, _> = Lazy::new(|| Foo);
1825 let r1 = lazy1.foo(); 1805 let r1 = lazy1.foo();
1826 1806
1827 fn make_foo_fn() -> Foo {} 1807 fn make_foo_fn() -> Foo {}
1828 let make_foo_fn_ptr: fn() -> Foo = make_foo_fn; 1808 let make_foo_fn_ptr: fn() -> Foo = make_foo_fn;
1829 let lazy2: Lazy<Foo, _> = Lazy::new(make_foo_fn_ptr); 1809 let lazy2: Lazy<Foo, _> = Lazy::new(make_foo_fn_ptr);
1830 let r2 = lazy2.foo(); 1810 let r2 = lazy2.foo();
1831 } 1811}"#,
1832 "#,
1833 expect![[r#" 1812 expect![[r#"
1834 64..68 'self': &Self 1813 64..68 'self': &Self
1835 165..169 'self': Self 1814 165..169 'self': Self
@@ -1865,23 +1844,22 @@ fn fn_trait_deref_with_ty_default() {
1865fn closure_1() { 1844fn closure_1() {
1866 check_infer_with_mismatches( 1845 check_infer_with_mismatches(
1867 r#" 1846 r#"
1868 #[lang = "fn_once"] 1847#[lang = "fn_once"]
1869 trait FnOnce<Args> { 1848trait FnOnce<Args> {
1870 type Output; 1849 type Output;
1871 } 1850}
1872 1851
1873 enum Option<T> { Some(T), None } 1852enum Option<T> { Some(T), None }
1874 impl<T> Option<T> { 1853impl<T> Option<T> {
1875 fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> { loop {} } 1854 fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> { loop {} }
1876 } 1855}
1877 1856
1878 fn test() { 1857fn test() {
1879 let x = Option::Some(1u32); 1858 let x = Option::Some(1u32);
1880 x.map(|v| v + 1); 1859 x.map(|v| v + 1);
1881 x.map(|_v| 1u64); 1860 x.map(|_v| 1u64);
1882 let y: Option<i64> = x.map(|_v| 1); 1861 let y: Option<i64> = x.map(|_v| 1);
1883 } 1862}"#,
1884 "#,
1885 expect![[r#" 1863 expect![[r#"
1886 147..151 'self': Option<T> 1864 147..151 'self': Option<T>
1887 153..154 'f': F 1865 153..154 'f': F
@@ -1919,38 +1897,63 @@ fn closure_1() {
1919fn closure_2() { 1897fn closure_2() {
1920 check_infer_with_mismatches( 1898 check_infer_with_mismatches(
1921 r#" 1899 r#"
1922 trait FnOnce<Args> { 1900#[lang = "add"]
1923 type Output; 1901pub trait Add<Rhs = Self> {
1924 } 1902 type Output;
1903 fn add(self, rhs: Rhs) -> Self::Output;
1904}
1925 1905
1926 fn test<F: FnOnce(u32) -> u64>(f: F) { 1906trait FnOnce<Args> {
1927 f(1); 1907 type Output;
1928 let g = |v| v + 1; 1908}
1929 g(1u64); 1909
1930 let h = |v| 1u128 + v; 1910impl Add for u64 {
1931 } 1911 type Output = Self;
1932 "#, 1912 fn add(self, rhs: u64) -> Self::Output {0}
1913}
1914
1915impl Add for u128 {
1916 type Output = Self;
1917 fn add(self, rhs: u128) -> Self::Output {0}
1918}
1919
1920fn test<F: FnOnce(u32) -> u64>(f: F) {
1921 f(1);
1922 let g = |v| v + 1;
1923 g(1u64);
1924 let h = |v| 1u128 + v;
1925}"#,
1933 expect![[r#" 1926 expect![[r#"
1934 72..73 'f': F 1927 72..76 'self': Self
1935 78..154 '{ ...+ v; }': () 1928 78..81 'rhs': Rhs
1936 84..85 'f': F 1929 203..207 'self': u64
1937 84..88 'f(1)': {unknown} 1930 209..212 'rhs': u64
1938 86..87 '1': i32 1931 235..238 '{0}': u64
1939 98..99 'g': |u64| -> i32 1932 236..237 '0': u64
1940 102..111 '|v| v + 1': |u64| -> i32 1933 297..301 'self': u128
1941 103..104 'v': u64 1934 303..306 'rhs': u128
1942 106..107 'v': u64 1935 330..333 '{0}': u128
1943 106..111 'v + 1': i32 1936 331..332 '0': u128
1944 110..111 '1': i32 1937 368..369 'f': F
1945 117..118 'g': |u64| -> i32 1938 374..450 '{ ...+ v; }': ()
1946 117..124 'g(1u64)': i32 1939 380..381 'f': F
1947 119..123 '1u64': u64 1940 380..384 'f(1)': {unknown}
1948 134..135 'h': |u128| -> u128 1941 382..383 '1': i32
1949 138..151 '|v| 1u128 + v': |u128| -> u128 1942 394..395 'g': |u64| -> u64
1950 139..140 'v': u128 1943 398..407 '|v| v + 1': |u64| -> u64
1951 142..147 '1u128': u128 1944 399..400 'v': u64
1952 142..151 '1u128 + v': u128 1945 402..403 'v': u64
1953 150..151 'v': u128 1946 402..407 'v + 1': u64
1947 406..407 '1': u64
1948 413..414 'g': |u64| -> u64
1949 413..420 'g(1u64)': u64
1950 415..419 '1u64': u64
1951 430..431 'h': |u128| -> u128
1952 434..447 '|v| 1u128 + v': |u128| -> u128
1953 435..436 'v': u128
1954 438..443 '1u128': u128
1955 438..447 '1u128 + v': u128
1956 446..447 'v': u128
1954 "#]], 1957 "#]],
1955 ); 1958 );
1956} 1959}
@@ -1959,29 +1962,28 @@ fn closure_2() {
1959fn closure_as_argument_inference_order() { 1962fn closure_as_argument_inference_order() {
1960 check_infer_with_mismatches( 1963 check_infer_with_mismatches(
1961 r#" 1964 r#"
1962 #[lang = "fn_once"] 1965#[lang = "fn_once"]
1963 trait FnOnce<Args> { 1966trait FnOnce<Args> {
1964 type Output; 1967 type Output;
1965 } 1968}
1966 1969
1967 fn foo1<T, U, F: FnOnce(T) -> U>(x: T, f: F) -> U { loop {} } 1970fn foo1<T, U, F: FnOnce(T) -> U>(x: T, f: F) -> U { loop {} }
1968 fn foo2<T, U, F: FnOnce(T) -> U>(f: F, x: T) -> U { loop {} } 1971fn foo2<T, U, F: FnOnce(T) -> U>(f: F, x: T) -> U { loop {} }
1969 1972
1970 struct S; 1973struct S;
1971 impl S { 1974impl S {
1972 fn method(self) -> u64; 1975 fn method(self) -> u64;
1973 1976
1974 fn foo1<T, U, F: FnOnce(T) -> U>(self, x: T, f: F) -> U { loop {} } 1977 fn foo1<T, U, F: FnOnce(T) -> U>(self, x: T, f: F) -> U { loop {} }
1975 fn foo2<T, U, F: FnOnce(T) -> U>(self, f: F, x: T) -> U { loop {} } 1978 fn foo2<T, U, F: FnOnce(T) -> U>(self, f: F, x: T) -> U { loop {} }
1976 } 1979}
1977 1980
1978 fn test() { 1981fn test() {
1979 let x1 = foo1(S, |s| s.method()); 1982 let x1 = foo1(S, |s| s.method());
1980 let x2 = foo2(|s| s.method(), S); 1983 let x2 = foo2(|s| s.method(), S);
1981 let x3 = S.foo1(S, |s| s.method()); 1984 let x3 = S.foo1(S, |s| s.method());
1982 let x4 = S.foo2(|s| s.method(), S); 1985 let x4 = S.foo2(|s| s.method(), S);
1983 } 1986}"#,
1984 "#,
1985 expect![[r#" 1987 expect![[r#"
1986 94..95 'x': T 1988 94..95 'x': T
1987 100..101 'f': F 1989 100..101 'f': F
@@ -2110,27 +2112,26 @@ fn test<T, U>() where T::Item: Trait2, T: Trait<U::Item>, U: Trait<()> {
2110fn unselected_projection_on_impl_self() { 2112fn unselected_projection_on_impl_self() {
2111 check_infer( 2113 check_infer(
2112 r#" 2114 r#"
2113 //- /main.rs 2115//- /main.rs
2114 trait Trait { 2116trait Trait {
2115 type Item; 2117 type Item;
2116 2118
2117 fn f(&self, x: Self::Item); 2119 fn f(&self, x: Self::Item);
2118 } 2120}
2119 2121
2120 struct S; 2122struct S;
2121 2123
2122 impl Trait for S { 2124impl Trait for S {
2123 type Item = u32; 2125 type Item = u32;
2124 fn f(&self, x: Self::Item) { let y = x; } 2126 fn f(&self, x: Self::Item) { let y = x; }
2125 } 2127}
2126 2128
2127 struct S2; 2129struct S2;
2128 2130
2129 impl Trait for S2 { 2131impl Trait for S2 {
2130 type Item = i32; 2132 type Item = i32;
2131 fn f(&self, x: <Self>::Item) { let y = x; } 2133 fn f(&self, x: <Self>::Item) { let y = x; }
2132 } 2134}"#,
2133 "#,
2134 expect![[r#" 2135 expect![[r#"
2135 40..44 'self': &Self 2136 40..44 'self': &Self
2136 46..47 'x': Trait::Item<Self> 2137 46..47 'x': Trait::Item<Self>
@@ -2366,58 +2367,57 @@ fn test<I: Iterator<Item: Iterator<Item = u32>>>() {
2366fn proc_macro_server_types() { 2367fn proc_macro_server_types() {
2367 check_infer( 2368 check_infer(
2368 r#" 2369 r#"
2369 macro_rules! with_api { 2370macro_rules! with_api {
2370 ($S:ident, $self:ident, $m:ident) => { 2371 ($S:ident, $self:ident, $m:ident) => {
2371 $m! { 2372 $m! {
2372 TokenStream { 2373 TokenStream {
2373 fn new() -> $S::TokenStream; 2374 fn new() -> $S::TokenStream;
2374 }, 2375 },
2375 Group { 2376 Group {
2376 }, 2377 },
2377 }
2378 };
2379 } 2378 }
2380 macro_rules! associated_item { 2379 };
2381 (type TokenStream) => 2380}
2382 (type TokenStream: 'static;); 2381macro_rules! associated_item {
2383 (type Group) => 2382 (type TokenStream) =>
2384 (type Group: 'static;); 2383 (type TokenStream: 'static;);
2385 ($($item:tt)*) => ($($item)*;) 2384 (type Group) =>
2386 } 2385 (type Group: 'static;);
2387 macro_rules! declare_server_traits { 2386 ($($item:tt)*) => ($($item)*;)
2388 ($($name:ident { 2387}
2389 $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?;)* 2388macro_rules! declare_server_traits {
2390 }),* $(,)?) => { 2389 ($($name:ident {
2391 pub trait Types { 2390 $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?;)*
2392 $(associated_item!(type $name);)* 2391 }),* $(,)?) => {
2393 } 2392 pub trait Types {
2394 2393 $(associated_item!(type $name);)*
2395 $(pub trait $name: Types {
2396 $(associated_item!(fn $method($($arg: $arg_ty),*) $(-> $ret_ty)?);)*
2397 })*
2398
2399 pub trait Server: Types $(+ $name)* {}
2400 impl<S: Types $(+ $name)*> Server for S {}
2401 }
2402 } 2394 }
2403 2395
2404 with_api!(Self, self_, declare_server_traits); 2396 $(pub trait $name: Types {
2405 struct G {} 2397 $(associated_item!(fn $method($($arg: $arg_ty),*) $(-> $ret_ty)?);)*
2406 struct T {} 2398 })*
2407 struct Rustc;
2408 impl Types for Rustc {
2409 type TokenStream = T;
2410 type Group = G;
2411 }
2412 2399
2413 fn make<T>() -> T { loop {} } 2400 pub trait Server: Types $(+ $name)* {}
2414 impl TokenStream for Rustc { 2401 impl<S: Types $(+ $name)*> Server for S {}
2415 fn new() -> Self::TokenStream { 2402 }
2416 let group: Self::Group = make(); 2403}
2417 make() 2404
2418 } 2405with_api!(Self, self_, declare_server_traits);
2419 } 2406struct G {}
2420 "#, 2407struct T {}
2408struct Rustc;
2409impl Types for Rustc {
2410 type TokenStream = T;
2411 type Group = G;
2412}
2413
2414fn make<T>() -> T { loop {} }
2415impl TokenStream for Rustc {
2416 fn new() -> Self::TokenStream {
2417 let group: Self::Group = make();
2418 make()
2419 }
2420}"#,
2421 expect![[r#" 2421 expect![[r#"
2422 1061..1072 '{ loop {} }': T 2422 1061..1072 '{ loop {} }': T
2423 1063..1070 'loop {}': ! 2423 1063..1070 'loop {}': !
@@ -2436,23 +2436,22 @@ fn proc_macro_server_types() {
2436fn unify_impl_trait() { 2436fn unify_impl_trait() {
2437 check_infer_with_mismatches( 2437 check_infer_with_mismatches(
2438 r#" 2438 r#"
2439 trait Trait<T> {} 2439trait Trait<T> {}
2440 2440
2441 fn foo(x: impl Trait<u32>) { loop {} } 2441fn foo(x: impl Trait<u32>) { loop {} }
2442 fn bar<T>(x: impl Trait<T>) -> T { loop {} } 2442fn bar<T>(x: impl Trait<T>) -> T { loop {} }
2443 2443
2444 struct S<T>(T); 2444struct S<T>(T);
2445 impl<T> Trait<T> for S<T> {} 2445impl<T> Trait<T> for S<T> {}
2446 2446
2447 fn default<T>() -> T { loop {} } 2447fn default<T>() -> T { loop {} }
2448 2448
2449 fn test() -> impl Trait<i32> { 2449fn test() -> impl Trait<i32> {
2450 let s1 = S(default()); 2450 let s1 = S(default());
2451 foo(s1); 2451 foo(s1);
2452 let x: i32 = bar(S(default())); 2452 let x: i32 = bar(S(default()));
2453 S(default()) 2453 S(default())
2454 } 2454}"#,
2455 "#,
2456 expect![[r#" 2455 expect![[r#"
2457 26..27 'x': impl Trait<u32> 2456 26..27 'x': impl Trait<u32>
2458 46..57 '{ loop {} }': () 2457 46..57 '{ loop {} }': ()
@@ -2493,30 +2492,29 @@ fn unify_impl_trait() {
2493fn assoc_types_from_bounds() { 2492fn assoc_types_from_bounds() {
2494 check_infer( 2493 check_infer(
2495 r#" 2494 r#"
2496 //- /main.rs 2495//- /main.rs
2497 #[lang = "fn_once"] 2496#[lang = "fn_once"]
2498 trait FnOnce<Args> { 2497trait FnOnce<Args> {
2499 type Output; 2498 type Output;
2500 } 2499}
2501 2500
2502 trait T { 2501trait T {
2503 type O; 2502 type O;
2504 } 2503}
2505 2504
2506 impl T for () { 2505impl T for () {
2507 type O = (); 2506 type O = ();
2508 } 2507}
2509 2508
2510 fn f<X, F>(_v: F) 2509fn f<X, F>(_v: F)
2511 where 2510where
2512 X: T, 2511 X: T,
2513 F: FnOnce(&X::O), 2512 F: FnOnce(&X::O),
2514 { } 2513{ }
2515 2514
2516 fn main() { 2515fn main() {
2517 f::<(), _>(|z| { z; }); 2516 f::<(), _>(|z| { z; });
2518 } 2517}"#,
2519 "#,
2520 expect![[r#" 2518 expect![[r#"
2521 133..135 '_v': F 2519 133..135 '_v': F
2522 178..181 '{ }': () 2520 178..181 '{ }': ()
@@ -2602,76 +2600,75 @@ fn test() {
2602fn iterator_chain() { 2600fn iterator_chain() {
2603 check_infer_with_mismatches( 2601 check_infer_with_mismatches(
2604 r#" 2602 r#"
2605 //- /main.rs 2603//- /main.rs
2606 #[lang = "fn_once"] 2604#[lang = "fn_once"]
2607 trait FnOnce<Args> { 2605trait FnOnce<Args> {
2608 type Output; 2606 type Output;
2609 } 2607}
2610 #[lang = "fn_mut"] 2608#[lang = "fn_mut"]
2611 trait FnMut<Args>: FnOnce<Args> { } 2609trait FnMut<Args>: FnOnce<Args> { }
2612 2610
2613 enum Option<T> { Some(T), None } 2611enum Option<T> { Some(T), None }
2614 use Option::*; 2612use Option::*;
2615 2613
2616 pub trait Iterator { 2614pub trait Iterator {
2617 type Item; 2615 type Item;
2618 2616
2619 fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> 2617 fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>
2620 where 2618 where
2621 F: FnMut(Self::Item) -> Option<B>, 2619 F: FnMut(Self::Item) -> Option<B>,
2622 { loop {} } 2620 { loop {} }
2623 2621
2624 fn for_each<F>(self, f: F) 2622 fn for_each<F>(self, f: F)
2625 where 2623 where
2626 F: FnMut(Self::Item), 2624 F: FnMut(Self::Item),
2627 { loop {} } 2625 { loop {} }
2628 } 2626}
2629 2627
2630 pub trait IntoIterator { 2628pub trait IntoIterator {
2631 type Item; 2629 type Item;
2632 type IntoIter: Iterator<Item = Self::Item>; 2630 type IntoIter: Iterator<Item = Self::Item>;
2633 fn into_iter(self) -> Self::IntoIter; 2631 fn into_iter(self) -> Self::IntoIter;
2634 } 2632}
2635 2633
2636 pub struct FilterMap<I, F> { } 2634pub struct FilterMap<I, F> { }
2637 impl<B, I: Iterator, F> Iterator for FilterMap<I, F> 2635impl<B, I: Iterator, F> Iterator for FilterMap<I, F>
2638 where 2636where
2639 F: FnMut(I::Item) -> Option<B>, 2637 F: FnMut(I::Item) -> Option<B>,
2640 { 2638{
2641 type Item = B; 2639 type Item = B;
2642 } 2640}
2643 2641
2644 #[stable(feature = "rust1", since = "1.0.0")] 2642#[stable(feature = "rust1", since = "1.0.0")]
2645 impl<I: Iterator> IntoIterator for I { 2643impl<I: Iterator> IntoIterator for I {
2646 type Item = I::Item; 2644 type Item = I::Item;
2647 type IntoIter = I; 2645 type IntoIter = I;
2648 2646
2649 fn into_iter(self) -> I { 2647 fn into_iter(self) -> I {
2650 self 2648 self
2651 } 2649 }
2652 } 2650}
2653 2651
2654 struct Vec<T> {} 2652struct Vec<T> {}
2655 impl<T> Vec<T> { 2653impl<T> Vec<T> {
2656 fn new() -> Self { loop {} } 2654 fn new() -> Self { loop {} }
2657 } 2655}
2658 2656
2659 impl<T> IntoIterator for Vec<T> { 2657impl<T> IntoIterator for Vec<T> {
2660 type Item = T; 2658 type Item = T;
2661 type IntoIter = IntoIter<T>; 2659 type IntoIter = IntoIter<T>;
2662 } 2660}
2663 2661
2664 pub struct IntoIter<T> { } 2662pub struct IntoIter<T> { }
2665 impl<T> Iterator for IntoIter<T> { 2663impl<T> Iterator for IntoIter<T> {
2666 type Item = T; 2664 type Item = T;
2667 } 2665}
2668 2666
2669 fn main() { 2667fn main() {
2670 Vec::<i32>::new().into_iter() 2668 Vec::<i32>::new().into_iter()
2671 .filter_map(|x| if x > 0 { Some(x as u32) } else { None }) 2669 .filter_map(|x| if x > 0 { Some(x as u32) } else { None })
2672 .for_each(|y| { y; }); 2670 .for_each(|y| { y; });
2673 } 2671}"#,
2674 "#,
2675 expect![[r#" 2672 expect![[r#"
2676 226..230 'self': Self 2673 226..230 'self': Self
2677 232..233 'f': F 2674 232..233 'f': F
@@ -2753,14 +2750,13 @@ fn main() {
2753fn trait_object_no_coercion() { 2750fn trait_object_no_coercion() {
2754 check_infer_with_mismatches( 2751 check_infer_with_mismatches(
2755 r#" 2752 r#"
2756 trait Foo {} 2753trait Foo {}
2757 2754
2758 fn foo(x: &dyn Foo) {} 2755fn foo(x: &dyn Foo) {}
2759 2756
2760 fn test(x: &dyn Foo) { 2757fn test(x: &dyn Foo) {
2761 foo(x); 2758 foo(x);
2762 } 2759}"#,
2763 "#,
2764 expect![[r#" 2760 expect![[r#"
2765 21..22 'x': &dyn Foo 2761 21..22 'x': &dyn Foo
2766 34..36 '{}': () 2762 34..36 '{}': ()
@@ -2777,23 +2773,22 @@ fn trait_object_no_coercion() {
2777fn builtin_copy() { 2773fn builtin_copy() {
2778 check_infer_with_mismatches( 2774 check_infer_with_mismatches(
2779 r#" 2775 r#"
2780 #[lang = "copy"] 2776#[lang = "copy"]
2781 trait Copy {} 2777trait Copy {}
2782 2778
2783 struct IsCopy; 2779struct IsCopy;
2784 impl Copy for IsCopy {} 2780impl Copy for IsCopy {}
2785 struct NotCopy; 2781struct NotCopy;
2786 2782
2787 trait Test { fn test(&self) -> bool; } 2783trait Test { fn test(&self) -> bool; }
2788 impl<T: Copy> Test for T {} 2784impl<T: Copy> Test for T {}
2789 2785
2790 fn test() { 2786fn test() {
2791 IsCopy.test(); 2787 IsCopy.test();
2792 NotCopy.test(); 2788 NotCopy.test();
2793 (IsCopy, IsCopy).test(); 2789 (IsCopy, IsCopy).test();
2794 (IsCopy, NotCopy).test(); 2790 (IsCopy, NotCopy).test();
2795 } 2791}"#,
2796 "#,
2797 expect![[r#" 2792 expect![[r#"
2798 110..114 'self': &Self 2793 110..114 'self': &Self
2799 166..267 '{ ...t(); }': () 2794 166..267 '{ ...t(); }': ()
@@ -2817,24 +2812,23 @@ fn builtin_copy() {
2817fn builtin_fn_def_copy() { 2812fn builtin_fn_def_copy() {
2818 check_infer_with_mismatches( 2813 check_infer_with_mismatches(
2819 r#" 2814 r#"
2820 #[lang = "copy"] 2815#[lang = "copy"]
2821 trait Copy {} 2816trait Copy {}
2822 2817
2823 fn foo() {} 2818fn foo() {}
2824 fn bar<T: Copy>(T) -> T {} 2819fn bar<T: Copy>(T) -> T {}
2825 struct Struct(usize); 2820struct Struct(usize);
2826 enum Enum { Variant(usize) } 2821enum Enum { Variant(usize) }
2827 2822
2828 trait Test { fn test(&self) -> bool; } 2823trait Test { fn test(&self) -> bool; }
2829 impl<T: Copy> Test for T {} 2824impl<T: Copy> Test for T {}
2830 2825
2831 fn test() { 2826fn test() {
2832 foo.test(); 2827 foo.test();
2833 bar.test(); 2828 bar.test();
2834 Struct.test(); 2829 Struct.test();
2835 Enum::Variant.test(); 2830 Enum::Variant.test();
2836 } 2831}"#,
2837 "#,
2838 expect![[r#" 2832 expect![[r#"
2839 41..43 '{}': () 2833 41..43 '{}': ()
2840 60..61 'T': {unknown} 2834 60..61 'T': {unknown}
@@ -2858,18 +2852,17 @@ fn builtin_fn_def_copy() {
2858fn builtin_fn_ptr_copy() { 2852fn builtin_fn_ptr_copy() {
2859 check_infer_with_mismatches( 2853 check_infer_with_mismatches(
2860 r#" 2854 r#"
2861 #[lang = "copy"] 2855#[lang = "copy"]
2862 trait Copy {} 2856trait Copy {}
2863 2857
2864 trait Test { fn test(&self) -> bool; } 2858trait Test { fn test(&self) -> bool; }
2865 impl<T: Copy> Test for T {} 2859impl<T: Copy> Test for T {}
2866 2860
2867 fn test(f1: fn(), f2: fn(usize) -> u8, f3: fn(u8, u8) -> &u8) { 2861fn test(f1: fn(), f2: fn(usize) -> u8, f3: fn(u8, u8) -> &u8) {
2868 f1.test(); 2862 f1.test();
2869 f2.test(); 2863 f2.test();
2870 f3.test(); 2864 f3.test();
2871 } 2865}"#,
2872 "#,
2873 expect![[r#" 2866 expect![[r#"
2874 54..58 'self': &Self 2867 54..58 'self': &Self
2875 108..110 'f1': fn() 2868 108..110 'f1': fn()
@@ -2890,19 +2883,18 @@ fn builtin_fn_ptr_copy() {
2890fn builtin_sized() { 2883fn builtin_sized() {
2891 check_infer_with_mismatches( 2884 check_infer_with_mismatches(
2892 r#" 2885 r#"
2893 #[lang = "sized"] 2886#[lang = "sized"]
2894 trait Sized {} 2887trait Sized {}
2895 2888
2896 trait Test { fn test(&self) -> bool; } 2889trait Test { fn test(&self) -> bool; }
2897 impl<T: Sized> Test for T {} 2890impl<T: Sized> Test for T {}
2898 2891
2899 fn test() { 2892fn test() {
2900 1u8.test(); 2893 1u8.test();
2901 (*"foo").test(); // not Sized 2894 (*"foo").test(); // not Sized
2902 (1u8, 1u8).test(); 2895 (1u8, 1u8).test();
2903 (1u8, *"foo").test(); // not Sized 2896 (1u8, *"foo").test(); // not Sized
2904 } 2897}"#,
2905 "#,
2906 expect![[r#" 2898 expect![[r#"
2907 56..60 'self': &Self 2899 56..60 'self': &Self
2908 113..228 '{ ...ized }': () 2900 113..228 '{ ...ized }': ()
@@ -2972,19 +2964,18 @@ impl<A: Step> iter::Iterator for ops::Range<A> {
2972fn infer_closure_arg() { 2964fn infer_closure_arg() {
2973 check_infer( 2965 check_infer(
2974 r#" 2966 r#"
2975 //- /lib.rs 2967//- /lib.rs
2976 2968
2977 enum Option<T> { 2969enum Option<T> {
2978 None, 2970 None,
2979 Some(T) 2971 Some(T)
2980 } 2972}
2981 2973
2982 fn foo() { 2974fn foo() {
2983 let s = Option::None; 2975 let s = Option::None;
2984 let f = |x: Option<i32>| {}; 2976 let f = |x: Option<i32>| {};
2985 (&f)(s) 2977 (&f)(s)
2986 } 2978}"#,
2987 "#,
2988 expect![[r#" 2979 expect![[r#"
2989 52..126 '{ ...)(s) }': () 2980 52..126 '{ ...)(s) }': ()
2990 62..63 's': Option<i32> 2981 62..63 's': Option<i32>
@@ -3053,46 +3044,45 @@ fn infer_box_fn_arg() {
3053 // The type mismatch is a bug 3044 // The type mismatch is a bug
3054 check_infer_with_mismatches( 3045 check_infer_with_mismatches(
3055 r#" 3046 r#"
3056 //- /lib.rs deps:std 3047//- /lib.rs deps:std
3057 3048
3058 #[lang = "fn_once"] 3049#[lang = "fn_once"]
3059 pub trait FnOnce<Args> { 3050pub trait FnOnce<Args> {
3060 type Output; 3051 type Output;
3061 3052
3062 extern "rust-call" fn call_once(self, args: Args) -> Self::Output; 3053 extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
3063 } 3054}
3064 3055
3065 #[lang = "deref"] 3056#[lang = "deref"]
3066 pub trait Deref { 3057pub trait Deref {
3067 type Target: ?Sized; 3058 type Target: ?Sized;
3068 3059
3069 fn deref(&self) -> &Self::Target; 3060 fn deref(&self) -> &Self::Target;
3070 } 3061}
3071 3062
3072 #[lang = "owned_box"] 3063#[lang = "owned_box"]
3073 pub struct Box<T: ?Sized> { 3064pub struct Box<T: ?Sized> {
3074 inner: *mut T, 3065 inner: *mut T,
3075 } 3066}
3076 3067
3077 impl<T: ?Sized> Deref for Box<T> { 3068impl<T: ?Sized> Deref for Box<T> {
3078 type Target = T; 3069 type Target = T;
3079 3070
3080 fn deref(&self) -> &T { 3071 fn deref(&self) -> &T {
3081 &self.inner 3072 &self.inner
3082 } 3073 }
3083 } 3074}
3084 3075
3085 enum Option<T> { 3076enum Option<T> {
3086 None, 3077 None,
3087 Some(T) 3078 Some(T)
3088 } 3079}
3089 3080
3090 fn foo() { 3081fn foo() {
3091 let s = Option::None; 3082 let s = Option::None;
3092 let f: Box<dyn FnOnce(&Option<i32>)> = box (|ps| {}); 3083 let f: Box<dyn FnOnce(&Option<i32>)> = box (|ps| {});
3093 f(&s); 3084 f(&s);
3094 } 3085}"#,
3095 "#,
3096 expect![[r#" 3086 expect![[r#"
3097 100..104 'self': Self 3087 100..104 'self': Self
3098 106..110 'args': Args 3088 106..110 'args': Args
@@ -3258,8 +3248,7 @@ fn f() {
3258 ().method(); 3248 ().method();
3259 //^^^^^^^^^^^ u8 3249 //^^^^^^^^^^^ u8
3260 } 3250 }
3261} 3251}"#,
3262 "#,
3263 expect![[r#" 3252 expect![[r#"
3264 46..50 'self': &Self 3253 46..50 'self': &Self
3265 58..63 '{ 0 }': u8 3254 58..63 '{ 0 }': u8
@@ -3313,8 +3302,7 @@ fn f() {
3313 fn inner() -> S { 3302 fn inner() -> S {
3314 let s = inner(); 3303 let s = inner();
3315 } 3304 }
3316} 3305}"#,
3317 "#,
3318 expect![[r#" 3306 expect![[r#"
3319 17..73 '{ ... } }': () 3307 17..73 '{ ... } }': ()
3320 39..71 '{ ... }': () 3308 39..71 '{ ... }': ()
@@ -3349,8 +3337,7 @@ fn test() {
3349 let x = A; 3337 let x = A;
3350 let y = A; 3338 let y = A;
3351 let r = x.do_op(y); 3339 let r = x.do_op(y);
3352} 3340}"#,
3353 "#,
3354 expect![[r#" 3341 expect![[r#"
3355 63..67 'self': Self 3342 63..67 'self': Self
3356 69..72 'rhs': RHS 3343 69..72 'rhs': RHS
@@ -3399,9 +3386,7 @@ impl foo::Bar for F {
3399fn foo() { 3386fn foo() {
3400 use foo::Bar; 3387 use foo::Bar;
3401 let x = <F as Bar>::boo(); 3388 let x = <F as Bar>::boo();
3402} 3389}"#,
3403
3404 "#,
3405 expect![[r#" 3390 expect![[r#"
3406 132..163 '{ ... }': Bar::Output<Self> 3391 132..163 '{ ... }': Bar::Output<Self>
3407 146..153 'loop {}': ! 3392 146..153 'loop {}': !
@@ -3413,3 +3398,79 @@ fn foo() {
3413 "#]], 3398 "#]],
3414 ); 3399 );
3415} 3400}
3401
3402#[test]
3403fn renamed_extern_crate_in_block() {
3404 check_types(
3405 r#"
3406//- /lib.rs crate:lib deps:serde
3407use serde::Deserialize;
3408
3409struct Foo {}
3410
3411const _ : () = {
3412 extern crate serde as _serde;
3413 impl _serde::Deserialize for Foo {
3414 fn deserialize() -> u8 { 0 }
3415 }
3416};
3417
3418fn foo() {
3419 Foo::deserialize();
3420 //^^^^^^^^^^^^^^^^^^ u8
3421}
3422
3423//- /serde.rs crate:serde
3424
3425pub trait Deserialize {
3426 fn deserialize() -> u8;
3427}"#,
3428 );
3429}
3430
3431#[test]
3432fn bin_op_adt_with_rhs_primitive() {
3433 check_infer_with_mismatches(
3434 r#"
3435#[lang = "add"]
3436pub trait Add<Rhs = Self> {
3437 type Output;
3438 fn add(self, rhs: Rhs) -> Self::Output;
3439}
3440
3441struct Wrapper(u32);
3442impl Add<u32> for Wrapper {
3443 type Output = Self;
3444 fn add(self, rhs: u32) -> Wrapper {
3445 Wrapper(rhs)
3446 }
3447}
3448fn main(){
3449 let wrapped = Wrapper(10);
3450 let num: u32 = 2;
3451 let res = wrapped + num;
3452
3453}"#,
3454 expect![[r#"
3455 72..76 'self': Self
3456 78..81 'rhs': Rhs
3457 192..196 'self': Wrapper
3458 198..201 'rhs': u32
3459 219..247 '{ ... }': Wrapper
3460 229..236 'Wrapper': Wrapper(u32) -> Wrapper
3461 229..241 'Wrapper(rhs)': Wrapper
3462 237..240 'rhs': u32
3463 259..345 '{ ...um; }': ()
3464 269..276 'wrapped': Wrapper
3465 279..286 'Wrapper': Wrapper(u32) -> Wrapper
3466 279..290 'Wrapper(10)': Wrapper
3467 287..289 '10': u32
3468 300..303 'num': u32
3469 311..312 '2': u32
3470 322..325 'res': Wrapper
3471 328..335 'wrapped': Wrapper
3472 328..341 'wrapped + num': Wrapper
3473 338..341 'num': u32
3474 "#]],
3475 )
3476}
diff --git a/crates/hir_ty/src/traits/chalk/tls.rs b/crates/hir_ty/src/tls.rs
index 8892a63a9..87c671a42 100644
--- a/crates/hir_ty/src/traits/chalk/tls.rs
+++ b/crates/hir_ty/src/tls.rs
@@ -4,8 +4,10 @@ use std::fmt;
4use chalk_ir::{AliasTy, GenericArg, Goal, Goals, Lifetime, ProgramClauseImplication}; 4use chalk_ir::{AliasTy, GenericArg, Goal, Goals, Lifetime, ProgramClauseImplication};
5use itertools::Itertools; 5use itertools::Itertools;
6 6
7use super::{from_chalk, Interner}; 7use crate::{
8use crate::{db::HirDatabase, from_assoc_type_id, CallableDefId}; 8 chalk_db, db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, mapping::from_chalk,
9 CallableDefId, Interner,
10};
9use hir_def::{AdtId, AssocContainerId, Lookup, TypeAliasId}; 11use hir_def::{AdtId, AssocContainerId, Lookup, TypeAliasId};
10 12
11pub(crate) use unsafe_tls::{set_current_program, with_current_program}; 13pub(crate) use unsafe_tls::{set_current_program, with_current_program};
@@ -15,7 +17,7 @@ pub(crate) struct DebugContext<'a>(&'a dyn HirDatabase);
15impl DebugContext<'_> { 17impl DebugContext<'_> {
16 pub(crate) fn debug_struct_id( 18 pub(crate) fn debug_struct_id(
17 &self, 19 &self,
18 id: super::AdtId, 20 id: chalk_db::AdtId,
19 f: &mut fmt::Formatter<'_>, 21 f: &mut fmt::Formatter<'_>,
20 ) -> Result<(), fmt::Error> { 22 ) -> Result<(), fmt::Error> {
21 let name = match id.0 { 23 let name = match id.0 {
@@ -28,17 +30,17 @@ impl DebugContext<'_> {
28 30
29 pub(crate) fn debug_trait_id( 31 pub(crate) fn debug_trait_id(
30 &self, 32 &self,
31 id: super::TraitId, 33 id: chalk_db::TraitId,
32 fmt: &mut fmt::Formatter<'_>, 34 fmt: &mut fmt::Formatter<'_>,
33 ) -> Result<(), fmt::Error> { 35 ) -> Result<(), fmt::Error> {
34 let trait_: hir_def::TraitId = from_chalk(self.0, id); 36 let trait_: hir_def::TraitId = from_chalk_trait_id(id);
35 let trait_data = self.0.trait_data(trait_); 37 let trait_data = self.0.trait_data(trait_);
36 write!(fmt, "{}", trait_data.name) 38 write!(fmt, "{}", trait_data.name)
37 } 39 }
38 40
39 pub(crate) fn debug_assoc_type_id( 41 pub(crate) fn debug_assoc_type_id(
40 &self, 42 &self,
41 id: super::AssocTypeId, 43 id: chalk_db::AssocTypeId,
42 fmt: &mut fmt::Formatter<'_>, 44 fmt: &mut fmt::Formatter<'_>,
43 ) -> Result<(), fmt::Error> { 45 ) -> Result<(), fmt::Error> {
44 let type_alias: TypeAliasId = from_assoc_type_id(id); 46 let type_alias: TypeAliasId = from_assoc_type_id(id);
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs
index c8883485c..9936d0803 100644
--- a/crates/hir_ty/src/traits.rs
+++ b/crates/hir_ty/src/traits.rs
@@ -1,28 +1,26 @@
1//! Trait solving using Chalk. 1//! Trait solving using Chalk.
2
2use std::env::var; 3use std::env::var;
3 4
4use base_db::CrateId;
5use chalk_ir::cast::Cast; 5use chalk_ir::cast::Cast;
6use chalk_solve::{logging_db::LoggingRustIrDatabase, Solver}; 6use chalk_solve::{logging_db::LoggingRustIrDatabase, Solver};
7
8use base_db::CrateId;
7use hir_def::{lang_item::LangItemTarget, TraitId}; 9use hir_def::{lang_item::LangItemTarget, TraitId};
8use stdx::panic_context; 10use stdx::panic_context;
9 11
10use crate::{ 12use crate::{
11 db::HirDatabase, AliasEq, AliasTy, Canonical, DomainGoal, Guidance, HirDisplay, InEnvironment, 13 db::HirDatabase, AliasEq, AliasTy, Canonical, DomainGoal, Guidance, HirDisplay, InEnvironment,
12 Solution, SolutionVariables, Ty, TyKind, WhereClause, 14 Interner, Solution, TraitRefExt, Ty, TyKind, WhereClause,
13}; 15};
14 16
15use self::chalk::{from_chalk, Interner, ToChalk};
16
17pub(crate) mod chalk;
18
19/// This controls how much 'time' we give the Chalk solver before giving up. 17/// This controls how much 'time' we give the Chalk solver before giving up.
20const CHALK_SOLVER_FUEL: i32 = 100; 18const CHALK_SOLVER_FUEL: i32 = 100;
21 19
22#[derive(Debug, Copy, Clone)] 20#[derive(Debug, Copy, Clone)]
23struct ChalkContext<'a> { 21pub(crate) struct ChalkContext<'a> {
24 db: &'a dyn HirDatabase, 22 pub(crate) db: &'a dyn HirDatabase,
25 krate: CrateId, 23 pub(crate) krate: CrateId,
26} 24}
27 25
28fn create_chalk_solver() -> chalk_recursive::RecursiveSolver<Interner> { 26fn create_chalk_solver() -> chalk_recursive::RecursiveSolver<Interner> {
@@ -81,6 +79,7 @@ pub(crate) fn trait_solve_query(
81 db.trait_data(it.hir_trait_id()).name.to_string() 79 db.trait_data(it.hir_trait_id()).name.to_string()
82 } 80 }
83 DomainGoal::Holds(WhereClause::AliasEq(_)) => "alias_eq".to_string(), 81 DomainGoal::Holds(WhereClause::AliasEq(_)) => "alias_eq".to_string(),
82 _ => "??".to_string(),
84 }); 83 });
85 log::info!("trait_solve_query({})", goal.value.goal.display(db)); 84 log::info!("trait_solve_query({})", goal.value.goal.display(db));
86 85
@@ -95,13 +94,12 @@ pub(crate) fn trait_solve_query(
95 } 94 }
96 } 95 }
97 96
98 let canonical = goal.to_chalk(db).cast(&Interner); 97 let canonical = goal.cast(&Interner);
99 98
100 // We currently don't deal with universes (I think / hope they're not yet 99 // We currently don't deal with universes (I think / hope they're not yet
101 // relevant for our use cases?) 100 // relevant for our use cases?)
102 let u_canonical = chalk_ir::UCanonical { canonical, universes: 1 }; 101 let u_canonical = chalk_ir::UCanonical { canonical, universes: 1 };
103 let solution = solve(db, krate, &u_canonical); 102 solve(db, krate, &u_canonical)
104 solution.map(|solution| solution_from_chalk(db, solution))
105} 103}
106 104
107fn solve( 105fn solve(
@@ -148,7 +146,7 @@ fn solve(
148 // don't set the TLS for Chalk unless Chalk debugging is active, to make 146 // don't set the TLS for Chalk unless Chalk debugging is active, to make
149 // extra sure we only use it for debugging 147 // extra sure we only use it for debugging
150 let solution = 148 let solution =
151 if is_chalk_debug() { chalk::tls::set_current_program(db, solve) } else { solve() }; 149 if is_chalk_debug() { crate::tls::set_current_program(db, solve) } else { solve() };
152 150
153 solution 151 solution
154} 152}
@@ -169,34 +167,6 @@ fn is_chalk_print() -> bool {
169 std::env::var("CHALK_PRINT").is_ok() 167 std::env::var("CHALK_PRINT").is_ok()
170} 168}
171 169
172fn solution_from_chalk(
173 db: &dyn HirDatabase,
174 solution: chalk_solve::Solution<Interner>,
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 {
181 chalk_solve::Solution::Unique(constr_subst) => {
182 let subst = chalk_ir::Canonical {
183 value: constr_subst.value.subst,
184 binders: constr_subst.binders,
185 };
186 Solution::Unique(convert_subst(subst))
187 }
188 chalk_solve::Solution::Ambig(chalk_solve::Guidance::Definite(subst)) => {
189 Solution::Ambig(Guidance::Definite(convert_subst(subst)))
190 }
191 chalk_solve::Solution::Ambig(chalk_solve::Guidance::Suggested(subst)) => {
192 Solution::Ambig(Guidance::Suggested(convert_subst(subst)))
193 }
194 chalk_solve::Solution::Ambig(chalk_solve::Guidance::Unknown) => {
195 Solution::Ambig(Guidance::Unknown)
196 }
197 }
198}
199
200#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 170#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
201pub enum FnTrait { 171pub enum FnTrait {
202 FnOnce, 172 FnOnce,
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs
deleted file mode 100644
index c3b148cab..000000000
--- a/crates/hir_ty/src/traits/chalk/mapping.rs
+++ /dev/null
@@ -1,572 +0,0 @@
1//! This module contains the implementations of the `ToChalk` trait, which
2//! handles conversion between our data types and their corresponding types in
3//! Chalk (in both directions); plus some helper functions for more specialized
4//! conversions.
5
6use chalk_ir::{cast::Cast, fold::shift::Shift, interner::HasInterner, LifetimeData};
7use chalk_solve::rust_ir;
8
9use base_db::salsa::InternKey;
10use hir_def::{GenericDefId, TypeAliasId};
11
12use crate::{
13 db::HirDatabase, primitive::UintTy, AliasTy, CallableDefId, Canonical, DomainGoal, FnPointer,
14 GenericArg, InEnvironment, OpaqueTy, ProjectionTy, QuantifiedWhereClause, Scalar, Substitution,
15 TraitRef, Ty, TypeWalk, WhereClause,
16};
17
18use super::interner::*;
19use super::*;
20
21impl ToChalk for Ty {
22 type Chalk = chalk_ir::Ty<Interner>;
23 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> {
24 match self.into_inner() {
25 TyKind::Ref(m, ty) => ref_to_chalk(db, m, ty),
26 TyKind::Array(ty) => array_to_chalk(db, ty),
27 TyKind::Function(FnPointer { sig, substs, .. }) => {
28 let substitution = chalk_ir::FnSubst(substs.to_chalk(db).shifted_in(&Interner));
29 chalk_ir::TyKind::Function(chalk_ir::FnPointer {
30 num_binders: 0,
31 sig,
32 substitution,
33 })
34 .intern(&Interner)
35 }
36 TyKind::AssociatedType(assoc_type_id, substs) => {
37 let substitution = substs.to_chalk(db);
38 chalk_ir::TyKind::AssociatedType(assoc_type_id, substitution).intern(&Interner)
39 }
40
41 TyKind::OpaqueType(id, substs) => {
42 let substitution = substs.to_chalk(db);
43 chalk_ir::TyKind::OpaqueType(id, substitution).intern(&Interner)
44 }
45
46 TyKind::Foreign(id) => chalk_ir::TyKind::Foreign(id).intern(&Interner),
47
48 TyKind::Scalar(scalar) => chalk_ir::TyKind::Scalar(scalar).intern(&Interner),
49
50 TyKind::Tuple(cardinality, substs) => {
51 let substitution = substs.to_chalk(db);
52 chalk_ir::TyKind::Tuple(cardinality, substitution).intern(&Interner)
53 }
54 TyKind::Raw(mutability, ty) => {
55 let ty = ty.to_chalk(db);
56 chalk_ir::TyKind::Raw(mutability, ty).intern(&Interner)
57 }
58 TyKind::Slice(ty) => chalk_ir::TyKind::Slice(ty.to_chalk(db)).intern(&Interner),
59 TyKind::Str => chalk_ir::TyKind::Str.intern(&Interner),
60 TyKind::FnDef(id, substs) => {
61 let substitution = substs.to_chalk(db);
62 chalk_ir::TyKind::FnDef(id, substitution).intern(&Interner)
63 }
64 TyKind::Never => chalk_ir::TyKind::Never.intern(&Interner),
65
66 TyKind::Closure(closure_id, substs) => {
67 let substitution = substs.to_chalk(db);
68 chalk_ir::TyKind::Closure(closure_id, substitution).intern(&Interner)
69 }
70
71 TyKind::Adt(adt_id, substs) => {
72 let substitution = substs.to_chalk(db);
73 chalk_ir::TyKind::Adt(adt_id, substitution).intern(&Interner)
74 }
75 TyKind::Alias(AliasTy::Projection(proj_ty)) => {
76 let associated_ty_id = proj_ty.associated_ty_id;
77 let substitution = proj_ty.substitution.to_chalk(db);
78 chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
79 associated_ty_id,
80 substitution,
81 })
82 .cast(&Interner)
83 .intern(&Interner)
84 }
85 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
86 let opaque_ty_id = opaque_ty.opaque_ty_id;
87 let substitution = opaque_ty.substitution.to_chalk(db);
88 chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy { opaque_ty_id, substitution })
89 .cast(&Interner)
90 .intern(&Interner)
91 }
92 TyKind::Placeholder(idx) => idx.to_ty::<Interner>(&Interner),
93 TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner),
94 TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"),
95 TyKind::Dyn(dyn_ty) => {
96 let (bounds, binders) = dyn_ty.bounds.into_value_and_skipped_binders();
97 let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter(
98 &Interner,
99 bounds.interned().iter().cloned().map(|p| p.to_chalk(db)),
100 );
101 let bounded_ty = chalk_ir::DynTy {
102 bounds: chalk_ir::Binders::new(binders, where_clauses),
103 lifetime: LifetimeData::Static.intern(&Interner),
104 };
105 chalk_ir::TyKind::Dyn(bounded_ty).intern(&Interner)
106 }
107 TyKind::Error => chalk_ir::TyKind::Error.intern(&Interner),
108 }
109 }
110 fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self {
111 match chalk.data(&Interner).kind.clone() {
112 chalk_ir::TyKind::Error => TyKind::Error,
113 chalk_ir::TyKind::Array(ty, _size) => TyKind::Array(from_chalk(db, ty)),
114 chalk_ir::TyKind::Placeholder(idx) => TyKind::Placeholder(idx),
115 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(proj)) => {
116 let associated_ty = proj.associated_ty_id;
117 let parameters = from_chalk(db, proj.substitution);
118 TyKind::Alias(AliasTy::Projection(ProjectionTy {
119 associated_ty_id: associated_ty,
120 substitution: parameters,
121 }))
122 }
123 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(opaque_ty)) => {
124 let opaque_ty_id = opaque_ty.opaque_ty_id;
125 let parameters = from_chalk(db, opaque_ty.substitution);
126 TyKind::Alias(AliasTy::Opaque(OpaqueTy { opaque_ty_id, substitution: parameters }))
127 }
128 chalk_ir::TyKind::Function(chalk_ir::FnPointer {
129 num_binders,
130 sig,
131 substitution,
132 ..
133 }) => {
134 assert_eq!(num_binders, 0);
135 let substs: Substitution = from_chalk(
136 db,
137 substitution.0.shifted_out(&Interner).expect("fn ptr should have no binders"),
138 );
139 TyKind::Function(FnPointer { num_args: (substs.len(&Interner) - 1), sig, substs })
140 }
141 chalk_ir::TyKind::BoundVar(idx) => TyKind::BoundVar(idx),
142 chalk_ir::TyKind::InferenceVar(_iv, _kind) => TyKind::Error,
143 chalk_ir::TyKind::Dyn(where_clauses) => {
144 assert_eq!(where_clauses.bounds.binders.len(&Interner), 1);
145 let bounds = where_clauses
146 .bounds
147 .skip_binders()
148 .iter(&Interner)
149 .map(|c| from_chalk(db, c.clone()));
150 TyKind::Dyn(crate::DynTy {
151 bounds: crate::Binders::new(
152 where_clauses.bounds.binders.clone(),
153 crate::QuantifiedWhereClauses::from_iter(&Interner, bounds),
154 ),
155 })
156 }
157
158 chalk_ir::TyKind::Adt(adt_id, subst) => TyKind::Adt(adt_id, from_chalk(db, subst)),
159 chalk_ir::TyKind::AssociatedType(type_id, subst) => {
160 TyKind::AssociatedType(type_id, from_chalk(db, subst))
161 }
162
163 chalk_ir::TyKind::OpaqueType(opaque_type_id, subst) => {
164 TyKind::OpaqueType(opaque_type_id, from_chalk(db, subst))
165 }
166
167 chalk_ir::TyKind::Scalar(scalar) => TyKind::Scalar(scalar),
168 chalk_ir::TyKind::Tuple(cardinality, subst) => {
169 TyKind::Tuple(cardinality, from_chalk(db, subst))
170 }
171 chalk_ir::TyKind::Raw(mutability, ty) => TyKind::Raw(mutability, from_chalk(db, ty)),
172 chalk_ir::TyKind::Slice(ty) => TyKind::Slice(from_chalk(db, ty)),
173 chalk_ir::TyKind::Ref(mutability, _lifetime, ty) => {
174 TyKind::Ref(mutability, from_chalk(db, ty))
175 }
176 chalk_ir::TyKind::Str => TyKind::Str,
177 chalk_ir::TyKind::Never => TyKind::Never,
178
179 chalk_ir::TyKind::FnDef(fn_def_id, subst) => {
180 TyKind::FnDef(fn_def_id, from_chalk(db, subst))
181 }
182
183 chalk_ir::TyKind::Closure(id, subst) => TyKind::Closure(id, from_chalk(db, subst)),
184
185 chalk_ir::TyKind::Foreign(foreign_def_id) => TyKind::Foreign(foreign_def_id),
186 chalk_ir::TyKind::Generator(_, _) => unimplemented!(), // FIXME
187 chalk_ir::TyKind::GeneratorWitness(_, _) => unimplemented!(), // FIXME
188 }
189 .intern(&Interner)
190 }
191}
192
193/// We currently don't model lifetimes, but Chalk does. So, we have to insert a
194/// fake lifetime here, because Chalks built-in logic may expect it to be there.
195fn ref_to_chalk(
196 db: &dyn HirDatabase,
197 mutability: chalk_ir::Mutability,
198 ty: Ty,
199) -> chalk_ir::Ty<Interner> {
200 let arg = ty.to_chalk(db);
201 let lifetime = LifetimeData::Static.intern(&Interner);
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) -> chalk_ir::Ty<Interner> {
208 let arg = ty.to_chalk(db);
209 let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner);
210 let const_ = chalk_ir::ConstData {
211 ty: usize_ty,
212 value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { interned: () }),
213 }
214 .intern(&Interner);
215 chalk_ir::TyKind::Array(arg, const_).intern(&Interner)
216}
217
218impl ToChalk for GenericArg {
219 type Chalk = chalk_ir::GenericArg<Interner>;
220
221 fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk {
222 match self.interned() {
223 crate::GenericArgData::Ty(ty) => ty.clone().to_chalk(db).cast(&Interner),
224 }
225 }
226
227 fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self {
228 match chalk.interned() {
229 chalk_ir::GenericArgData::Ty(ty) => Ty::from_chalk(db, ty.clone()).cast(&Interner),
230 chalk_ir::GenericArgData::Lifetime(_) => unimplemented!(),
231 chalk_ir::GenericArgData::Const(_) => unimplemented!(),
232 }
233 }
234}
235
236impl ToChalk for Substitution {
237 type Chalk = chalk_ir::Substitution<Interner>;
238
239 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Substitution<Interner> {
240 chalk_ir::Substitution::from_iter(
241 &Interner,
242 self.iter(&Interner).map(|ty| ty.clone().to_chalk(db)),
243 )
244 }
245
246 fn from_chalk(
247 db: &dyn HirDatabase,
248 parameters: chalk_ir::Substitution<Interner>,
249 ) -> Substitution {
250 let tys = parameters.iter(&Interner).map(|p| from_chalk(db, p.clone())).collect();
251 Substitution::intern(tys)
252 }
253}
254
255impl ToChalk for TraitRef {
256 type Chalk = chalk_ir::TraitRef<Interner>;
257
258 fn to_chalk(self: TraitRef, db: &dyn HirDatabase) -> chalk_ir::TraitRef<Interner> {
259 let trait_id = self.trait_id;
260 let substitution = self.substitution.to_chalk(db);
261 chalk_ir::TraitRef { trait_id, substitution }
262 }
263
264 fn from_chalk(db: &dyn HirDatabase, trait_ref: chalk_ir::TraitRef<Interner>) -> Self {
265 let trait_id = trait_ref.trait_id;
266 let substs = from_chalk(db, trait_ref.substitution);
267 TraitRef { trait_id, substitution: substs }
268 }
269}
270
271impl ToChalk for hir_def::TraitId {
272 type Chalk = TraitId;
273
274 fn to_chalk(self, _db: &dyn HirDatabase) -> TraitId {
275 chalk_ir::TraitId(self.as_intern_id())
276 }
277
278 fn from_chalk(_db: &dyn HirDatabase, trait_id: TraitId) -> hir_def::TraitId {
279 InternKey::from_intern_id(trait_id.0)
280 }
281}
282
283impl ToChalk for hir_def::ImplId {
284 type Chalk = ImplId;
285
286 fn to_chalk(self, _db: &dyn HirDatabase) -> ImplId {
287 chalk_ir::ImplId(self.as_intern_id())
288 }
289
290 fn from_chalk(_db: &dyn HirDatabase, impl_id: ImplId) -> hir_def::ImplId {
291 InternKey::from_intern_id(impl_id.0)
292 }
293}
294
295impl ToChalk for CallableDefId {
296 type Chalk = FnDefId;
297
298 fn to_chalk(self, db: &dyn HirDatabase) -> FnDefId {
299 db.intern_callable_def(self).into()
300 }
301
302 fn from_chalk(db: &dyn HirDatabase, fn_def_id: FnDefId) -> CallableDefId {
303 db.lookup_intern_callable_def(fn_def_id.into())
304 }
305}
306
307pub(crate) struct TypeAliasAsValue(pub(crate) TypeAliasId);
308
309impl ToChalk for TypeAliasAsValue {
310 type Chalk = AssociatedTyValueId;
311
312 fn to_chalk(self, _db: &dyn HirDatabase) -> AssociatedTyValueId {
313 rust_ir::AssociatedTyValueId(self.0.as_intern_id())
314 }
315
316 fn from_chalk(
317 _db: &dyn HirDatabase,
318 assoc_ty_value_id: AssociatedTyValueId,
319 ) -> TypeAliasAsValue {
320 TypeAliasAsValue(TypeAliasId::from_intern_id(assoc_ty_value_id.0))
321 }
322}
323
324impl ToChalk for WhereClause {
325 type Chalk = chalk_ir::WhereClause<Interner>;
326
327 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::WhereClause<Interner> {
328 match self {
329 WhereClause::Implemented(trait_ref) => {
330 chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db))
331 }
332 WhereClause::AliasEq(alias_eq) => chalk_ir::WhereClause::AliasEq(alias_eq.to_chalk(db)),
333 }
334 }
335
336 fn from_chalk(
337 db: &dyn HirDatabase,
338 where_clause: chalk_ir::WhereClause<Interner>,
339 ) -> WhereClause {
340 match where_clause {
341 chalk_ir::WhereClause::Implemented(tr) => WhereClause::Implemented(from_chalk(db, tr)),
342 chalk_ir::WhereClause::AliasEq(alias_eq) => {
343 WhereClause::AliasEq(from_chalk(db, alias_eq))
344 }
345
346 chalk_ir::WhereClause::LifetimeOutlives(_) => {
347 // we shouldn't get these from Chalk
348 panic!("encountered LifetimeOutlives from Chalk")
349 }
350
351 chalk_ir::WhereClause::TypeOutlives(_) => {
352 // we shouldn't get these from Chalk
353 panic!("encountered TypeOutlives from Chalk")
354 }
355 }
356 }
357}
358
359impl ToChalk for ProjectionTy {
360 type Chalk = chalk_ir::ProjectionTy<Interner>;
361
362 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::ProjectionTy<Interner> {
363 chalk_ir::ProjectionTy {
364 associated_ty_id: self.associated_ty_id,
365 substitution: self.substitution.to_chalk(db),
366 }
367 }
368
369 fn from_chalk(
370 db: &dyn HirDatabase,
371 projection_ty: chalk_ir::ProjectionTy<Interner>,
372 ) -> ProjectionTy {
373 ProjectionTy {
374 associated_ty_id: projection_ty.associated_ty_id,
375 substitution: from_chalk(db, projection_ty.substitution),
376 }
377 }
378}
379impl ToChalk for OpaqueTy {
380 type Chalk = chalk_ir::OpaqueTy<Interner>;
381
382 fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk {
383 chalk_ir::OpaqueTy {
384 opaque_ty_id: self.opaque_ty_id,
385 substitution: self.substitution.to_chalk(db),
386 }
387 }
388
389 fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self {
390 OpaqueTy {
391 opaque_ty_id: chalk.opaque_ty_id,
392 substitution: from_chalk(db, chalk.substitution),
393 }
394 }
395}
396
397impl ToChalk for AliasTy {
398 type Chalk = chalk_ir::AliasTy<Interner>;
399
400 fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk {
401 match self {
402 AliasTy::Projection(projection_ty) => {
403 chalk_ir::AliasTy::Projection(projection_ty.to_chalk(db))
404 }
405 AliasTy::Opaque(opaque_ty) => chalk_ir::AliasTy::Opaque(opaque_ty.to_chalk(db)),
406 }
407 }
408
409 fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self {
410 match chalk {
411 chalk_ir::AliasTy::Projection(projection_ty) => {
412 AliasTy::Projection(from_chalk(db, projection_ty))
413 }
414 chalk_ir::AliasTy::Opaque(opaque_ty) => AliasTy::Opaque(from_chalk(db, opaque_ty)),
415 }
416 }
417}
418
419impl ToChalk for AliasEq {
420 type Chalk = chalk_ir::AliasEq<Interner>;
421
422 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::AliasEq<Interner> {
423 chalk_ir::AliasEq { alias: self.alias.to_chalk(db), ty: self.ty.to_chalk(db) }
424 }
425
426 fn from_chalk(db: &dyn HirDatabase, alias_eq: chalk_ir::AliasEq<Interner>) -> Self {
427 AliasEq { alias: from_chalk(db, alias_eq.alias), ty: from_chalk(db, alias_eq.ty) }
428 }
429}
430
431impl ToChalk for DomainGoal {
432 type Chalk = chalk_ir::DomainGoal<Interner>;
433
434 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> {
435 match self {
436 DomainGoal::Holds(WhereClause::Implemented(tr)) => tr.to_chalk(db).cast(&Interner),
437 DomainGoal::Holds(WhereClause::AliasEq(alias_eq)) => {
438 alias_eq.to_chalk(db).cast(&Interner)
439 }
440 }
441 }
442
443 fn from_chalk(_db: &dyn HirDatabase, _goal: chalk_ir::DomainGoal<Interner>) -> Self {
444 unimplemented!()
445 }
446}
447
448impl<T> ToChalk for Canonical<T>
449where
450 T: ToChalk,
451 T::Chalk: HasInterner<Interner = Interner>,
452{
453 type Chalk = chalk_ir::Canonical<T::Chalk>;
454
455 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> {
456 let value = self.value.to_chalk(db);
457 chalk_ir::Canonical { value, binders: self.binders }
458 }
459
460 fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> {
461 Canonical { binders: canonical.binders, value: from_chalk(db, canonical.value) }
462 }
463}
464
465impl<T: ToChalk> ToChalk for InEnvironment<T>
466where
467 T::Chalk: chalk_ir::interner::HasInterner<Interner = Interner>,
468{
469 type Chalk = chalk_ir::InEnvironment<T::Chalk>;
470
471 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> {
472 chalk_ir::InEnvironment { environment: self.environment, goal: self.goal.to_chalk(db) }
473 }
474
475 fn from_chalk(
476 _db: &dyn HirDatabase,
477 _in_env: chalk_ir::InEnvironment<T::Chalk>,
478 ) -> InEnvironment<T> {
479 unimplemented!()
480 }
481}
482
483impl<T: ToChalk> ToChalk for crate::Binders<T>
484where
485 T::Chalk: chalk_ir::interner::HasInterner<Interner = Interner>,
486{
487 type Chalk = chalk_ir::Binders<T::Chalk>;
488
489 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Binders<T::Chalk> {
490 let (value, binders) = self.into_value_and_skipped_binders();
491 chalk_ir::Binders::new(binders, value.to_chalk(db))
492 }
493
494 fn from_chalk(db: &dyn HirDatabase, binders: chalk_ir::Binders<T::Chalk>) -> crate::Binders<T> {
495 let (v, b) = binders.into_value_and_skipped_binders();
496 crate::Binders::new(b, from_chalk(db, v))
497 }
498}
499
500pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T>
501where
502 T: HasInterner<Interner = Interner>,
503{
504 chalk_ir::Binders::new(
505 chalk_ir::VariableKinds::from_iter(
506 &Interner,
507 std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General))
508 .take(num_vars),
509 ),
510 value,
511 )
512}
513
514pub(super) fn convert_where_clauses(
515 db: &dyn HirDatabase,
516 def: GenericDefId,
517 substs: &Substitution,
518) -> Vec<chalk_ir::QuantifiedWhereClause<Interner>> {
519 let generic_predicates = db.generic_predicates(def);
520 let mut result = Vec::with_capacity(generic_predicates.len());
521 for pred in generic_predicates.iter() {
522 result.push(pred.clone().substitute(&Interner, substs).to_chalk(db));
523 }
524 result
525}
526
527pub(super) fn generic_predicate_to_inline_bound(
528 db: &dyn HirDatabase,
529 pred: &QuantifiedWhereClause,
530 self_ty: &Ty,
531) -> Option<chalk_ir::Binders<rust_ir::InlineBound<Interner>>> {
532 // An InlineBound is like a GenericPredicate, except the self type is left out.
533 // We don't have a special type for this, but Chalk does.
534 let self_ty_shifted_in = self_ty.clone().shifted_in_from(DebruijnIndex::ONE);
535 let (pred, binders) = pred.as_ref().into_value_and_skipped_binders();
536 match pred {
537 WhereClause::Implemented(trait_ref) => {
538 if trait_ref.self_type_parameter(&Interner) != &self_ty_shifted_in {
539 // we can only convert predicates back to type bounds if they
540 // have the expected self type
541 return None;
542 }
543 let args_no_self = trait_ref.substitution.interned()[1..]
544 .iter()
545 .map(|ty| ty.clone().to_chalk(db).cast(&Interner))
546 .collect();
547 let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self };
548 Some(chalk_ir::Binders::new(binders, rust_ir::InlineBound::TraitBound(trait_bound)))
549 }
550 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
551 if projection_ty.self_type_parameter(&Interner) != &self_ty_shifted_in {
552 return None;
553 }
554 let trait_ = projection_ty.trait_(db);
555 let args_no_self = projection_ty.substitution.interned()[1..]
556 .iter()
557 .map(|ty| ty.clone().to_chalk(db).cast(&Interner))
558 .collect();
559 let alias_eq_bound = rust_ir::AliasEqBound {
560 value: ty.clone().to_chalk(db),
561 trait_bound: rust_ir::TraitBound { trait_id: trait_.to_chalk(db), args_no_self },
562 associated_ty_id: projection_ty.associated_ty_id,
563 parameters: Vec::new(), // FIXME we don't support generic associated types yet
564 };
565 Some(chalk_ir::Binders::new(
566 binders,
567 rust_ir::InlineBound::AliasEqBound(alias_eq_bound),
568 ))
569 }
570 _ => None,
571 }
572}
diff --git a/crates/hir_ty/src/types.rs b/crates/hir_ty/src/types.rs
deleted file mode 100644
index 46c705a76..000000000
--- a/crates/hir_ty/src/types.rs
+++ /dev/null
@@ -1,475 +0,0 @@
1//! This is the home of `Ty` etc. until they get replaced by their chalk_ir
2//! equivalents.
3
4use std::sync::Arc;
5
6use chalk_ir::{
7 cast::{CastTo, Caster},
8 BoundVar, Mutability, Scalar, TyVariableKind,
9};
10use hir_def::LifetimeParamId;
11use smallvec::SmallVec;
12
13use crate::{
14 AssocTypeId, CanonicalVarKinds, ChalkTraitId, ClosureId, FnDefId, FnSig, ForeignDefId,
15 InferenceVar, Interner, OpaqueTyId, PlaceholderIndex, TypeWalk, VariableKinds,
16};
17
18#[derive(Clone, PartialEq, Eq, Debug, Hash)]
19pub enum Lifetime {
20 Parameter(LifetimeParamId),
21 Static,
22}
23
24#[derive(Clone, PartialEq, Eq, Debug, Hash)]
25pub struct OpaqueTy {
26 pub opaque_ty_id: OpaqueTyId,
27 pub substitution: Substitution,
28}
29
30/// A "projection" type corresponds to an (unnormalized)
31/// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the
32/// trait and all its parameters are fully known.
33#[derive(Clone, PartialEq, Eq, Debug, Hash)]
34pub struct ProjectionTy {
35 pub associated_ty_id: AssocTypeId,
36 pub substitution: Substitution,
37}
38
39#[derive(Clone, PartialEq, Eq, Debug, Hash)]
40pub struct DynTy {
41 /// The unknown self type.
42 pub bounds: Binders<QuantifiedWhereClauses>,
43}
44
45#[derive(Clone, PartialEq, Eq, Debug, Hash)]
46pub struct FnPointer {
47 pub num_args: usize,
48 pub sig: FnSig,
49 pub substs: Substitution,
50}
51
52#[derive(Clone, PartialEq, Eq, Debug, Hash)]
53pub enum AliasTy {
54 /// A "projection" type corresponds to an (unnormalized)
55 /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the
56 /// trait and all its parameters are fully known.
57 Projection(ProjectionTy),
58 /// An opaque type (`impl Trait`).
59 ///
60 /// This is currently only used for return type impl trait; each instance of
61 /// `impl Trait` in a return type gets its own ID.
62 Opaque(OpaqueTy),
63}
64
65/// A type.
66///
67/// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents
68/// the same thing (but in a different way).
69///
70/// This should be cheap to clone.
71#[derive(Clone, PartialEq, Eq, Debug, Hash)]
72pub enum TyKind {
73 /// Structures, enumerations and unions.
74 Adt(chalk_ir::AdtId<Interner>, Substitution),
75
76 /// Represents an associated item like `Iterator::Item`. This is used
77 /// when we have tried to normalize a projection like `T::Item` but
78 /// couldn't find a better representation. In that case, we generate
79 /// an **application type** like `(Iterator::Item)<T>`.
80 AssociatedType(AssocTypeId, Substitution),
81
82 /// a scalar type like `bool` or `u32`
83 Scalar(Scalar),
84
85 /// A tuple type. For example, `(i32, bool)`.
86 Tuple(usize, Substitution),
87
88 /// An array with the given length. Written as `[T; n]`.
89 Array(Ty),
90
91 /// The pointee of an array slice. Written as `[T]`.
92 Slice(Ty),
93
94 /// A raw pointer. Written as `*mut T` or `*const T`
95 Raw(Mutability, Ty),
96
97 /// A reference; a pointer with an associated lifetime. Written as
98 /// `&'a mut T` or `&'a T`.
99 Ref(Mutability, Ty),
100
101 /// This represents a placeholder for an opaque type in situations where we
102 /// don't know the hidden type (i.e. currently almost always). This is
103 /// analogous to the `AssociatedType` type constructor.
104 /// It is also used as the type of async block, with one type parameter
105 /// representing the Future::Output type.
106 OpaqueType(OpaqueTyId, Substitution),
107
108 /// The anonymous type of a function declaration/definition. Each
109 /// function has a unique type, which is output (for a function
110 /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`.
111 ///
112 /// This includes tuple struct / enum variant constructors as well.
113 ///
114 /// For example the type of `bar` here:
115 ///
116 /// ```
117 /// fn foo() -> i32 { 1 }
118 /// let bar = foo; // bar: fn() -> i32 {foo}
119 /// ```
120 FnDef(FnDefId, Substitution),
121
122 /// The pointee of a string slice. Written as `str`.
123 Str,
124
125 /// The never type `!`.
126 Never,
127
128 /// The type of a specific closure.
129 ///
130 /// The closure signature is stored in a `FnPtr` type in the first type
131 /// parameter.
132 Closure(ClosureId, Substitution),
133
134 /// Represents a foreign type declared in external blocks.
135 Foreign(ForeignDefId),
136
137 /// A pointer to a function. Written as `fn() -> i32`.
138 ///
139 /// For example the type of `bar` here:
140 ///
141 /// ```
142 /// fn foo() -> i32 { 1 }
143 /// let bar: fn() -> i32 = foo;
144 /// ```
145 Function(FnPointer),
146
147 /// An "alias" type represents some form of type alias, such as:
148 /// - An associated type projection like `<T as Iterator>::Item`
149 /// - `impl Trait` types
150 /// - Named type aliases like `type Foo<X> = Vec<X>`
151 Alias(AliasTy),
152
153 /// A placeholder for a type parameter; for example, `T` in `fn f<T>(x: T)
154 /// {}` when we're type-checking the body of that function. In this
155 /// situation, we know this stands for *some* type, but don't know the exact
156 /// type.
157 Placeholder(PlaceholderIndex),
158
159 /// A bound type variable. This is used in various places: when representing
160 /// some polymorphic type like the type of function `fn f<T>`, the type
161 /// parameters get turned into variables; during trait resolution, inference
162 /// variables get turned into bound variables and back; and in `Dyn` the
163 /// `Self` type is represented with a bound variable as well.
164 BoundVar(BoundVar),
165
166 /// A type variable used during type checking.
167 InferenceVar(InferenceVar, TyVariableKind),
168
169 /// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust).
170 ///
171 /// The predicates are quantified over the `Self` type, i.e. `Ty::Bound(0)`
172 /// represents the `Self` type inside the bounds. This is currently
173 /// implicit; Chalk has the `Binders` struct to make it explicit, but it
174 /// didn't seem worth the overhead yet.
175 Dyn(DynTy),
176
177 /// A placeholder for a type which could not be computed; this is propagated
178 /// to avoid useless error messages. Doubles as a placeholder where type
179 /// variables are inserted before type checking, since we want to try to
180 /// infer a better type here anyway -- for the IDE use case, we want to try
181 /// to infer as much as possible even in the presence of type errors.
182 Error,
183}
184
185#[derive(Clone, PartialEq, Eq, Debug, Hash)]
186pub struct Ty(Arc<TyKind>);
187
188impl TyKind {
189 pub fn intern(self, _interner: &Interner) -> Ty {
190 Ty(Arc::new(self))
191 }
192}
193
194impl Ty {
195 pub fn kind(&self, _interner: &Interner) -> &TyKind {
196 &self.0
197 }
198
199 pub fn interned_mut(&mut self) -> &mut TyKind {
200 Arc::make_mut(&mut self.0)
201 }
202
203 pub fn into_inner(self) -> TyKind {
204 Arc::try_unwrap(self.0).unwrap_or_else(|a| (*a).clone())
205 }
206}
207
208#[derive(Clone, PartialEq, Eq, Debug, Hash)]
209pub struct GenericArg {
210 interned: GenericArgData,
211}
212
213#[derive(Clone, PartialEq, Eq, Debug, Hash)]
214pub enum GenericArgData {
215 Ty(Ty),
216}
217
218impl GenericArg {
219 /// Constructs a generic argument using `GenericArgData`.
220 pub fn new(_interner: &Interner, data: GenericArgData) -> Self {
221 GenericArg { interned: data }
222 }
223
224 /// Gets the interned value.
225 pub fn interned(&self) -> &GenericArgData {
226 &self.interned
227 }
228
229 /// Asserts that this is a type argument.
230 pub fn assert_ty_ref(&self, interner: &Interner) -> &Ty {
231 self.ty(interner).unwrap()
232 }
233
234 /// Checks whether the generic argument is a type.
235 pub fn is_ty(&self, _interner: &Interner) -> bool {
236 match self.interned() {
237 GenericArgData::Ty(_) => true,
238 }
239 }
240
241 /// Returns the type if it is one, `None` otherwise.
242 pub fn ty(&self, _interner: &Interner) -> Option<&Ty> {
243 match self.interned() {
244 GenericArgData::Ty(t) => Some(t),
245 }
246 }
247
248 pub fn interned_mut(&mut self) -> &mut GenericArgData {
249 &mut self.interned
250 }
251}
252
253/// A list of substitutions for generic parameters.
254#[derive(Clone, PartialEq, Eq, Debug, Hash)]
255pub struct Substitution(SmallVec<[GenericArg; 2]>);
256
257impl Substitution {
258 pub fn interned(&self) -> &[GenericArg] {
259 &self.0
260 }
261
262 pub fn len(&self, _: &Interner) -> usize {
263 self.0.len()
264 }
265
266 pub fn is_empty(&self, _: &Interner) -> bool {
267 self.0.is_empty()
268 }
269
270 pub fn at(&self, _: &Interner, i: usize) -> &GenericArg {
271 &self.0[i]
272 }
273
274 pub fn empty(_: &Interner) -> Substitution {
275 Substitution(SmallVec::new())
276 }
277
278 pub fn iter(&self, _: &Interner) -> std::slice::Iter<'_, GenericArg> {
279 self.0.iter()
280 }
281
282 pub fn from_iter(
283 interner: &Interner,
284 elements: impl IntoIterator<Item = impl CastTo<GenericArg>>,
285 ) -> Self {
286 Substitution(elements.into_iter().casted(interner).collect())
287 }
288
289 pub fn apply<T: TypeWalk>(&self, value: T, _interner: &Interner) -> T {
290 value.subst_bound_vars(self)
291 }
292
293 // Temporary helper functions, to be removed
294 pub fn intern(interned: SmallVec<[GenericArg; 2]>) -> Substitution {
295 Substitution(interned)
296 }
297
298 pub fn interned_mut(&mut self) -> &mut SmallVec<[GenericArg; 2]> {
299 &mut self.0
300 }
301}
302
303#[derive(Clone, PartialEq, Eq, Hash)]
304pub struct Binders<T> {
305 /// The binders that quantify over the value.
306 pub binders: VariableKinds,
307 value: T,
308}
309
310impl<T> Binders<T> {
311 pub fn new(binders: VariableKinds, value: T) -> Self {
312 Self { binders, value }
313 }
314
315 pub fn empty(_interner: &Interner, value: T) -> Self {
316 crate::make_only_type_binders(0, value)
317 }
318
319 pub fn as_ref(&self) -> Binders<&T> {
320 Binders { binders: self.binders.clone(), value: &self.value }
321 }
322
323 pub fn map<U>(self, f: impl FnOnce(T) -> U) -> Binders<U> {
324 Binders { binders: self.binders, value: f(self.value) }
325 }
326
327 pub fn filter_map<U>(self, f: impl FnOnce(T) -> Option<U>) -> Option<Binders<U>> {
328 Some(Binders { binders: self.binders, value: f(self.value)? })
329 }
330
331 pub fn skip_binders(&self) -> &T {
332 &self.value
333 }
334
335 pub fn into_value_and_skipped_binders(self) -> (T, VariableKinds) {
336 (self.value, self.binders)
337 }
338
339 /// Returns the number of binders.
340 pub fn len(&self, interner: &Interner) -> usize {
341 self.binders.len(interner)
342 }
343
344 // Temporary helper function, to be removed
345 pub fn skip_binders_mut(&mut self) -> &mut T {
346 &mut self.value
347 }
348}
349
350impl<T: Clone> Binders<&T> {
351 pub fn cloned(&self) -> Binders<T> {
352 Binders::new(self.binders.clone(), self.value.clone())
353 }
354}
355
356impl<T: std::fmt::Debug> std::fmt::Debug for Binders<T> {
357 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
358 let Binders { ref binders, ref value } = *self;
359 write!(fmt, "for{:?} ", binders.inner_debug(&Interner))?;
360 std::fmt::Debug::fmt(value, fmt)
361 }
362}
363
364/// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait.
365#[derive(Clone, PartialEq, Eq, Debug, Hash)]
366pub struct TraitRef {
367 pub trait_id: ChalkTraitId,
368 pub substitution: Substitution,
369}
370
371/// Like `generics::WherePredicate`, but with resolved types: A condition on the
372/// parameters of a generic item.
373#[derive(Debug, Clone, PartialEq, Eq, Hash)]
374pub enum WhereClause {
375 /// The given trait needs to be implemented for its type parameters.
376 Implemented(TraitRef),
377 /// An associated type bindings like in `Iterator<Item = T>`.
378 AliasEq(AliasEq),
379}
380
381pub type QuantifiedWhereClause = Binders<WhereClause>;
382
383#[derive(Debug, Clone, PartialEq, Eq, Hash)]
384pub struct QuantifiedWhereClauses(Arc<[QuantifiedWhereClause]>);
385
386impl QuantifiedWhereClauses {
387 pub fn from_iter(
388 _interner: &Interner,
389 elements: impl IntoIterator<Item = QuantifiedWhereClause>,
390 ) -> Self {
391 QuantifiedWhereClauses(elements.into_iter().collect())
392 }
393
394 pub fn interned(&self) -> &Arc<[QuantifiedWhereClause]> {
395 &self.0
396 }
397
398 pub fn interned_mut(&mut self) -> &mut Arc<[QuantifiedWhereClause]> {
399 &mut self.0
400 }
401}
402
403/// Basically a claim (currently not validated / checked) that the contained
404/// type / trait ref contains no inference variables; any inference variables it
405/// contained have been replaced by bound variables, and `kinds` tells us how
406/// many there are and whether they were normal or float/int variables. This is
407/// used to erase irrelevant differences between types before using them in
408/// queries.
409#[derive(Debug, Clone, PartialEq, Eq, Hash)]
410pub struct Canonical<T> {
411 pub value: T,
412 pub binders: CanonicalVarKinds,
413}
414
415/// Something (usually a goal), along with an environment.
416#[derive(Clone, Debug, PartialEq, Eq, Hash)]
417pub struct InEnvironment<T> {
418 pub environment: chalk_ir::Environment<Interner>,
419 pub goal: T,
420}
421
422impl<T> InEnvironment<T> {
423 pub fn new(environment: chalk_ir::Environment<Interner>, value: T) -> InEnvironment<T> {
424 InEnvironment { environment, goal: value }
425 }
426}
427
428/// Something that needs to be proven (by Chalk) during type checking, e.g. that
429/// a certain type implements a certain trait. Proving the Obligation might
430/// result in additional information about inference variables.
431#[derive(Clone, Debug, PartialEq, Eq, Hash)]
432pub enum DomainGoal {
433 Holds(WhereClause),
434}
435
436#[derive(Clone, Debug, PartialEq, Eq, Hash)]
437pub struct AliasEq {
438 pub alias: AliasTy,
439 pub ty: Ty,
440}
441
442#[derive(Clone, Debug, PartialEq, Eq)]
443pub struct SolutionVariables(pub Canonical<Substitution>);
444
445#[derive(Clone, Debug, PartialEq, Eq)]
446/// A (possible) solution for a proposed goal.
447pub enum Solution {
448 /// The goal indeed holds, and there is a unique value for all existential
449 /// variables.
450 Unique(SolutionVariables),
451
452 /// The goal may be provable in multiple ways, but regardless we may have some guidance
453 /// for type inference. In this case, we don't return any lifetime
454 /// constraints, since we have not "committed" to any particular solution
455 /// yet.
456 Ambig(Guidance),
457}
458
459#[derive(Clone, Debug, PartialEq, Eq)]
460/// When a goal holds ambiguously (e.g., because there are multiple possible
461/// solutions), we issue a set of *guidance* back to type inference.
462pub enum Guidance {
463 /// The existential variables *must* have the given values if the goal is
464 /// ever to hold, but that alone isn't enough to guarantee the goal will
465 /// actually hold.
466 Definite(SolutionVariables),
467
468 /// There are multiple plausible values for the existentials, but the ones
469 /// here are suggested as the preferred choice heuristically. These should
470 /// be used for inference fallback only.
471 Suggested(SolutionVariables),
472
473 /// There's no useful information to feed back to type inference
474 Unknown,
475}
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs
index d11708299..5f6cb052a 100644
--- a/crates/hir_ty/src/utils.rs
+++ b/crates/hir_ty/src/utils.rs
@@ -1,10 +1,8 @@
1//! Helper functions for working with def, which don't need to be a separate 1//! Helper functions for working with def, which don't need to be a separate
2//! query, but can't be computed directly from `*Data` (ie, which need a `db`). 2//! query, but can't be computed directly from `*Data` (ie, which need a `db`).
3use std::sync::Arc;
4 3
5use chalk_ir::{BoundVar, DebruijnIndex}; 4use chalk_ir::{fold::Shift, BoundVar, DebruijnIndex};
6use hir_def::{ 5use hir_def::{
7 adt::VariantData,
8 db::DefDatabase, 6 db::DefDatabase,
9 generics::{ 7 generics::{
10 GenericParams, TypeParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget, 8 GenericParams, TypeParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
@@ -13,11 +11,11 @@ use hir_def::{
13 path::Path, 11 path::Path,
14 resolver::{HasResolver, TypeNs}, 12 resolver::{HasResolver, TypeNs},
15 type_ref::TypeRef, 13 type_ref::TypeRef,
16 AssocContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId, VariantId, 14 AssocContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId,
17}; 15};
18use hir_expand::name::{name, Name}; 16use hir_expand::name::{name, Name};
19 17
20use crate::{db::HirDatabase, Interner, Substitution, TraitRef, TyKind, TypeWalk, WhereClause}; 18use crate::{db::HirDatabase, Interner, Substitution, TraitRef, TraitRefExt, TyKind, WhereClause};
21 19
22fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { 20fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
23 let resolver = trait_.resolver(db); 21 let resolver = trait_.resolver(db);
@@ -68,7 +66,7 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr
68 // FIXME: how to correctly handle higher-ranked bounds here? 66 // FIXME: how to correctly handle higher-ranked bounds here?
69 WhereClause::Implemented(tr) => Some( 67 WhereClause::Implemented(tr) => Some(
70 tr.clone() 68 tr.clone()
71 .shifted_out_to(DebruijnIndex::ONE) 69 .shifted_out_to(&Interner, DebruijnIndex::ONE)
72 .expect("FIXME unexpected higher-ranked trait bound"), 70 .expect("FIXME unexpected higher-ranked trait bound"),
73 ), 71 ),
74 _ => None, 72 _ => None,
@@ -136,25 +134,6 @@ pub(super) fn associated_type_by_name_including_super_traits(
136 }) 134 })
137} 135}
138 136
139pub(super) fn variant_data(db: &dyn DefDatabase, var: VariantId) -> Arc<VariantData> {
140 match var {
141 VariantId::StructId(it) => db.struct_data(it).variant_data.clone(),
142 VariantId::UnionId(it) => db.union_data(it).variant_data.clone(),
143 VariantId::EnumVariantId(it) => {
144 db.enum_data(it.parent).variants[it.local_id].variant_data.clone()
145 }
146 }
147}
148
149/// Helper for mutating `Arc<[T]>` (i.e. `Arc::make_mut` for Arc slices).
150/// The underlying values are cloned if there are other strong references.
151pub(crate) fn make_mut_slice<T: Clone>(a: &mut Arc<[T]>) -> &mut [T] {
152 if Arc::get_mut(a).is_none() {
153 *a = a.iter().cloned().collect();
154 }
155 Arc::get_mut(a).unwrap()
156}
157
158pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics { 137pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
159 let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def))); 138 let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def)));
160 Generics { def, params: db.generic_params(def), parent_generics } 139 Generics { def, params: db.generic_params(def), parent_generics }
diff --git a/crates/hir_ty/src/walk.rs b/crates/hir_ty/src/walk.rs
index b85e6ab4d..6ef1d5336 100644
--- a/crates/hir_ty/src/walk.rs
+++ b/crates/hir_ty/src/walk.rs
@@ -1,130 +1,17 @@
1//! The `TypeWalk` trait (probably to be replaced by Chalk's `Fold` and 1//! The `TypeWalk` trait (probably to be replaced by Chalk's `Fold` and
2//! `Visit`). 2//! `Visit`).
3 3
4use std::mem; 4use chalk_ir::interner::HasInterner;
5
6use chalk_ir::DebruijnIndex;
7 5
8use crate::{ 6use crate::{
9 utils::make_mut_slice, AliasEq, AliasTy, Binders, CallableSig, GenericArg, GenericArgData, 7 AliasEq, AliasTy, Binders, CallableSig, FnSubst, GenericArg, GenericArgData, Interner,
10 Interner, OpaqueTy, ProjectionTy, Substitution, TraitRef, Ty, TyKind, WhereClause, 8 OpaqueTy, ProjectionTy, Substitution, TraitRef, Ty, TyKind, WhereClause,
11}; 9};
12 10
13/// This allows walking structures that contain types to do something with those 11/// This allows walking structures that contain types to do something with those
14/// types, similar to Chalk's `Fold` trait. 12/// types, similar to Chalk's `Fold` trait.
15pub trait TypeWalk { 13pub trait TypeWalk {
16 fn walk(&self, f: &mut impl FnMut(&Ty)); 14 fn walk(&self, f: &mut impl FnMut(&Ty));
17 fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
18 self.walk_mut_binders(&mut |ty, _binders| f(ty), DebruijnIndex::INNERMOST);
19 }
20 /// Walk the type, counting entered binders.
21 ///
22 /// `TyKind::Bound` variables use DeBruijn indexing, which means that 0 refers
23 /// to the innermost binder, 1 to the next, etc.. So when we want to
24 /// substitute a certain bound variable, we can't just walk the whole type
25 /// and blindly replace each instance of a certain index; when we 'enter'
26 /// things that introduce new bound variables, we have to keep track of
27 /// that. Currently, the only thing that introduces bound variables on our
28 /// side are `TyKind::Dyn` and `TyKind::Opaque`, which each introduce a bound
29 /// variable for the self type.
30 fn walk_mut_binders(
31 &mut self,
32 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
33 binders: DebruijnIndex,
34 );
35
36 fn fold_binders(
37 mut self,
38 f: &mut impl FnMut(Ty, DebruijnIndex) -> Ty,
39 binders: DebruijnIndex,
40 ) -> Self
41 where
42 Self: Sized,
43 {
44 self.walk_mut_binders(
45 &mut |ty_mut, binders| {
46 let ty = mem::replace(ty_mut, TyKind::Error.intern(&Interner));
47 *ty_mut = f(ty, binders);
48 },
49 binders,
50 );
51 self
52 }
53
54 fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Self
55 where
56 Self: Sized,
57 {
58 self.walk_mut(&mut |ty_mut| {
59 let ty = mem::replace(ty_mut, TyKind::Error.intern(&Interner));
60 *ty_mut = f(ty);
61 });
62 self
63 }
64
65 /// Substitutes `TyKind::Bound` vars with the given substitution.
66 fn subst_bound_vars(self, substs: &Substitution) -> Self
67 where
68 Self: Sized,
69 {
70 self.subst_bound_vars_at_depth(substs, DebruijnIndex::INNERMOST)
71 }
72
73 /// Substitutes `TyKind::Bound` vars with the given substitution.
74 fn subst_bound_vars_at_depth(mut self, substs: &Substitution, depth: DebruijnIndex) -> Self
75 where
76 Self: Sized,
77 {
78 self.walk_mut_binders(
79 &mut |ty, binders| {
80 if let &mut TyKind::BoundVar(bound) = ty.interned_mut() {
81 if bound.debruijn >= binders {
82 *ty = substs.interned()[bound.index]
83 .assert_ty_ref(&Interner)
84 .clone()
85 .shifted_in_from(binders);
86 }
87 }
88 },
89 depth,
90 );
91 self
92 }
93
94 /// Shifts up debruijn indices of `TyKind::Bound` vars by `n`.
95 fn shifted_in_from(self, n: DebruijnIndex) -> Self
96 where
97 Self: Sized,
98 {
99 self.fold_binders(
100 &mut |ty, binders| match ty.kind(&Interner) {
101 TyKind::BoundVar(bound) if bound.debruijn >= binders => {
102 TyKind::BoundVar(bound.shifted_in_from(n)).intern(&Interner)
103 }
104 _ => ty,
105 },
106 DebruijnIndex::INNERMOST,
107 )
108 }
109
110 /// Shifts debruijn indices of `TyKind::Bound` vars out (down) by `n`.
111 fn shifted_out_to(self, n: DebruijnIndex) -> Option<Self>
112 where
113 Self: Sized + std::fmt::Debug,
114 {
115 Some(self.fold_binders(
116 &mut |ty, binders| {
117 match ty.kind(&Interner) {
118 TyKind::BoundVar(bound) if bound.debruijn >= binders => {
119 TyKind::BoundVar(bound.shifted_out_to(n).unwrap_or(bound.clone()))
120 .intern(&Interner)
121 }
122 _ => ty,
123 }
124 },
125 DebruijnIndex::INNERMOST,
126 ))
127 }
128} 15}
129 16
130impl TypeWalk for Ty { 17impl TypeWalk for Ty {
@@ -145,47 +32,26 @@ impl TypeWalk for Ty {
145 p.walk(f); 32 p.walk(f);
146 } 33 }
147 } 34 }
148 TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => { 35 TyKind::Slice(ty)
36 | TyKind::Array(ty, _)
37 | TyKind::Ref(_, _, ty)
38 | TyKind::Raw(_, ty) => {
149 ty.walk(f); 39 ty.walk(f);
150 } 40 }
151 _ => { 41 TyKind::Function(fn_pointer) => {
152 if let Some(substs) = self.substs() { 42 fn_pointer.substitution.0.walk(f);
153 for t in substs.iter(&Interner) {
154 t.walk(f);
155 }
156 }
157 }
158 }
159 f(self);
160 }
161
162 fn walk_mut_binders(
163 &mut self,
164 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
165 binders: DebruijnIndex,
166 ) {
167 match self.interned_mut() {
168 TyKind::Alias(AliasTy::Projection(p_ty)) => {
169 p_ty.substitution.walk_mut_binders(f, binders);
170 }
171 TyKind::Dyn(dyn_ty) => {
172 for p in make_mut_slice(dyn_ty.bounds.skip_binders_mut().interned_mut()) {
173 p.walk_mut_binders(f, binders.shifted_in());
174 }
175 }
176 TyKind::Alias(AliasTy::Opaque(o_ty)) => {
177 o_ty.substitution.walk_mut_binders(f, binders);
178 } 43 }
179 TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => { 44 TyKind::Adt(_, substs)
180 ty.walk_mut_binders(f, binders); 45 | TyKind::FnDef(_, substs)
181 } 46 | TyKind::Tuple(_, substs)
182 _ => { 47 | TyKind::OpaqueType(_, substs)
183 if let Some(substs) = self.substs_mut() { 48 | TyKind::AssociatedType(_, substs)
184 substs.walk_mut_binders(f, binders); 49 | TyKind::Closure(.., substs) => {
185 } 50 substs.walk(f);
186 } 51 }
52 _ => {}
187 } 53 }
188 f(self, binders); 54 f(self);
189 } 55 }
190} 56}
191 57
@@ -195,43 +61,18 @@ impl<T: TypeWalk> TypeWalk for Vec<T> {
195 t.walk(f); 61 t.walk(f);
196 } 62 }
197 } 63 }
198 fn walk_mut_binders(
199 &mut self,
200 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
201 binders: DebruijnIndex,
202 ) {
203 for t in self {
204 t.walk_mut_binders(f, binders);
205 }
206 }
207} 64}
208 65
209impl TypeWalk for OpaqueTy { 66impl TypeWalk for OpaqueTy {
210 fn walk(&self, f: &mut impl FnMut(&Ty)) { 67 fn walk(&self, f: &mut impl FnMut(&Ty)) {
211 self.substitution.walk(f); 68 self.substitution.walk(f);
212 } 69 }
213
214 fn walk_mut_binders(
215 &mut self,
216 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
217 binders: DebruijnIndex,
218 ) {
219 self.substitution.walk_mut_binders(f, binders);
220 }
221} 70}
222 71
223impl TypeWalk for ProjectionTy { 72impl TypeWalk for ProjectionTy {
224 fn walk(&self, f: &mut impl FnMut(&Ty)) { 73 fn walk(&self, f: &mut impl FnMut(&Ty)) {
225 self.substitution.walk(f); 74 self.substitution.walk(f);
226 } 75 }
227
228 fn walk_mut_binders(
229 &mut self,
230 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
231 binders: DebruijnIndex,
232 ) {
233 self.substitution.walk_mut_binders(f, binders);
234 }
235} 76}
236 77
237impl TypeWalk for AliasTy { 78impl TypeWalk for AliasTy {
@@ -241,17 +82,6 @@ impl TypeWalk for AliasTy {
241 AliasTy::Opaque(it) => it.walk(f), 82 AliasTy::Opaque(it) => it.walk(f),
242 } 83 }
243 } 84 }
244
245 fn walk_mut_binders(
246 &mut self,
247 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
248 binders: DebruijnIndex,
249 ) {
250 match self {
251 AliasTy::Projection(it) => it.walk_mut_binders(f, binders),
252 AliasTy::Opaque(it) => it.walk_mut_binders(f, binders),
253 }
254 }
255} 85}
256 86
257impl TypeWalk for GenericArg { 87impl TypeWalk for GenericArg {
@@ -260,18 +90,7 @@ impl TypeWalk for GenericArg {
260 GenericArgData::Ty(ty) => { 90 GenericArgData::Ty(ty) => {
261 ty.walk(f); 91 ty.walk(f);
262 } 92 }
263 } 93 _ => {}
264 }
265
266 fn walk_mut_binders(
267 &mut self,
268 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
269 binders: DebruijnIndex,
270 ) {
271 match self.interned_mut() {
272 GenericArgData::Ty(ty) => {
273 ty.walk_mut_binders(f, binders);
274 }
275 } 94 }
276 } 95 }
277} 96}
@@ -282,44 +101,18 @@ impl TypeWalk for Substitution {
282 t.walk(f); 101 t.walk(f);
283 } 102 }
284 } 103 }
285
286 fn walk_mut_binders(
287 &mut self,
288 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
289 binders: DebruijnIndex,
290 ) {
291 for t in self.interned_mut() {
292 t.walk_mut_binders(f, binders);
293 }
294 }
295} 104}
296 105
297impl<T: TypeWalk> TypeWalk for Binders<T> { 106impl<T: TypeWalk + HasInterner<Interner = Interner>> TypeWalk for Binders<T> {
298 fn walk(&self, f: &mut impl FnMut(&Ty)) { 107 fn walk(&self, f: &mut impl FnMut(&Ty)) {
299 self.skip_binders().walk(f); 108 self.skip_binders().walk(f);
300 } 109 }
301
302 fn walk_mut_binders(
303 &mut self,
304 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
305 binders: DebruijnIndex,
306 ) {
307 self.skip_binders_mut().walk_mut_binders(f, binders.shifted_in())
308 }
309} 110}
310 111
311impl TypeWalk for TraitRef { 112impl TypeWalk for TraitRef {
312 fn walk(&self, f: &mut impl FnMut(&Ty)) { 113 fn walk(&self, f: &mut impl FnMut(&Ty)) {
313 self.substitution.walk(f); 114 self.substitution.walk(f);
314 } 115 }
315
316 fn walk_mut_binders(
317 &mut self,
318 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
319 binders: DebruijnIndex,
320 ) {
321 self.substitution.walk_mut_binders(f, binders);
322 }
323} 116}
324 117
325impl TypeWalk for WhereClause { 118impl TypeWalk for WhereClause {
@@ -327,17 +120,7 @@ impl TypeWalk for WhereClause {
327 match self { 120 match self {
328 WhereClause::Implemented(trait_ref) => trait_ref.walk(f), 121 WhereClause::Implemented(trait_ref) => trait_ref.walk(f),
329 WhereClause::AliasEq(alias_eq) => alias_eq.walk(f), 122 WhereClause::AliasEq(alias_eq) => alias_eq.walk(f),
330 } 123 _ => {}
331 }
332
333 fn walk_mut_binders(
334 &mut self,
335 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
336 binders: DebruijnIndex,
337 ) {
338 match self {
339 WhereClause::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders),
340 WhereClause::AliasEq(alias_eq) => alias_eq.walk_mut_binders(f, binders),
341 } 124 }
342 } 125 }
343} 126}
@@ -348,16 +131,6 @@ impl TypeWalk for CallableSig {
348 t.walk(f); 131 t.walk(f);
349 } 132 }
350 } 133 }
351
352 fn walk_mut_binders(
353 &mut self,
354 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
355 binders: DebruijnIndex,
356 ) {
357 for t in make_mut_slice(&mut self.params_and_return) {
358 t.walk_mut_binders(f, binders);
359 }
360 }
361} 134}
362 135
363impl TypeWalk for AliasEq { 136impl TypeWalk for AliasEq {
@@ -368,16 +141,10 @@ impl TypeWalk for AliasEq {
368 AliasTy::Opaque(opaque) => opaque.walk(f), 141 AliasTy::Opaque(opaque) => opaque.walk(f),
369 } 142 }
370 } 143 }
144}
371 145
372 fn walk_mut_binders( 146impl TypeWalk for FnSubst<Interner> {
373 &mut self, 147 fn walk(&self, f: &mut impl FnMut(&Ty)) {
374 f: &mut impl FnMut(&mut Ty, DebruijnIndex), 148 self.0.walk(f)
375 binders: DebruijnIndex,
376 ) {
377 self.ty.walk_mut_binders(f, binders);
378 match &mut self.alias {
379 AliasTy::Projection(projection_ty) => projection_ty.walk_mut_binders(f, binders),
380 AliasTy::Opaque(opaque) => opaque.walk_mut_binders(f, binders),
381 }
382 } 149 }
383} 150}
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs
index dd42116a7..0ace80a1e 100644
--- a/crates/ide/src/diagnostics.rs
+++ b/crates/ide/src/diagnostics.rs
@@ -20,7 +20,7 @@ use itertools::Itertools;
20use rustc_hash::FxHashSet; 20use rustc_hash::FxHashSet;
21use syntax::{ 21use syntax::{
22 ast::{self, AstNode}, 22 ast::{self, AstNode},
23 SyntaxNode, SyntaxNodePtr, TextRange, 23 SyntaxNode, SyntaxNodePtr, TextRange, TextSize,
24}; 24};
25use text_edit::TextEdit; 25use text_edit::TextEdit;
26use unlinked_file::UnlinkedFile; 26use unlinked_file::UnlinkedFile;
@@ -159,14 +159,16 @@ pub(crate) fn diagnostics(
159 ); 159 );
160 }) 160 })
161 .on::<UnlinkedFile, _>(|d| { 161 .on::<UnlinkedFile, _>(|d| {
162 // Limit diagnostic to the first few characters in the file. This matches how VS Code
163 // renders it with the full span, but on other editors, and is less invasive.
164 let range = sema.diagnostics_display_range(d.display_source()).range;
165 let range = range.intersect(TextRange::up_to(TextSize::of("..."))).unwrap_or(range);
166
162 // Override severity and mark as unused. 167 // Override severity and mark as unused.
163 res.borrow_mut().push( 168 res.borrow_mut().push(
164 Diagnostic::hint( 169 Diagnostic::hint(range, d.message())
165 sema.diagnostics_display_range(d.display_source()).range, 170 .with_fix(d.fix(&sema))
166 d.message(), 171 .with_code(Some(d.code())),
167 )
168 .with_fix(d.fix(&sema))
169 .with_code(Some(d.code())),
170 ); 172 );
171 }) 173 })
172 .on::<hir::diagnostics::UnresolvedProcMacro, _>(|d| { 174 .on::<hir::diagnostics::UnresolvedProcMacro, _>(|d| {
diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs
index 9eeabbeda..be0ee03bf 100644
--- a/crates/ide/src/expand_macro.rs
+++ b/crates/ide/src/expand_macro.rs
@@ -1,3 +1,5 @@
1use std::iter;
2
1use hir::Semantics; 3use hir::Semantics;
2use ide_db::RootDatabase; 4use ide_db::RootDatabase;
3use syntax::{ 5use syntax::{
@@ -91,24 +93,42 @@ fn insert_whitespaces(syn: SyntaxNode) -> String {
91 let is_last = 93 let is_last =
92 |f: fn(SyntaxKind) -> bool, default| -> bool { last.map(f).unwrap_or(default) }; 94 |f: fn(SyntaxKind) -> bool, default| -> bool { last.map(f).unwrap_or(default) };
93 95
94 res += &match token.kind() { 96 match token.kind() {
95 k if is_text(k) && is_next(|it| !it.is_punct(), true) => token.text().to_string() + " ", 97 k if is_text(k) && is_next(|it| !it.is_punct(), true) => {
98 res.push_str(token.text());
99 res.push(' ');
100 }
96 L_CURLY if is_next(|it| it != R_CURLY, true) => { 101 L_CURLY if is_next(|it| it != R_CURLY, true) => {
97 indent += 1; 102 indent += 1;
98 let leading_space = if is_last(is_text, false) { " " } else { "" }; 103 if is_last(is_text, false) {
99 format!("{}{{\n{}", leading_space, " ".repeat(indent)) 104 res.push(' ');
105 }
106 res.push_str("{\n");
107 res.extend(iter::repeat(" ").take(2 * indent));
100 } 108 }
101 R_CURLY if is_last(|it| it != L_CURLY, true) => { 109 R_CURLY if is_last(|it| it != L_CURLY, true) => {
102 indent = indent.saturating_sub(1); 110 indent = indent.saturating_sub(1);
103 format!("\n{}}}", " ".repeat(indent)) 111 res.push('\n');
112 res.extend(iter::repeat(" ").take(2 * indent));
113 res.push_str("}");
104 } 114 }
105 R_CURLY => format!("}}\n{}", " ".repeat(indent)), 115 R_CURLY => {
106 T![;] => format!(";\n{}", " ".repeat(indent)), 116 res.push_str("}\n");
107 T![->] => " -> ".to_string(), 117 res.extend(iter::repeat(" ").take(2 * indent));
108 T![=] => " = ".to_string(), 118 }
109 T![=>] => " => ".to_string(), 119 LIFETIME_IDENT if is_next(|it| it == IDENT, true) => {
110 _ => token.text().to_string(), 120 res.push_str(token.text());
111 }; 121 res.push(' ');
122 }
123 T![;] => {
124 res.push_str(";\n");
125 res.extend(iter::repeat(" ").take(2 * indent));
126 }
127 T![->] => res.push_str(" -> "),
128 T![=] => res.push_str(" = "),
129 T![=>] => res.push_str(" => "),
130 _ => res.push_str(token.text()),
131 }
112 132
113 last = Some(token.kind()); 133 last = Some(token.kind());
114 } 134 }
diff --git a/crates/ide/src/folding_ranges.rs b/crates/ide/src/folding_ranges.rs
index 153726ce8..2b9ed123c 100644
--- a/crates/ide/src/folding_ranges.rs
+++ b/crates/ide/src/folding_ranges.rs
@@ -19,6 +19,7 @@ pub enum FoldKind {
19 Region, 19 Region,
20 Consts, 20 Consts,
21 Statics, 21 Statics,
22 Array,
22} 23}
23 24
24#[derive(Debug)] 25#[derive(Debug)]
@@ -119,6 +120,7 @@ fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> {
119 match kind { 120 match kind {
120 COMMENT => Some(FoldKind::Comment), 121 COMMENT => Some(FoldKind::Comment),
121 ARG_LIST | PARAM_LIST => Some(FoldKind::ArgList), 122 ARG_LIST | PARAM_LIST => Some(FoldKind::ArgList),
123 ARRAY_EXPR => Some(FoldKind::Array),
122 ASSOC_ITEM_LIST 124 ASSOC_ITEM_LIST
123 | RECORD_FIELD_LIST 125 | RECORD_FIELD_LIST
124 | RECORD_PAT_FIELD_LIST 126 | RECORD_PAT_FIELD_LIST
@@ -269,6 +271,7 @@ mod tests {
269 FoldKind::Region => "region", 271 FoldKind::Region => "region",
270 FoldKind::Consts => "consts", 272 FoldKind::Consts => "consts",
271 FoldKind::Statics => "statics", 273 FoldKind::Statics => "statics",
274 FoldKind::Array => "array",
272 }; 275 };
273 assert_eq!(kind, &attr.unwrap()); 276 assert_eq!(kind, &attr.unwrap());
274 } 277 }
@@ -465,6 +468,20 @@ fn foo<fold arglist>(
465 } 468 }
466 469
467 #[test] 470 #[test]
471 fn fold_multiline_array() {
472 check(
473 r#"
474const FOO: [usize; 4] = <fold array>[
475 1,
476 2,
477 3,
478 4,
479]</fold>;
480"#,
481 )
482 }
483
484 #[test]
468 fn fold_region() { 485 fn fold_region() {
469 check( 486 check(
470 r#" 487 r#"
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs
index 5ccb84714..e921784bf 100644
--- a/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/crates/ide/src/syntax_highlighting/highlight.rs
@@ -323,8 +323,18 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight {
323 hir::ModuleDef::Trait(_) => HlTag::Symbol(SymbolKind::Trait), 323 hir::ModuleDef::Trait(_) => HlTag::Symbol(SymbolKind::Trait),
324 hir::ModuleDef::TypeAlias(type_) => { 324 hir::ModuleDef::TypeAlias(type_) => {
325 let mut h = Highlight::new(HlTag::Symbol(SymbolKind::TypeAlias)); 325 let mut h = Highlight::new(HlTag::Symbol(SymbolKind::TypeAlias));
326 if type_.as_assoc_item(db).is_some() { 326 if let Some(item) = type_.as_assoc_item(db) {
327 h |= HlMod::Associated 327 h |= HlMod::Associated;
328 match item.container(db) {
329 AssocItemContainer::Impl(i) => {
330 if i.trait_(db).is_some() {
331 h |= HlMod::Trait;
332 }
333 }
334 AssocItemContainer::Trait(_t) => {
335 h |= HlMod::Trait;
336 }
337 }
328 } 338 }
329 return h; 339 return h;
330 } 340 }
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs
index 1b02857ec..de2d22ac7 100644
--- a/crates/ide/src/syntax_highlighting/tests.rs
+++ b/crates/ide/src/syntax_highlighting/tests.rs
@@ -1,5 +1,8 @@
1use std::time::Instant;
2
1use expect_test::{expect_file, ExpectFile}; 3use expect_test::{expect_file, ExpectFile};
2use ide_db::SymbolKind; 4use ide_db::SymbolKind;
5use stdx::format_to;
3use test_utils::{bench, bench_fixture, skip_slow_tests}; 6use test_utils::{bench, bench_fixture, skip_slow_tests};
4 7
5use crate::{fixture, FileRange, HlTag, TextRange}; 8use crate::{fixture, FileRange, HlTag, TextRange};
@@ -258,6 +261,99 @@ fn benchmark_syntax_highlighting_long_struct() {
258} 261}
259 262
260#[test] 263#[test]
264fn syntax_highlighting_not_quadratic() {
265 if skip_slow_tests() {
266 return;
267 }
268
269 let mut measures = Vec::new();
270 for i in 6..=10 {
271 let n = 1 << i;
272 let fixture = bench_fixture::big_struct_n(n);
273 let (analysis, file_id) = fixture::file(&fixture);
274
275 let time = Instant::now();
276
277 let hash = analysis
278 .highlight(file_id)
279 .unwrap()
280 .iter()
281 .filter(|it| it.highlight.tag == HlTag::Symbol(SymbolKind::Struct))
282 .count();
283 assert!(hash > n as usize);
284
285 let elapsed = time.elapsed();
286 measures.push((n as f64, elapsed.as_millis() as f64))
287 }
288
289 assert_linear(&measures)
290}
291
292/// Checks that a set of measurements looks like a liner function rather than
293/// like a quadratic function. Algorithm:
294///
295/// 1. Linearly scale input to be in [0; 1)
296/// 2. Using linear regression, compute the best linear function approximating
297/// the input.
298/// 3. Compute RMSE and maximal absolute error.
299/// 4. Check that errors are within tolerances and that the constant term is not
300/// too negative.
301///
302/// Ideally, we should use a proper "model selection" to directly compare
303/// quadratic and linear models, but that sounds rather complicated:
304///
305/// https://stats.stackexchange.com/questions/21844/selecting-best-model-based-on-linear-quadratic-and-cubic-fit-of-data
306fn assert_linear(xy: &[(f64, f64)]) {
307 let (mut xs, mut ys): (Vec<_>, Vec<_>) = xy.iter().copied().unzip();
308 normalize(&mut xs);
309 normalize(&mut ys);
310 let xy = xs.iter().copied().zip(ys.iter().copied());
311
312 // Linear regression: finding a and b to fit y = a + b*x.
313
314 let mean_x = mean(&xs);
315 let mean_y = mean(&ys);
316
317 let b = {
318 let mut num = 0.0;
319 let mut denom = 0.0;
320 for (x, y) in xy.clone() {
321 num += (x - mean_x) * (y - mean_y);
322 denom += (x - mean_x).powi(2);
323 }
324 num / denom
325 };
326
327 let a = mean_y - b * mean_x;
328
329 let mut plot = format!("y_pred = {:.3} + {:.3} * x\n\nx y y_pred\n", a, b);
330
331 let mut se = 0.0;
332 let mut max_error = 0.0f64;
333 for (x, y) in xy {
334 let y_pred = a + b * x;
335 se += (y - y_pred).powi(2);
336 max_error = max_error.max((y_pred - y).abs());
337
338 format_to!(plot, "{:.3} {:.3} {:.3}\n", x, y, y_pred);
339 }
340
341 let rmse = (se / xs.len() as f64).sqrt();
342 format_to!(plot, "\nrmse = {:.3} max error = {:.3}", rmse, max_error);
343
344 assert!(rmse < 0.05 && max_error < 0.1 && a > -0.1, "\nLooks quadratic\n{}", plot);
345
346 fn normalize(xs: &mut Vec<f64>) {
347 let max = xs.iter().copied().max_by(|a, b| a.partial_cmp(b).unwrap()).unwrap();
348 xs.iter_mut().for_each(|it| *it /= max);
349 }
350
351 fn mean(xs: &[f64]) -> f64 {
352 xs.iter().copied().sum::<f64>() / (xs.len() as f64)
353 }
354}
355
356#[test]
261fn benchmark_syntax_highlighting_parser() { 357fn benchmark_syntax_highlighting_parser() {
262 if skip_slow_tests() { 358 if skip_slow_tests() {
263 return; 359 return;
diff --git a/crates/ide/src/typing.rs b/crates/ide/src/typing.rs
index 11408d445..1378048e5 100644
--- a/crates/ide/src/typing.rs
+++ b/crates/ide/src/typing.rs
@@ -22,18 +22,19 @@ use ide_db::{
22use syntax::{ 22use syntax::{
23 algo::find_node_at_offset, 23 algo::find_node_at_offset,
24 ast::{self, edit::IndentLevel, AstToken}, 24 ast::{self, edit::IndentLevel, AstToken},
25 AstNode, SourceFile, 25 AstNode, Parse, SourceFile,
26 SyntaxKind::{FIELD_EXPR, METHOD_CALL_EXPR}, 26 SyntaxKind::{FIELD_EXPR, METHOD_CALL_EXPR},
27 TextRange, TextSize, 27 TextRange, TextSize,
28}; 28};
29 29
30use text_edit::TextEdit; 30use text_edit::{Indel, TextEdit};
31 31
32use crate::SourceChange; 32use crate::SourceChange;
33 33
34pub(crate) use on_enter::on_enter; 34pub(crate) use on_enter::on_enter;
35 35
36pub(crate) const TRIGGER_CHARS: &str = ".=>"; 36// Don't forget to add new trigger characters to `server_capabilities` in `caps.rs`.
37pub(crate) const TRIGGER_CHARS: &str = ".=>{";
37 38
38// Feature: On Typing Assists 39// Feature: On Typing Assists
39// 40//
@@ -41,6 +42,7 @@ pub(crate) const TRIGGER_CHARS: &str = ".=>";
41// 42//
42// - typing `let =` tries to smartly add `;` if `=` is followed by an existing expression 43// - typing `let =` tries to smartly add `;` if `=` is followed by an existing expression
43// - typing `.` in a chain method call auto-indents 44// - typing `.` in a chain method call auto-indents
45// - typing `{` in front of an expression inserts a closing `}` after the expression
44// 46//
45// VS Code:: 47// VS Code::
46// 48//
@@ -57,28 +59,79 @@ pub(crate) fn on_char_typed(
57 position: FilePosition, 59 position: FilePosition,
58 char_typed: char, 60 char_typed: char,
59) -> Option<SourceChange> { 61) -> Option<SourceChange> {
60 assert!(TRIGGER_CHARS.contains(char_typed)); 62 if !stdx::always!(TRIGGER_CHARS.contains(char_typed)) {
61 let file = &db.parse(position.file_id).tree(); 63 return None;
62 assert_eq!(file.syntax().text().char_at(position.offset), Some(char_typed)); 64 }
65 let file = &db.parse(position.file_id);
66 if !stdx::always!(file.tree().syntax().text().char_at(position.offset) == Some(char_typed)) {
67 return None;
68 }
63 let edit = on_char_typed_inner(file, position.offset, char_typed)?; 69 let edit = on_char_typed_inner(file, position.offset, char_typed)?;
64 Some(SourceChange::from_text_edit(position.file_id, edit)) 70 Some(SourceChange::from_text_edit(position.file_id, edit))
65} 71}
66 72
67fn on_char_typed_inner(file: &SourceFile, offset: TextSize, char_typed: char) -> Option<TextEdit> { 73fn on_char_typed_inner(
68 assert!(TRIGGER_CHARS.contains(char_typed)); 74 file: &Parse<SourceFile>,
75 offset: TextSize,
76 char_typed: char,
77) -> Option<TextEdit> {
78 if !stdx::always!(TRIGGER_CHARS.contains(char_typed)) {
79 return None;
80 }
69 match char_typed { 81 match char_typed {
70 '.' => on_dot_typed(file, offset), 82 '.' => on_dot_typed(&file.tree(), offset),
71 '=' => on_eq_typed(file, offset), 83 '=' => on_eq_typed(&file.tree(), offset),
72 '>' => on_arrow_typed(file, offset), 84 '>' => on_arrow_typed(&file.tree(), offset),
85 '{' => on_opening_brace_typed(file, offset),
73 _ => unreachable!(), 86 _ => unreachable!(),
74 } 87 }
75} 88}
76 89
90/// Inserts a closing `}` when the user types an opening `{`, wrapping an existing expression in a
91/// block.
92fn on_opening_brace_typed(file: &Parse<SourceFile>, offset: TextSize) -> Option<TextEdit> {
93 if !stdx::always!(file.tree().syntax().text().char_at(offset) == Some('{')) {
94 return None;
95 }
96
97 let brace_token = file.tree().syntax().token_at_offset(offset).right_biased()?;
98
99 // Remove the `{` to get a better parse tree, and reparse
100 let file = file.reparse(&Indel::delete(brace_token.text_range()));
101
102 let mut expr: ast::Expr = find_node_at_offset(file.tree().syntax(), offset)?;
103 if expr.syntax().text_range().start() != offset {
104 return None;
105 }
106
107 // Enclose the outermost expression starting at `offset`
108 while let Some(parent) = expr.syntax().parent() {
109 if parent.text_range().start() != expr.syntax().text_range().start() {
110 break;
111 }
112
113 match ast::Expr::cast(parent) {
114 Some(parent) => expr = parent,
115 None => break,
116 }
117 }
118
119 // If it's a statement in a block, we don't know how many statements should be included
120 if ast::ExprStmt::can_cast(expr.syntax().parent()?.kind()) {
121 return None;
122 }
123
124 // Insert `}` right after the expression.
125 Some(TextEdit::insert(expr.syntax().text_range().end() + TextSize::of("{"), "}".to_string()))
126}
127
77/// Returns an edit which should be applied after `=` was typed. Primarily, 128/// Returns an edit which should be applied after `=` was typed. Primarily,
78/// this works when adding `let =`. 129/// this works when adding `let =`.
79// FIXME: use a snippet completion instead of this hack here. 130// FIXME: use a snippet completion instead of this hack here.
80fn on_eq_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> { 131fn on_eq_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
81 assert_eq!(file.syntax().text().char_at(offset), Some('=')); 132 if !stdx::always!(file.syntax().text().char_at(offset) == Some('=')) {
133 return None;
134 }
82 let let_stmt: ast::LetStmt = find_node_at_offset(file.syntax(), offset)?; 135 let let_stmt: ast::LetStmt = find_node_at_offset(file.syntax(), offset)?;
83 if let_stmt.semicolon_token().is_some() { 136 if let_stmt.semicolon_token().is_some() {
84 return None; 137 return None;
@@ -100,7 +153,9 @@ fn on_eq_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
100 153
101/// Returns an edit which should be applied when a dot ('.') is typed on a blank line, indenting the line appropriately. 154/// Returns an edit which should be applied when a dot ('.') is typed on a blank line, indenting the line appropriately.
102fn on_dot_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> { 155fn on_dot_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
103 assert_eq!(file.syntax().text().char_at(offset), Some('.')); 156 if !stdx::always!(file.syntax().text().char_at(offset) == Some('.')) {
157 return None;
158 }
104 let whitespace = 159 let whitespace =
105 file.syntax().token_at_offset(offset).left_biased().and_then(ast::Whitespace::cast)?; 160 file.syntax().token_at_offset(offset).left_biased().and_then(ast::Whitespace::cast)?;
106 161
@@ -129,7 +184,9 @@ fn on_dot_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
129/// Adds a space after an arrow when `fn foo() { ... }` is turned into `fn foo() -> { ... }` 184/// Adds a space after an arrow when `fn foo() { ... }` is turned into `fn foo() -> { ... }`
130fn on_arrow_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> { 185fn on_arrow_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
131 let file_text = file.syntax().text(); 186 let file_text = file.syntax().text();
132 assert_eq!(file_text.char_at(offset), Some('>')); 187 if !stdx::always!(file_text.char_at(offset) == Some('>')) {
188 return None;
189 }
133 let after_arrow = offset + TextSize::of('>'); 190 let after_arrow = offset + TextSize::of('>');
134 if file_text.char_at(after_arrow) != Some('{') { 191 if file_text.char_at(after_arrow) != Some('{') {
135 return None; 192 return None;
@@ -152,7 +209,7 @@ mod tests {
152 let edit = TextEdit::insert(offset, char_typed.to_string()); 209 let edit = TextEdit::insert(offset, char_typed.to_string());
153 edit.apply(&mut before); 210 edit.apply(&mut before);
154 let parse = SourceFile::parse(&before); 211 let parse = SourceFile::parse(&before);
155 on_char_typed_inner(&parse.tree(), offset, char_typed).map(|it| { 212 on_char_typed_inner(&parse, offset, char_typed).map(|it| {
156 it.apply(&mut before); 213 it.apply(&mut before);
157 before.to_string() 214 before.to_string()
158 }) 215 })
@@ -373,4 +430,85 @@ fn main() {
373 fn adds_space_after_return_type() { 430 fn adds_space_after_return_type() {
374 type_char('>', "fn foo() -$0{ 92 }", "fn foo() -> { 92 }") 431 type_char('>', "fn foo() -$0{ 92 }", "fn foo() -> { 92 }")
375 } 432 }
433
434 #[test]
435 fn adds_closing_brace() {
436 type_char(
437 '{',
438 r#"
439fn f() { match () { _ => $0() } }
440 "#,
441 r#"
442fn f() { match () { _ => {()} } }
443 "#,
444 );
445 type_char(
446 '{',
447 r#"
448fn f() { $0() }
449 "#,
450 r#"
451fn f() { {()} }
452 "#,
453 );
454 type_char(
455 '{',
456 r#"
457fn f() { let x = $0(); }
458 "#,
459 r#"
460fn f() { let x = {()}; }
461 "#,
462 );
463 type_char(
464 '{',
465 r#"
466fn f() { let x = $0a.b(); }
467 "#,
468 r#"
469fn f() { let x = {a.b()}; }
470 "#,
471 );
472 type_char(
473 '{',
474 r#"
475const S: () = $0();
476fn f() {}
477 "#,
478 r#"
479const S: () = {()};
480fn f() {}
481 "#,
482 );
483 type_char(
484 '{',
485 r#"
486const S: () = $0a.b();
487fn f() {}
488 "#,
489 r#"
490const S: () = {a.b()};
491fn f() {}
492 "#,
493 );
494 type_char(
495 '{',
496 r#"
497fn f() {
498 match x {
499 0 => $0(),
500 1 => (),
501 }
502}
503 "#,
504 r#"
505fn f() {
506 match x {
507 0 => {()},
508 1 => (),
509 }
510}
511 "#,
512 );
513 }
376} 514}
diff --git a/crates/ide/src/typing/on_enter.rs b/crates/ide/src/typing/on_enter.rs
index 9144681bf..6f1ce3689 100644
--- a/crates/ide/src/typing/on_enter.rs
+++ b/crates/ide/src/typing/on_enter.rs
@@ -18,6 +18,7 @@ use text_edit::TextEdit;
18// 18//
19// - kbd:[Enter] inside triple-slash comments automatically inserts `///` 19// - kbd:[Enter] inside triple-slash comments automatically inserts `///`
20// - kbd:[Enter] in the middle or after a trailing space in `//` inserts `//` 20// - kbd:[Enter] in the middle or after a trailing space in `//` inserts `//`
21// - kbd:[Enter] inside `//!` doc comments automatically inserts `//!`
21// 22//
22// This action needs to be assigned to shortcut explicitly. 23// This action needs to be assigned to shortcut explicitly.
23// 24//
@@ -187,6 +188,25 @@ fn foo() {
187 } 188 }
188 189
189 #[test] 190 #[test]
191 fn continues_another_doc_comment() {
192 do_check(
193 r#"
194fn main() {
195 //! Documentation for$0 on enter
196 let x = 1 + 1;
197}
198"#,
199 r#"
200fn main() {
201 //! Documentation for
202 //! $0 on enter
203 let x = 1 + 1;
204}
205"#,
206 );
207 }
208
209 #[test]
190 fn continues_code_comment_in_the_middle_of_line() { 210 fn continues_code_comment_in_the_middle_of_line() {
191 do_check( 211 do_check(
192 r" 212 r"
diff --git a/crates/ide_assists/src/handlers/remove_dbg.rs b/crates/ide_assists/src/handlers/remove_dbg.rs
index 6114091f2..c8226550f 100644
--- a/crates/ide_assists/src/handlers/remove_dbg.rs
+++ b/crates/ide_assists/src/handlers/remove_dbg.rs
@@ -1,5 +1,5 @@
1use syntax::{ 1use syntax::{
2 ast::{self, AstNode}, 2 ast::{self, AstNode, AstToken},
3 match_ast, SyntaxElement, TextRange, TextSize, T, 3 match_ast, SyntaxElement, TextRange, TextSize, T,
4}; 4};
5 5
@@ -24,7 +24,39 @@ pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
24 let macro_call = ctx.find_node_at_offset::<ast::MacroCall>()?; 24 let macro_call = ctx.find_node_at_offset::<ast::MacroCall>()?;
25 let new_contents = adjusted_macro_contents(&macro_call)?; 25 let new_contents = adjusted_macro_contents(&macro_call)?;
26 26
27 let macro_text_range = macro_call.syntax().text_range(); 27 let parent = macro_call.syntax().parent();
28
29 let macro_text_range = if let Some(it) = parent.as_ref() {
30 if new_contents.is_empty() {
31 match_ast! {
32 match it {
33 ast::BlockExpr(_it) => {
34 macro_call.syntax()
35 .prev_sibling_or_token()
36 .and_then(whitespace_start)
37 .map(|start| TextRange::new(start, macro_call.syntax().text_range().end()))
38 .unwrap_or(macro_call.syntax().text_range())
39 },
40 ast::ExprStmt(it) => {
41 let start = it
42 .syntax()
43 .prev_sibling_or_token()
44 .and_then(whitespace_start)
45 .unwrap_or(it.syntax().text_range().start());
46 let end = it.syntax().text_range().end();
47
48 TextRange::new(start, end)
49 },
50 _ => macro_call.syntax().text_range()
51 }
52 }
53 } else {
54 macro_call.syntax().text_range()
55 }
56 } else {
57 macro_call.syntax().text_range()
58 };
59
28 let macro_end = if macro_call.semicolon_token().is_some() { 60 let macro_end = if macro_call.semicolon_token().is_some() {
29 macro_text_range.end() - TextSize::of(';') 61 macro_text_range.end() - TextSize::of(';')
30 } else { 62 } else {
@@ -36,11 +68,22 @@ pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
36 "Remove dbg!()", 68 "Remove dbg!()",
37 macro_text_range, 69 macro_text_range,
38 |builder| { 70 |builder| {
39 builder.replace(TextRange::new(macro_text_range.start(), macro_end), new_contents); 71 builder.replace(
72 TextRange::new(macro_text_range.start(), macro_end),
73 if new_contents.is_empty() && parent.and_then(ast::LetStmt::cast).is_some() {
74 ast::make::expr_unit().to_string()
75 } else {
76 new_contents
77 },
78 );
40 }, 79 },
41 ) 80 )
42} 81}
43 82
83fn whitespace_start(it: SyntaxElement) -> Option<TextSize> {
84 Some(it.into_token().and_then(ast::Whitespace::cast)?.syntax().text_range().start())
85}
86
44fn adjusted_macro_contents(macro_call: &ast::MacroCall) -> Option<String> { 87fn adjusted_macro_contents(macro_call: &ast::MacroCall) -> Option<String> {
45 let contents = get_valid_macrocall_contents(&macro_call, "dbg")?; 88 let contents = get_valid_macrocall_contents(&macro_call, "dbg")?;
46 let macro_text_with_brackets = macro_call.token_tree()?.syntax().text(); 89 let macro_text_with_brackets = macro_call.token_tree()?.syntax().text();
@@ -94,15 +137,11 @@ fn get_valid_macrocall_contents(
94 let mut contents_between_brackets = children_with_tokens.collect::<Vec<_>>(); 137 let mut contents_between_brackets = children_with_tokens.collect::<Vec<_>>();
95 let last_child = contents_between_brackets.pop()?; 138 let last_child = contents_between_brackets.pop()?;
96 139
97 if contents_between_brackets.is_empty() { 140 match (first_child.kind(), last_child.kind()) {
98 None 141 (T!['('], T![')']) | (T!['['], T![']']) | (T!['{'], T!['}']) => {
99 } else { 142 Some(contents_between_brackets)
100 match (first_child.kind(), last_child.kind()) {
101 (T!['('], T![')']) | (T!['['], T![']']) | (T!['{'], T!['}']) => {
102 Some(contents_between_brackets)
103 }
104 _ => None,
105 } 143 }
144 _ => None,
106 } 145 }
107} 146}
108 147
@@ -418,4 +457,48 @@ fn main() {
418}"#, 457}"#,
419 ); 458 );
420 } 459 }
460
461 #[test]
462 fn test_remove_empty_dbg() {
463 check_assist(remove_dbg, r#"fn foo() { $0dbg!(); }"#, r#"fn foo() { }"#);
464 check_assist(
465 remove_dbg,
466 r#"
467fn foo() {
468 $0dbg!();
469}
470"#,
471 r#"
472fn foo() {
473}
474"#,
475 );
476 check_assist(
477 remove_dbg,
478 r#"
479fn foo() {
480 let test = $0dbg!();
481}"#,
482 r#"
483fn foo() {
484 let test = ();
485}"#,
486 );
487 check_assist(
488 remove_dbg,
489 r#"
490fn foo() {
491 let t = {
492 println!("Hello, world");
493 $0dbg!()
494 };
495}"#,
496 r#"
497fn foo() {
498 let t = {
499 println!("Hello, world");
500 };
501}"#,
502 );
503 }
421} 504}
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_completion/src/item.rs b/crates/ide_completion/src/item.rs
index cc4ac9ea2..16991b688 100644
--- a/crates/ide_completion/src/item.rs
+++ b/crates/ide_completion/src/item.rs
@@ -29,7 +29,7 @@ pub struct CompletionItem {
29 /// Range of identifier that is being completed. 29 /// Range of identifier that is being completed.
30 /// 30 ///
31 /// It should be used primarily for UI, but we also use this to convert 31 /// It should be used primarily for UI, but we also use this to convert
32 /// genetic TextEdit into LSP's completion edit (see conv.rs). 32 /// generic TextEdit into LSP's completion edit (see conv.rs).
33 /// 33 ///
34 /// `source_range` must contain the completion offset. `insert_text` should 34 /// `source_range` must contain the completion offset. `insert_text` should
35 /// start with what `source_range` points to, or VSCode will filter out the 35 /// start with what `source_range` points to, or VSCode will filter out the
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/paths/src/lib.rs b/crates/paths/src/lib.rs
index 22011cb33..f09ad37e3 100644
--- a/crates/paths/src/lib.rs
+++ b/crates/paths/src/lib.rs
@@ -1,6 +1,7 @@
1//! Thin wrappers around `std::path`, distinguishing between absolute and 1//! Thin wrappers around `std::path`, distinguishing between absolute and
2//! relative paths. 2//! relative paths.
3use std::{ 3use std::{
4 borrow::Borrow,
4 convert::{TryFrom, TryInto}, 5 convert::{TryFrom, TryInto},
5 ops, 6 ops,
6 path::{Component, Path, PathBuf}, 7 path::{Component, Path, PathBuf},
@@ -35,6 +36,12 @@ impl AsRef<AbsPath> for AbsPathBuf {
35 } 36 }
36} 37}
37 38
39impl Borrow<AbsPath> for AbsPathBuf {
40 fn borrow(&self) -> &AbsPath {
41 self.as_path()
42 }
43}
44
38impl TryFrom<PathBuf> for AbsPathBuf { 45impl TryFrom<PathBuf> for AbsPathBuf {
39 type Error = PathBuf; 46 type Error = PathBuf;
40 fn try_from(path_buf: PathBuf) -> Result<AbsPathBuf, PathBuf> { 47 fn try_from(path_buf: PathBuf) -> Result<AbsPathBuf, PathBuf> {
diff --git a/crates/project_model/src/build_data.rs b/crates/project_model/src/build_data.rs
index f7050be4e..0d4d39fef 100644
--- a/crates/project_model/src/build_data.rs
+++ b/crates/project_model/src/build_data.rs
@@ -13,12 +13,12 @@ use cargo_metadata::{BuildScript, Message};
13use itertools::Itertools; 13use itertools::Itertools;
14use paths::{AbsPath, AbsPathBuf}; 14use paths::{AbsPath, AbsPathBuf};
15use rustc_hash::FxHashMap; 15use rustc_hash::FxHashMap;
16use stdx::JodChild; 16use stdx::{format_to, JodChild};
17 17
18use crate::{cfg_flag::CfgFlag, CargoConfig}; 18use crate::{cfg_flag::CfgFlag, CargoConfig};
19 19
20#[derive(Debug, Clone, Default, PartialEq, Eq)] 20#[derive(Debug, Clone, Default, PartialEq, Eq)]
21pub(crate) struct BuildData { 21pub(crate) struct PackageBuildData {
22 /// List of config flags defined by this package's build script 22 /// List of config flags defined by this package's build script
23 pub(crate) cfgs: Vec<CfgFlag>, 23 pub(crate) cfgs: Vec<CfgFlag>,
24 /// List of cargo-related environment variables with their value 24 /// List of cargo-related environment variables with their value
@@ -32,6 +32,17 @@ pub(crate) struct BuildData {
32 pub(crate) proc_macro_dylib_path: Option<AbsPathBuf>, 32 pub(crate) proc_macro_dylib_path: Option<AbsPathBuf>,
33} 33}
34 34
35#[derive(Debug, Default, PartialEq, Eq, Clone)]
36pub(crate) struct WorkspaceBuildData {
37 per_package: FxHashMap<String, PackageBuildData>,
38 error: Option<String>,
39}
40
41#[derive(Debug, Default, PartialEq, Eq, Clone)]
42pub struct BuildDataResult {
43 per_workspace: FxHashMap<AbsPathBuf, WorkspaceBuildData>,
44}
45
35#[derive(Clone, Debug)] 46#[derive(Clone, Debug)]
36pub(crate) struct BuildDataConfig { 47pub(crate) struct BuildDataConfig {
37 cargo_toml: AbsPathBuf, 48 cargo_toml: AbsPathBuf,
@@ -52,13 +63,6 @@ pub struct BuildDataCollector {
52 configs: FxHashMap<AbsPathBuf, BuildDataConfig>, 63 configs: FxHashMap<AbsPathBuf, BuildDataConfig>,
53} 64}
54 65
55#[derive(Debug, Default, PartialEq, Eq)]
56pub struct BuildDataResult {
57 data: FxHashMap<AbsPathBuf, BuildDataMap>,
58}
59
60pub(crate) type BuildDataMap = FxHashMap<String, BuildData>;
61
62impl BuildDataCollector { 66impl BuildDataCollector {
63 pub(crate) fn add_config(&mut self, workspace_root: &AbsPath, config: BuildDataConfig) { 67 pub(crate) fn add_config(&mut self, workspace_root: &AbsPath, config: BuildDataConfig) {
64 self.configs.insert(workspace_root.to_path_buf(), config); 68 self.configs.insert(workspace_root.to_path_buf(), config);
@@ -67,7 +71,7 @@ impl BuildDataCollector {
67 pub fn collect(&mut self, progress: &dyn Fn(String)) -> Result<BuildDataResult> { 71 pub fn collect(&mut self, progress: &dyn Fn(String)) -> Result<BuildDataResult> {
68 let mut res = BuildDataResult::default(); 72 let mut res = BuildDataResult::default();
69 for (path, config) in self.configs.iter() { 73 for (path, config) in self.configs.iter() {
70 res.data.insert( 74 res.per_workspace.insert(
71 path.clone(), 75 path.clone(),
72 collect_from_workspace( 76 collect_from_workspace(
73 &config.cargo_toml, 77 &config.cargo_toml,
@@ -81,9 +85,28 @@ impl BuildDataCollector {
81 } 85 }
82} 86}
83 87
88impl WorkspaceBuildData {
89 pub(crate) fn get(&self, package_id: &str) -> Option<&PackageBuildData> {
90 self.per_package.get(package_id)
91 }
92}
93
84impl BuildDataResult { 94impl BuildDataResult {
85 pub(crate) fn get(&self, root: &AbsPath) -> Option<&BuildDataMap> { 95 pub(crate) fn get(&self, workspace_root: &AbsPath) -> Option<&WorkspaceBuildData> {
86 self.data.get(&root.to_path_buf()) 96 self.per_workspace.get(workspace_root)
97 }
98 pub fn error(&self) -> Option<String> {
99 let mut buf = String::new();
100 for (_workspace_root, build_data) in &self.per_workspace {
101 if let Some(err) = &build_data.error {
102 format_to!(buf, "cargo check failed:\n{}", err);
103 }
104 }
105 if buf.is_empty() {
106 return None;
107 }
108
109 Some(buf)
87 } 110 }
88} 111}
89 112
@@ -102,7 +125,7 @@ fn collect_from_workspace(
102 cargo_features: &CargoConfig, 125 cargo_features: &CargoConfig,
103 packages: &Vec<cargo_metadata::Package>, 126 packages: &Vec<cargo_metadata::Package>,
104 progress: &dyn Fn(String), 127 progress: &dyn Fn(String),
105) -> Result<BuildDataMap> { 128) -> Result<WorkspaceBuildData> {
106 let mut cmd = Command::new(toolchain::cargo()); 129 let mut cmd = Command::new(toolchain::cargo());
107 cmd.args(&["check", "--workspace", "--message-format=json", "--manifest-path"]) 130 cmd.args(&["check", "--workspace", "--message-format=json", "--manifest-path"])
108 .arg(cargo_toml.as_ref()); 131 .arg(cargo_toml.as_ref());
@@ -130,13 +153,13 @@ fn collect_from_workspace(
130 } 153 }
131 } 154 }
132 155
133 cmd.stdout(Stdio::piped()).stderr(Stdio::null()).stdin(Stdio::null()); 156 cmd.stdout(Stdio::piped()).stderr(Stdio::piped()).stdin(Stdio::null());
134 157
135 let mut child = cmd.spawn().map(JodChild)?; 158 let mut child = cmd.spawn().map(JodChild)?;
136 let child_stdout = child.stdout.take().unwrap(); 159 let child_stdout = child.stdout.take().unwrap();
137 let stdout = BufReader::new(child_stdout); 160 let stdout = BufReader::new(child_stdout);
138 161
139 let mut res = BuildDataMap::default(); 162 let mut res = WorkspaceBuildData::default();
140 for message in cargo_metadata::Message::parse_stream(stdout).flatten() { 163 for message in cargo_metadata::Message::parse_stream(stdout).flatten() {
141 match message { 164 match message {
142 Message::BuildScriptExecuted(BuildScript { 165 Message::BuildScriptExecuted(BuildScript {
@@ -154,16 +177,17 @@ fn collect_from_workspace(
154 } 177 }
155 acc 178 acc
156 }; 179 };
157 let res = res.entry(package_id.repr.clone()).or_default(); 180 let package_build_data =
181 res.per_package.entry(package_id.repr.clone()).or_default();
158 // cargo_metadata crate returns default (empty) path for 182 // cargo_metadata crate returns default (empty) path for
159 // older cargos, which is not absolute, so work around that. 183 // older cargos, which is not absolute, so work around that.
160 if !out_dir.as_str().is_empty() { 184 if !out_dir.as_str().is_empty() {
161 let out_dir = AbsPathBuf::assert(PathBuf::from(out_dir.into_os_string())); 185 let out_dir = AbsPathBuf::assert(PathBuf::from(out_dir.into_os_string()));
162 res.out_dir = Some(out_dir); 186 package_build_data.out_dir = Some(out_dir);
163 res.cfgs = cfgs; 187 package_build_data.cfgs = cfgs;
164 } 188 }
165 189
166 res.envs = env; 190 package_build_data.envs = env;
167 } 191 }
168 Message::CompilerArtifact(message) => { 192 Message::CompilerArtifact(message) => {
169 progress(format!("metadata {}", message.target.name)); 193 progress(format!("metadata {}", message.target.name));
@@ -173,8 +197,9 @@ fn collect_from_workspace(
173 // Skip rmeta file 197 // Skip rmeta file
174 if let Some(filename) = message.filenames.iter().find(|name| is_dylib(name)) { 198 if let Some(filename) = message.filenames.iter().find(|name| is_dylib(name)) {
175 let filename = AbsPathBuf::assert(PathBuf::from(&filename)); 199 let filename = AbsPathBuf::assert(PathBuf::from(&filename));
176 let res = res.entry(package_id.repr.clone()).or_default(); 200 let package_build_data =
177 res.proc_macro_dylib_path = Some(filename); 201 res.per_package.entry(package_id.repr.clone()).or_default();
202 package_build_data.proc_macro_dylib_path = Some(filename);
178 } 203 }
179 } 204 }
180 } 205 }
@@ -188,16 +213,25 @@ fn collect_from_workspace(
188 } 213 }
189 214
190 for package in packages { 215 for package in packages {
191 let build_data = res.entry(package.id.repr.clone()).or_default(); 216 let package_build_data = res.per_package.entry(package.id.repr.clone()).or_default();
192 inject_cargo_env(package, build_data); 217 inject_cargo_env(package, package_build_data);
193 if let Some(out_dir) = &build_data.out_dir { 218 if let Some(out_dir) = &package_build_data.out_dir {
194 // NOTE: cargo and rustc seem to hide non-UTF-8 strings from env! and option_env!() 219 // NOTE: cargo and rustc seem to hide non-UTF-8 strings from env! and option_env!()
195 if let Some(out_dir) = out_dir.to_str().map(|s| s.to_owned()) { 220 if let Some(out_dir) = out_dir.to_str().map(|s| s.to_owned()) {
196 build_data.envs.push(("OUT_DIR".to_string(), out_dir)); 221 package_build_data.envs.push(("OUT_DIR".to_string(), out_dir));
197 } 222 }
198 } 223 }
199 } 224 }
200 225
226 let output = child.into_inner().wait_with_output()?;
227 if !output.status.success() {
228 let mut stderr = String::from_utf8(output.stderr).unwrap_or_default();
229 if stderr.is_empty() {
230 stderr = "cargo check failed".to_string();
231 }
232 res.error = Some(stderr)
233 }
234
201 Ok(res) 235 Ok(res)
202} 236}
203 237
@@ -212,7 +246,7 @@ fn is_dylib(path: &Utf8Path) -> bool {
212/// Recreates the compile-time environment variables that Cargo sets. 246/// Recreates the compile-time environment variables that Cargo sets.
213/// 247///
214/// Should be synced with <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates> 248/// Should be synced with <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates>
215fn inject_cargo_env(package: &cargo_metadata::Package, build_data: &mut BuildData) { 249fn inject_cargo_env(package: &cargo_metadata::Package, build_data: &mut PackageBuildData) {
216 let env = &mut build_data.envs; 250 let env = &mut build_data.envs;
217 251
218 // FIXME: Missing variables: 252 // FIXME: Missing variables:
diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs
index 1b53fcc30..2fcd0f8fa 100644
--- a/crates/project_model/src/workspace.rs
+++ b/crates/project_model/src/workspace.rs
@@ -12,7 +12,7 @@ use proc_macro_api::ProcMacroClient;
12use rustc_hash::{FxHashMap, FxHashSet}; 12use rustc_hash::{FxHashMap, FxHashSet};
13 13
14use crate::{ 14use crate::{
15 build_data::{BuildData, BuildDataMap, BuildDataResult}, 15 build_data::{BuildDataResult, PackageBuildData, WorkspaceBuildData},
16 cargo_workspace, 16 cargo_workspace,
17 cfg_flag::CfgFlag, 17 cfg_flag::CfgFlag,
18 rustc_cfg, 18 rustc_cfg,
@@ -354,10 +354,10 @@ fn cargo_to_crate_graph(
354 proc_macro_loader: &dyn Fn(&Path) -> Vec<ProcMacro>, 354 proc_macro_loader: &dyn Fn(&Path) -> Vec<ProcMacro>,
355 load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, 355 load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
356 cargo: &CargoWorkspace, 356 cargo: &CargoWorkspace,
357 build_data_map: Option<&BuildDataMap>, 357 build_data_map: Option<&WorkspaceBuildData>,
358 sysroot: &Sysroot, 358 sysroot: &Sysroot,
359 rustc: &Option<CargoWorkspace>, 359 rustc: &Option<CargoWorkspace>,
360 rustc_build_data_map: Option<&BuildDataMap>, 360 rustc_build_data_map: Option<&WorkspaceBuildData>,
361) -> CrateGraph { 361) -> CrateGraph {
362 let _p = profile::span("cargo_to_crate_graph"); 362 let _p = profile::span("cargo_to_crate_graph");
363 let mut crate_graph = CrateGraph::default(); 363 let mut crate_graph = CrateGraph::default();
@@ -464,7 +464,7 @@ fn handle_rustc_crates(
464 rustc_workspace: &CargoWorkspace, 464 rustc_workspace: &CargoWorkspace,
465 load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, 465 load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
466 crate_graph: &mut CrateGraph, 466 crate_graph: &mut CrateGraph,
467 rustc_build_data_map: Option<&FxHashMap<String, BuildData>>, 467 rustc_build_data_map: Option<&WorkspaceBuildData>,
468 cfg_options: &CfgOptions, 468 cfg_options: &CfgOptions,
469 proc_macro_loader: &dyn Fn(&Path) -> Vec<ProcMacro>, 469 proc_macro_loader: &dyn Fn(&Path) -> Vec<ProcMacro>,
470 pkg_to_lib_crate: &mut FxHashMap<la_arena::Idx<crate::PackageData>, CrateId>, 470 pkg_to_lib_crate: &mut FxHashMap<la_arena::Idx<crate::PackageData>, CrateId>,
@@ -555,7 +555,7 @@ fn handle_rustc_crates(
555fn add_target_crate_root( 555fn add_target_crate_root(
556 crate_graph: &mut CrateGraph, 556 crate_graph: &mut CrateGraph,
557 pkg: &cargo_workspace::PackageData, 557 pkg: &cargo_workspace::PackageData,
558 build_data: Option<&BuildData>, 558 build_data: Option<&PackageBuildData>,
559 cfg_options: &CfgOptions, 559 cfg_options: &CfgOptions,
560 proc_macro_loader: &dyn Fn(&Path) -> Vec<ProcMacro>, 560 proc_macro_loader: &dyn Fn(&Path) -> Vec<ProcMacro>,
561 file_id: FileId, 561 file_id: FileId,
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml
index 3130785cc..0571a912c 100644
--- a/crates/rust-analyzer/Cargo.toml
+++ b/crates/rust-analyzer/Cargo.toml
@@ -22,7 +22,7 @@ env_logger = { version = "0.8.1", default-features = false }
22itertools = "0.10.0" 22itertools = "0.10.0"
23jod-thread = "0.1.0" 23jod-thread = "0.1.0"
24log = "0.4.8" 24log = "0.4.8"
25lsp-types = { version = "0.88.0", features = ["proposed"] } 25lsp-types = { version = "0.89.0", features = ["proposed"] }
26parking_lot = "0.11.0" 26parking_lot = "0.11.0"
27xflags = "0.2.1" 27xflags = "0.2.1"
28oorandom = "11.1.2" 28oorandom = "11.1.2"
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs
index 7a5bcb8c7..3c87782f2 100644
--- a/crates/rust-analyzer/src/caps.rs
+++ b/crates/rust-analyzer/src/caps.rs
@@ -57,7 +57,7 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti
57 document_range_formatting_provider: None, 57 document_range_formatting_provider: None,
58 document_on_type_formatting_provider: Some(DocumentOnTypeFormattingOptions { 58 document_on_type_formatting_provider: Some(DocumentOnTypeFormattingOptions {
59 first_trigger_character: "=".to_string(), 59 first_trigger_character: "=".to_string(),
60 more_trigger_character: Some(vec![".".to_string(), ">".to_string()]), 60 more_trigger_character: Some(vec![".".to_string(), ">".to_string(), "{".to_string()]),
61 }), 61 }),
62 selection_range_provider: Some(SelectionRangeProviderCapability::Simple(true)), 62 selection_range_provider: Some(SelectionRangeProviderCapability::Simple(true)),
63 folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)), 63 folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)),
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index 18fd7ea74..fe9f273b0 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -12,7 +12,7 @@ use hir::{
12 AssocItem, Crate, Function, HasSource, HirDisplay, ModuleDef, 12 AssocItem, Crate, Function, HasSource, HirDisplay, ModuleDef,
13}; 13};
14use hir_def::FunctionId; 14use hir_def::FunctionId;
15use hir_ty::TypeWalk; 15use hir_ty::{TyExt, TypeWalk};
16use ide::{AnalysisHost, RootDatabase}; 16use ide::{AnalysisHost, RootDatabase};
17use ide_db::base_db::{ 17use ide_db::base_db::{
18 salsa::{self, ParallelDatabase}, 18 salsa::{self, ParallelDatabase},
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index cda272fd4..f809667e9 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -445,8 +445,8 @@ impl Config {
445 pub fn hover_actions(&self) -> bool { 445 pub fn hover_actions(&self) -> bool {
446 self.experimental("hoverActions") 446 self.experimental("hoverActions")
447 } 447 }
448 pub fn status_notification(&self) -> bool { 448 pub fn server_status_notification(&self) -> bool {
449 self.experimental("statusNotification") 449 self.experimental("serverStatusNotification")
450 } 450 }
451 451
452 pub fn publish_diagnostics(&self) -> bool { 452 pub fn publish_diagnostics(&self) -> bool {
@@ -656,6 +656,19 @@ impl Config {
656 pub fn code_lens_refresh(&self) -> bool { 656 pub fn code_lens_refresh(&self) -> bool {
657 try_or!(self.caps.workspace.as_ref()?.code_lens.as_ref()?.refresh_support?, false) 657 try_or!(self.caps.workspace.as_ref()?.code_lens.as_ref()?.refresh_support?, false)
658 } 658 }
659 pub fn insert_replace_support(&self) -> bool {
660 try_or!(
661 self.caps
662 .text_document
663 .as_ref()?
664 .completion
665 .as_ref()?
666 .completion_item
667 .as_ref()?
668 .insert_replace_support?,
669 false
670 )
671 }
659} 672}
660 673
661#[derive(Deserialize, Debug, Clone)] 674#[derive(Deserialize, Debug, Clone)]
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs
index 8679c8599..adeb7a97e 100644
--- a/crates/rust-analyzer/src/global_state.rs
+++ b/crates/rust-analyzer/src/global_state.rs
@@ -23,6 +23,7 @@ use crate::{
23 document::DocumentData, 23 document::DocumentData,
24 from_proto, 24 from_proto,
25 line_index::{LineEndings, LineIndex}, 25 line_index::{LineEndings, LineIndex},
26 lsp_ext,
26 main_loop::Task, 27 main_loop::Task,
27 op_queue::OpQueue, 28 op_queue::OpQueue,
28 reload::SourceRootConfig, 29 reload::SourceRootConfig,
@@ -32,20 +33,6 @@ use crate::{
32 Result, 33 Result,
33}; 34};
34 35
35#[derive(Eq, PartialEq, Copy, Clone)]
36pub(crate) enum Status {
37 Loading,
38 Ready { partial: bool },
39 Invalid,
40 NeedsReload,
41}
42
43impl Default for Status {
44 fn default() -> Self {
45 Status::Loading
46 }
47}
48
49// Enforces drop order 36// Enforces drop order
50pub(crate) struct Handle<H, C> { 37pub(crate) struct Handle<H, C> {
51 pub(crate) handle: H, 38 pub(crate) handle: H,
@@ -67,26 +54,36 @@ pub(crate) struct GlobalState {
67 req_queue: ReqQueue, 54 req_queue: ReqQueue,
68 pub(crate) task_pool: Handle<TaskPool<Task>, Receiver<Task>>, 55 pub(crate) task_pool: Handle<TaskPool<Task>, Receiver<Task>>,
69 pub(crate) loader: Handle<Box<dyn vfs::loader::Handle>, Receiver<vfs::loader::Message>>, 56 pub(crate) loader: Handle<Box<dyn vfs::loader::Handle>, Receiver<vfs::loader::Message>>,
70 pub(crate) vfs_config_version: u32,
71 pub(crate) flycheck: Vec<FlycheckHandle>,
72 pub(crate) flycheck_sender: Sender<flycheck::Message>,
73 pub(crate) flycheck_receiver: Receiver<flycheck::Message>,
74 pub(crate) config: Arc<Config>, 57 pub(crate) config: Arc<Config>,
75 pub(crate) analysis_host: AnalysisHost, 58 pub(crate) analysis_host: AnalysisHost,
76 pub(crate) diagnostics: DiagnosticCollection, 59 pub(crate) diagnostics: DiagnosticCollection,
77 pub(crate) mem_docs: FxHashMap<VfsPath, DocumentData>, 60 pub(crate) mem_docs: FxHashMap<VfsPath, DocumentData>,
78 pub(crate) semantic_tokens_cache: Arc<Mutex<FxHashMap<Url, SemanticTokens>>>, 61 pub(crate) semantic_tokens_cache: Arc<Mutex<FxHashMap<Url, SemanticTokens>>>,
79 pub(crate) vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>,
80 pub(crate) shutdown_requested: bool, 62 pub(crate) shutdown_requested: bool,
81 pub(crate) status: Status, 63 pub(crate) last_reported_status: Option<lsp_ext::ServerStatusParams>,
82 pub(crate) source_root_config: SourceRootConfig, 64 pub(crate) source_root_config: SourceRootConfig,
83 pub(crate) proc_macro_client: Option<ProcMacroClient>, 65 pub(crate) proc_macro_client: Option<ProcMacroClient>,
84 66
85 pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>, 67 pub(crate) flycheck: Vec<FlycheckHandle>,
86 pub(crate) fetch_workspaces_queue: OpQueue<(), ()>, 68 pub(crate) flycheck_sender: Sender<flycheck::Message>,
69 pub(crate) flycheck_receiver: Receiver<flycheck::Message>,
87 70
71 pub(crate) vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>,
72 pub(crate) vfs_config_version: u32,
73 pub(crate) vfs_progress_config_version: u32,
74 pub(crate) vfs_progress_n_total: usize,
75 pub(crate) vfs_progress_n_done: usize,
76
77 /// For both `workspaces` and `workspace_build_data`, the field stores the
78 /// data we actually use, while the `OpQueue` stores the result of the last
79 /// fetch.
80 ///
81 /// If the fetch (partially) fails, we do not update the values.
82 pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>,
83 pub(crate) fetch_workspaces_queue: OpQueue<(), Vec<anyhow::Result<ProjectWorkspace>>>,
88 pub(crate) workspace_build_data: Option<BuildDataResult>, 84 pub(crate) workspace_build_data: Option<BuildDataResult>,
89 pub(crate) fetch_build_data_queue: OpQueue<BuildDataCollector, ()>, 85 pub(crate) fetch_build_data_queue:
86 OpQueue<BuildDataCollector, Option<anyhow::Result<BuildDataResult>>>,
90 87
91 latest_requests: Arc<RwLock<LatestRequests>>, 88 latest_requests: Arc<RwLock<LatestRequests>>,
92} 89}
@@ -124,25 +121,32 @@ impl GlobalState {
124 GlobalState { 121 GlobalState {
125 sender, 122 sender,
126 req_queue: ReqQueue::default(), 123 req_queue: ReqQueue::default(),
127 vfs_config_version: 0,
128 task_pool, 124 task_pool,
129 loader, 125 loader,
130 flycheck: Vec::new(),
131 flycheck_sender,
132 flycheck_receiver,
133 config: Arc::new(config), 126 config: Arc::new(config),
134 analysis_host, 127 analysis_host,
135 diagnostics: Default::default(), 128 diagnostics: Default::default(),
136 mem_docs: FxHashMap::default(), 129 mem_docs: FxHashMap::default(),
137 semantic_tokens_cache: Arc::new(Default::default()), 130 semantic_tokens_cache: Arc::new(Default::default()),
138 vfs: Arc::new(RwLock::new((vfs::Vfs::default(), FxHashMap::default()))),
139 shutdown_requested: false, 131 shutdown_requested: false,
140 status: Status::default(), 132 last_reported_status: None,
141 source_root_config: SourceRootConfig::default(), 133 source_root_config: SourceRootConfig::default(),
142 proc_macro_client: None, 134 proc_macro_client: None,
135
136 flycheck: Vec::new(),
137 flycheck_sender,
138 flycheck_receiver,
139
140 vfs: Arc::new(RwLock::new((vfs::Vfs::default(), FxHashMap::default()))),
141 vfs_config_version: 0,
142 vfs_progress_config_version: 0,
143 vfs_progress_n_total: 0,
144 vfs_progress_n_done: 0,
145
143 workspaces: Arc::new(Vec::new()), 146 workspaces: Arc::new(Vec::new()),
144 fetch_workspaces_queue: OpQueue::default(), 147 fetch_workspaces_queue: OpQueue::default(),
145 workspace_build_data: None, 148 workspace_build_data: None,
149
146 fetch_build_data_queue: OpQueue::default(), 150 fetch_build_data_queue: OpQueue::default(),
147 latest_requests: Default::default(), 151 latest_requests: Default::default(),
148 } 152 }
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 4d10a2ead..edfa42eb5 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -231,7 +231,6 @@ pub(crate) fn handle_on_enter(
231 Ok(Some(edit)) 231 Ok(Some(edit))
232} 232}
233 233
234// Don't forget to add new trigger characters to `ServerCapabilities` in `caps.rs`.
235pub(crate) fn handle_on_type_formatting( 234pub(crate) fn handle_on_type_formatting(
236 snap: GlobalStateSnapshot, 235 snap: GlobalStateSnapshot,
237 params: lsp_types::DocumentOnTypeFormattingParams, 236 params: lsp_types::DocumentOnTypeFormattingParams,
@@ -665,10 +664,13 @@ pub(crate) fn handle_completion(
665 }; 664 };
666 let line_index = snap.file_line_index(position.file_id)?; 665 let line_index = snap.file_line_index(position.file_id)?;
667 666
667 let insert_replace_support =
668 snap.config.insert_replace_support().then(|| text_document_position.position);
668 let items: Vec<CompletionItem> = items 669 let items: Vec<CompletionItem> = items
669 .into_iter() 670 .into_iter()
670 .flat_map(|item| { 671 .flat_map(|item| {
671 let mut new_completion_items = to_proto::completion_item(&line_index, item.clone()); 672 let mut new_completion_items =
673 to_proto::completion_item(insert_replace_support, &line_index, item.clone());
672 674
673 if completion_config.enable_imports_on_the_fly { 675 if completion_config.enable_imports_on_the_fly {
674 for new_item in &mut new_completion_items { 676 for new_item in &mut new_completion_items {
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs
index 0e1fec209..81a6f22f1 100644
--- a/crates/rust-analyzer/src/lsp_ext.rs
+++ b/crates/rust-analyzer/src/lsp_ext.rs
@@ -241,26 +241,26 @@ pub struct SsrParams {
241 pub selections: Vec<lsp_types::Range>, 241 pub selections: Vec<lsp_types::Range>,
242} 242}
243 243
244pub enum StatusNotification {} 244pub enum ServerStatusNotification {}
245 245
246#[derive(Serialize, Deserialize)] 246impl Notification for ServerStatusNotification {
247#[serde(rename_all = "camelCase")] 247 type Params = ServerStatusParams;
248pub enum Status { 248 const METHOD: &'static str = "experimental/serverStatus";
249 Loading,
250 ReadyPartial,
251 Ready,
252 NeedsReload,
253 Invalid,
254} 249}
255 250
256#[derive(Deserialize, Serialize)] 251#[derive(Deserialize, Serialize, PartialEq, Eq, Clone)]
257pub struct StatusParams { 252pub struct ServerStatusParams {
258 pub status: Status, 253 pub health: Health,
254 pub quiescent: bool,
255 pub message: Option<String>,
259} 256}
260 257
261impl Notification for StatusNotification { 258#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
262 type Params = StatusParams; 259#[serde(rename_all = "camelCase")]
263 const METHOD: &'static str = "rust-analyzer/status"; 260pub enum Health {
261 Ok,
262 Warning,
263 Error,
264} 264}
265 265
266pub enum CodeActionRequest {} 266pub enum CodeActionRequest {}
diff --git a/crates/rust-analyzer/src/lsp_utils.rs b/crates/rust-analyzer/src/lsp_utils.rs
index 2ac487632..73c4193e8 100644
--- a/crates/rust-analyzer/src/lsp_utils.rs
+++ b/crates/rust-analyzer/src/lsp_utils.rs
@@ -150,8 +150,16 @@ pub(crate) fn all_edits_are_disjoint(
150 edit_ranges.push(edit.range); 150 edit_ranges.push(edit.range);
151 } 151 }
152 Some(lsp_types::CompletionTextEdit::InsertAndReplace(edit)) => { 152 Some(lsp_types::CompletionTextEdit::InsertAndReplace(edit)) => {
153 edit_ranges.push(edit.insert); 153 let replace = edit.replace;
154 edit_ranges.push(edit.replace); 154 let insert = edit.insert;
155 if replace.start != insert.start
156 || insert.start > insert.end
157 || insert.end > replace.end
158 {
159 // insert has to be a prefix of replace but it is not
160 return false;
161 }
162 edit_ranges.push(replace);
155 } 163 }
156 None => {} 164 None => {}
157 } 165 }
@@ -314,18 +322,6 @@ mod tests {
314 Some(CompletionTextEdit::InsertAndReplace(InsertReplaceEdit { 322 Some(CompletionTextEdit::InsertAndReplace(InsertReplaceEdit {
315 new_text: "new_text".to_string(), 323 new_text: "new_text".to_string(),
316 insert: disjoint_edit.range, 324 insert: disjoint_edit.range,
317 replace: joint_edit.range,
318 }));
319 completion_with_joint_edits.additional_text_edits = None;
320 assert!(
321 !all_edits_are_disjoint(&completion_with_joint_edits, &[]),
322 "Completion with disjoint edits fails the validation even with empty extra edits"
323 );
324
325 completion_with_joint_edits.text_edit =
326 Some(CompletionTextEdit::InsertAndReplace(InsertReplaceEdit {
327 new_text: "new_text".to_string(),
328 insert: disjoint_edit.range,
329 replace: disjoint_edit_2.range, 325 replace: disjoint_edit_2.range,
330 })); 326 }));
331 completion_with_joint_edits.additional_text_edits = Some(vec![joint_edit]); 327 completion_with_joint_edits.additional_text_edits = Some(vec![joint_edit]);
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index e88f16cc1..47c6c6d77 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -2,6 +2,7 @@
2//! requests/replies and notifications back to the client. 2//! requests/replies and notifications back to the client.
3use std::{ 3use std::{
4 env, fmt, 4 env, fmt,
5 sync::Arc,
5 time::{Duration, Instant}, 6 time::{Duration, Instant},
6}; 7};
7 8
@@ -12,6 +13,7 @@ use ide::{Canceled, FileId};
12use ide_db::base_db::VfsPath; 13use ide_db::base_db::VfsPath;
13use lsp_server::{Connection, Notification, Request, Response}; 14use lsp_server::{Connection, Notification, Request, Response};
14use lsp_types::notification::Notification as _; 15use lsp_types::notification::Notification as _;
16use project_model::BuildDataCollector;
15use vfs::ChangeKind; 17use vfs::ChangeKind;
16 18
17use crate::{ 19use crate::{
@@ -19,7 +21,7 @@ use crate::{
19 dispatch::{NotificationDispatcher, RequestDispatcher}, 21 dispatch::{NotificationDispatcher, RequestDispatcher},
20 document::DocumentData, 22 document::DocumentData,
21 from_proto, 23 from_proto,
22 global_state::{file_id_to_url, url_to_file_id, GlobalState, Status}, 24 global_state::{file_id_to_url, url_to_file_id, GlobalState},
23 handlers, lsp_ext, 25 handlers, lsp_ext,
24 lsp_utils::{apply_document_changes, is_canceled, notification_is, Progress}, 26 lsp_utils::{apply_document_changes, is_canceled, notification_is, Progress},
25 reload::{BuildDataProgress, ProjectWorkspaceProgress}, 27 reload::{BuildDataProgress, ProjectWorkspaceProgress},
@@ -187,7 +189,7 @@ impl GlobalState {
187 log::info!("task queue len: {}", task_queue_len); 189 log::info!("task queue len: {}", task_queue_len);
188 } 190 }
189 191
190 let mut new_status = self.status; 192 let was_quiescent = self.is_quiescent();
191 match event { 193 match event {
192 Event::Lsp(msg) => match msg { 194 Event::Lsp(msg) => match msg {
193 lsp_server::Message::Request(req) => self.on_request(loop_start, req)?, 195 lsp_server::Message::Request(req) => self.on_request(loop_start, req)?,
@@ -227,11 +229,24 @@ impl GlobalState {
227 (Progress::Report, Some(msg)) 229 (Progress::Report, Some(msg))
228 } 230 }
229 ProjectWorkspaceProgress::End(workspaces) => { 231 ProjectWorkspaceProgress::End(workspaces) => {
230 self.fetch_workspaces_completed(); 232 self.fetch_workspaces_completed(workspaces);
231 self.switch_workspaces(workspaces, None); 233
234 let old = Arc::clone(&self.workspaces);
235 self.switch_workspaces();
236 let workspaces_updated = !Arc::ptr_eq(&old, &self.workspaces);
237
238 if self.config.run_build_scripts() && workspaces_updated {
239 let mut collector = BuildDataCollector::default();
240 for ws in self.workspaces.iter() {
241 ws.collect_build_data_configs(&mut collector);
242 }
243 self.fetch_build_data_request(collector)
244 }
245
232 (Progress::End, None) 246 (Progress::End, None)
233 } 247 }
234 }; 248 };
249
235 self.report_progress("fetching", state, msg, None); 250 self.report_progress("fetching", state, msg, None);
236 } 251 }
237 Task::FetchBuildData(progress) => { 252 Task::FetchBuildData(progress) => {
@@ -240,19 +255,21 @@ impl GlobalState {
240 BuildDataProgress::Report(msg) => { 255 BuildDataProgress::Report(msg) => {
241 (Some(Progress::Report), Some(msg)) 256 (Some(Progress::Report), Some(msg))
242 } 257 }
243 BuildDataProgress::End(collector) => { 258 BuildDataProgress::End(build_data_result) => {
244 self.fetch_build_data_completed(); 259 self.fetch_build_data_completed(build_data_result);
245 let workspaces = 260
246 (*self.workspaces).clone().into_iter().map(Ok).collect(); 261 self.switch_workspaces();
247 self.switch_workspaces(workspaces, Some(collector)); 262
248 (Some(Progress::End), None) 263 (Some(Progress::End), None)
249 } 264 }
250 }; 265 };
266
251 if let Some(state) = state { 267 if let Some(state) = state {
252 self.report_progress("loading", state, msg, None); 268 self.report_progress("loading", state, msg, None);
253 } 269 }
254 } 270 }
255 } 271 }
272
256 // Coalesce multiple task events into one loop turn 273 // Coalesce multiple task events into one loop turn
257 task = match self.task_pool.receiver.try_recv() { 274 task = match self.task_pool.receiver.try_recv() {
258 Ok(task) => task, 275 Ok(task) => task,
@@ -298,30 +315,25 @@ impl GlobalState {
298 } 315 }
299 vfs::loader::Message::Progress { n_total, n_done, config_version } => { 316 vfs::loader::Message::Progress { n_total, n_done, config_version } => {
300 always!(config_version <= self.vfs_config_version); 317 always!(config_version <= self.vfs_config_version);
301 if n_total == 0 { 318
302 new_status = Status::Invalid; 319 self.vfs_progress_config_version = config_version;
320 self.vfs_progress_n_total = n_total;
321 self.vfs_progress_n_done = n_done;
322
323 let state = if n_done == 0 {
324 Progress::Begin
325 } else if n_done < n_total {
326 Progress::Report
303 } else { 327 } else {
304 let state = if n_done == 0 { 328 assert_eq!(n_done, n_total);
305 new_status = Status::Loading; 329 Progress::End
306 Progress::Begin 330 };
307 } else if n_done < n_total { 331 self.report_progress(
308 Progress::Report 332 "roots scanned",
309 } else { 333 state,
310 assert_eq!(n_done, n_total); 334 Some(format!("{}/{}", n_done, n_total)),
311 new_status = Status::Ready { 335 Some(Progress::fraction(n_done, n_total)),
312 partial: self.config.run_build_scripts() 336 )
313 && self.workspace_build_data.is_none()
314 || config_version < self.vfs_config_version,
315 };
316 Progress::End
317 };
318 self.report_progress(
319 "roots scanned",
320 state,
321 Some(format!("{}/{}", n_done, n_total)),
322 Some(Progress::fraction(n_done, n_total)),
323 )
324 }
325 } 337 }
326 } 338 }
327 // Coalesce many VFS event into a single loop turn 339 // Coalesce many VFS event into a single loop turn
@@ -397,18 +409,14 @@ impl GlobalState {
397 } 409 }
398 410
399 let state_changed = self.process_changes(); 411 let state_changed = self.process_changes();
400 let prev_status = self.status; 412
401 if prev_status != new_status { 413 if self.is_quiescent() && !was_quiescent {
402 self.transition(new_status);
403 }
404 let is_ready = matches!(self.status, Status::Ready { .. });
405 if prev_status == Status::Loading && is_ready {
406 for flycheck in &self.flycheck { 414 for flycheck in &self.flycheck {
407 flycheck.update(); 415 flycheck.update();
408 } 416 }
409 } 417 }
410 418
411 if is_ready && (state_changed || prev_status == Status::Loading) { 419 if self.is_quiescent() && (!was_quiescent || state_changed) {
412 self.update_file_notifications_on_threadpool(); 420 self.update_file_notifications_on_threadpool();
413 421
414 // Refresh semantic tokens if the client supports it. 422 // Refresh semantic tokens if the client supports it.
@@ -437,9 +445,13 @@ impl GlobalState {
437 } 445 }
438 } 446 }
439 447
440 self.fetch_workspaces_if_needed(); 448 if self.config.cargo_autoreload() {
449 self.fetch_workspaces_if_needed();
450 }
441 self.fetch_build_data_if_needed(); 451 self.fetch_build_data_if_needed();
442 452
453 self.report_new_status_if_needed();
454
443 let loop_duration = loop_start.elapsed(); 455 let loop_duration = loop_start.elapsed();
444 if loop_duration > Duration::from_millis(100) { 456 if loop_duration > Duration::from_millis(100) {
445 log::warn!("overly long loop turn: {:?}", loop_duration); 457 log::warn!("overly long loop turn: {:?}", loop_duration);
@@ -466,18 +478,23 @@ impl GlobalState {
466 return Ok(()); 478 return Ok(());
467 } 479 }
468 480
469 if self.status == Status::Loading && req.method != "shutdown" { 481 // Avoid flashing a bunch of unresolved references during initial load.
482 if self.workspaces.is_empty() && !self.is_quiescent() {
470 self.respond(lsp_server::Response::new_err( 483 self.respond(lsp_server::Response::new_err(
471 req.id, 484 req.id,
472 // FIXME: i32 should impl From<ErrorCode> (from() guarantees lossless conversion) 485 // FIXME: i32 should impl From<ErrorCode> (from() guarantees lossless conversion)
473 lsp_server::ErrorCode::ContentModified as i32, 486 lsp_server::ErrorCode::ContentModified as i32,
474 "Rust Analyzer is still loading...".to_owned(), 487 "waiting for cargo metadata or cargo check".to_owned(),
475 )); 488 ));
476 return Ok(()); 489 return Ok(());
477 } 490 }
478 491
479 RequestDispatcher { req: Some(req), global_state: self } 492 RequestDispatcher { req: Some(req), global_state: self }
480 .on_sync::<lsp_ext::ReloadWorkspace>(|s, ()| Ok(s.fetch_workspaces_request()))? 493 .on_sync::<lsp_ext::ReloadWorkspace>(|s, ()| {
494 s.fetch_workspaces_request();
495 s.fetch_workspaces_if_needed();
496 Ok(())
497 })?
481 .on_sync::<lsp_ext::JoinLines>(|s, p| handlers::handle_join_lines(s.snapshot(), p))? 498 .on_sync::<lsp_ext::JoinLines>(|s, p| handlers::handle_join_lines(s.snapshot(), p))?
482 .on_sync::<lsp_ext::OnEnter>(|s, p| handlers::handle_on_enter(s.snapshot(), p))? 499 .on_sync::<lsp_ext::OnEnter>(|s, p| handlers::handle_on_enter(s.snapshot(), p))?
483 .on_sync::<lsp_types::request::Shutdown>(|s, ()| { 500 .on_sync::<lsp_types::request::Shutdown>(|s, ()| {
diff --git a/crates/rust-analyzer/src/op_queue.rs b/crates/rust-analyzer/src/op_queue.rs
index f71b718bc..1d612a933 100644
--- a/crates/rust-analyzer/src/op_queue.rs
+++ b/crates/rust-analyzer/src/op_queue.rs
@@ -2,27 +2,27 @@
2//! at a time. 2//! at a time.
3 3
4pub(crate) struct OpQueue<Args, Output> { 4pub(crate) struct OpQueue<Args, Output> {
5 op_scheduled: Option<Args>, 5 op_requested: Option<Args>,
6 op_in_progress: bool, 6 op_in_progress: bool,
7 last_op_result: Output, 7 last_op_result: Output,
8} 8}
9 9
10impl<Args, Output: Default> Default for OpQueue<Args, Output> { 10impl<Args, Output: Default> Default for OpQueue<Args, Output> {
11 fn default() -> Self { 11 fn default() -> Self {
12 Self { op_scheduled: None, op_in_progress: false, last_op_result: Default::default() } 12 Self { op_requested: None, op_in_progress: false, last_op_result: Default::default() }
13 } 13 }
14} 14}
15 15
16impl<Args, Output> OpQueue<Args, Output> { 16impl<Args, Output> OpQueue<Args, Output> {
17 pub(crate) fn request_op(&mut self, data: Args) { 17 pub(crate) fn request_op(&mut self, data: Args) {
18 self.op_scheduled = Some(data); 18 self.op_requested = Some(data);
19 } 19 }
20 pub(crate) fn should_start_op(&mut self) -> Option<Args> { 20 pub(crate) fn should_start_op(&mut self) -> Option<Args> {
21 if self.op_in_progress { 21 if self.op_in_progress {
22 return None; 22 return None;
23 } 23 }
24 self.op_in_progress = self.op_scheduled.is_some(); 24 self.op_in_progress = self.op_requested.is_some();
25 self.op_scheduled.take() 25 self.op_requested.take()
26 } 26 }
27 pub(crate) fn op_completed(&mut self, result: Output) { 27 pub(crate) fn op_completed(&mut self, result: Output) {
28 assert!(self.op_in_progress); 28 assert!(self.op_in_progress);
@@ -34,4 +34,10 @@ impl<Args, Output> OpQueue<Args, Output> {
34 pub(crate) fn last_op_result(&self) -> &Output { 34 pub(crate) fn last_op_result(&self) -> &Output {
35 &self.last_op_result 35 &self.last_op_result
36 } 36 }
37 pub(crate) fn op_in_progress(&self) -> bool {
38 self.op_in_progress
39 }
40 pub(crate) fn op_requested(&self) -> bool {
41 self.op_requested.is_some()
42 }
37} 43}
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index d12f891bb..d0cc1b61a 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -9,11 +9,10 @@ use vfs::{file_set::FileSetConfig, AbsPath, AbsPathBuf, ChangeKind};
9 9
10use crate::{ 10use crate::{
11 config::{Config, FilesWatcher, LinkedProject}, 11 config::{Config, FilesWatcher, LinkedProject},
12 global_state::{GlobalState, Status}, 12 global_state::GlobalState,
13 lsp_ext, 13 lsp_ext,
14 main_loop::Task, 14 main_loop::Task,
15}; 15};
16use lsp_ext::StatusParams;
17 16
18#[derive(Debug)] 17#[derive(Debug)]
19pub(crate) enum ProjectWorkspaceProgress { 18pub(crate) enum ProjectWorkspaceProgress {
@@ -30,6 +29,13 @@ pub(crate) enum BuildDataProgress {
30} 29}
31 30
32impl GlobalState { 31impl GlobalState {
32 pub(crate) fn is_quiescent(&self) -> bool {
33 !(self.fetch_workspaces_queue.op_in_progress()
34 || self.fetch_build_data_queue.op_in_progress()
35 || self.vfs_progress_config_version < self.vfs_config_version
36 || self.vfs_progress_n_done < self.vfs_progress_n_total)
37 }
38
33 pub(crate) fn update_configuration(&mut self, config: Config) { 39 pub(crate) fn update_configuration(&mut self, config: Config) {
34 let _p = profile::span("GlobalState::update_configuration"); 40 let _p = profile::span("GlobalState::update_configuration");
35 let old_config = mem::replace(&mut self.config, Arc::new(config)); 41 let old_config = mem::replace(&mut self.config, Arc::new(config));
@@ -46,25 +52,17 @@ impl GlobalState {
46 if !changes.iter().any(|(path, kind)| is_interesting(path, *kind)) { 52 if !changes.iter().any(|(path, kind)| is_interesting(path, *kind)) {
47 return; 53 return;
48 } 54 }
49 match self.status {
50 Status::Loading | Status::NeedsReload => return,
51 Status::Ready { .. } | Status::Invalid => (),
52 }
53 log::info!( 55 log::info!(
54 "Reloading workspace because of the following changes: {}", 56 "Requesting workspace reload because of the following changes: {}",
55 itertools::join( 57 itertools::join(
56 changes 58 changes
57 .iter() 59 .iter()
58 .filter(|(path, kind)| is_interesting(path, *kind)) 60 .filter(|(path, kind)| is_interesting(path, *kind))
59 .map(|(path, kind)| format!("{}/{:?}", path.display(), kind)), 61 .map(|(path, kind)| format!("{}: {:?}", path.display(), kind)),
60 ", " 62 ", "
61 ) 63 )
62 ); 64 );
63 if self.config.cargo_autoreload() { 65 self.fetch_workspaces_request();
64 self.fetch_workspaces_request();
65 } else {
66 self.transition(Status::NeedsReload);
67 }
68 66
69 fn is_interesting(path: &AbsPath, change_kind: ChangeKind) -> bool { 67 fn is_interesting(path: &AbsPath, change_kind: ChangeKind) -> bool {
70 const IMPLICIT_TARGET_FILES: &[&str] = &["build.rs", "src/main.rs", "src/lib.rs"]; 68 const IMPLICIT_TARGET_FILES: &[&str] = &["build.rs", "src/main.rs", "src/lib.rs"];
@@ -101,46 +99,38 @@ impl GlobalState {
101 false 99 false
102 } 100 }
103 } 101 }
104 pub(crate) fn transition(&mut self, new_status: Status) { 102 pub(crate) fn report_new_status_if_needed(&mut self) {
105 self.status = new_status; 103 if !self.config.server_status_notification() {
106 if self.config.status_notification() { 104 return;
107 let lsp_status = match new_status {
108 Status::Loading => lsp_ext::Status::Loading,
109 Status::Ready { partial: true } => lsp_ext::Status::ReadyPartial,
110 Status::Ready { partial: false } => lsp_ext::Status::Ready,
111 Status::Invalid => lsp_ext::Status::Invalid,
112 Status::NeedsReload => lsp_ext::Status::NeedsReload,
113 };
114 self.send_notification::<lsp_ext::StatusNotification>(StatusParams {
115 status: lsp_status,
116 });
117 } 105 }
118 }
119
120 pub(crate) fn fetch_build_data_request(&mut self, build_data_collector: BuildDataCollector) {
121 self.fetch_build_data_queue.request_op(build_data_collector);
122 }
123 106
124 pub(crate) fn fetch_build_data_if_needed(&mut self) { 107 let mut status = lsp_ext::ServerStatusParams {
125 let mut build_data_collector = match self.fetch_build_data_queue.should_start_op() { 108 health: lsp_ext::Health::Ok,
126 Some(it) => it, 109 quiescent: self.is_quiescent(),
127 None => return, 110 message: None,
128 }; 111 };
129 self.task_pool.handle.spawn_with_sender(move |sender| {
130 sender.send(Task::FetchBuildData(BuildDataProgress::Begin)).unwrap();
131 112
132 let progress = { 113 if let Some(error) = self.build_data_error() {
133 let sender = sender.clone(); 114 status.health = lsp_ext::Health::Warning;
134 move |msg| { 115 status.message = Some(error)
135 sender.send(Task::FetchBuildData(BuildDataProgress::Report(msg))).unwrap() 116 }
136 } 117 if !self.config.cargo_autoreload()
137 }; 118 && self.is_quiescent()
138 let res = build_data_collector.collect(&progress); 119 && self.fetch_workspaces_queue.op_requested()
139 sender.send(Task::FetchBuildData(BuildDataProgress::End(res))).unwrap(); 120 {
140 }); 121 status.health = lsp_ext::Health::Warning;
141 } 122 status.message = Some("Workspace reload required".to_string())
142 pub(crate) fn fetch_build_data_completed(&mut self) { 123 }
143 self.fetch_build_data_queue.op_completed(()) 124
125 if let Some(error) = self.fetch_workspace_error() {
126 status.health = lsp_ext::Health::Error;
127 status.message = Some(error)
128 }
129
130 if self.last_reported_status.as_ref() != Some(&status) {
131 self.last_reported_status = Some(status.clone());
132 self.send_notification::<lsp_ext::ServerStatusNotification>(status);
133 }
144 } 134 }
145 135
146 pub(crate) fn fetch_workspaces_request(&mut self) { 136 pub(crate) fn fetch_workspaces_request(&mut self) {
@@ -194,54 +184,71 @@ impl GlobalState {
194 } 184 }
195 }); 185 });
196 } 186 }
197 pub(crate) fn fetch_workspaces_completed(&mut self) { 187 pub(crate) fn fetch_workspaces_completed(
198 self.fetch_workspaces_queue.op_completed(()) 188 &mut self,
189 workspaces: Vec<anyhow::Result<ProjectWorkspace>>,
190 ) {
191 self.fetch_workspaces_queue.op_completed(workspaces)
192 }
193
194 pub(crate) fn fetch_build_data_request(&mut self, build_data_collector: BuildDataCollector) {
195 self.fetch_build_data_queue.request_op(build_data_collector);
199 } 196 }
197 pub(crate) fn fetch_build_data_if_needed(&mut self) {
198 let mut build_data_collector = match self.fetch_build_data_queue.should_start_op() {
199 Some(it) => it,
200 None => return,
201 };
202 self.task_pool.handle.spawn_with_sender(move |sender| {
203 sender.send(Task::FetchBuildData(BuildDataProgress::Begin)).unwrap();
200 204
201 pub(crate) fn switch_workspaces( 205 let progress = {
206 let sender = sender.clone();
207 move |msg| {
208 sender.send(Task::FetchBuildData(BuildDataProgress::Report(msg))).unwrap()
209 }
210 };
211 let res = build_data_collector.collect(&progress);
212 sender.send(Task::FetchBuildData(BuildDataProgress::End(res))).unwrap();
213 });
214 }
215 pub(crate) fn fetch_build_data_completed(
202 &mut self, 216 &mut self,
203 workspaces: Vec<anyhow::Result<ProjectWorkspace>>, 217 build_data: anyhow::Result<BuildDataResult>,
204 workspace_build_data: Option<anyhow::Result<BuildDataResult>>,
205 ) { 218 ) {
206 let _p = profile::span("GlobalState::switch_workspaces"); 219 self.fetch_build_data_queue.op_completed(Some(build_data))
207 log::info!("will switch workspaces: {:?}", workspaces); 220 }
208 221
209 let mut has_errors = false; 222 pub(crate) fn switch_workspaces(&mut self) {
210 let workspaces = workspaces 223 let _p = profile::span("GlobalState::switch_workspaces");
211 .into_iter() 224 log::info!("will switch workspaces");
212 .filter_map(|res| {
213 res.map_err(|err| {
214 has_errors = true;
215 log::error!("failed to load workspace: {:#}", err);
216 if self.workspaces.is_empty() {
217 self.show_message(
218 lsp_types::MessageType::Error,
219 format!("rust-analyzer failed to load workspace: {:#}", err),
220 );
221 }
222 })
223 .ok()
224 })
225 .collect::<Vec<_>>();
226 225
227 let workspace_build_data = match workspace_build_data { 226 if let Some(error_message) = self.fetch_workspace_error() {
228 Some(Ok(it)) => Some(it), 227 log::error!("failed to switch workspaces: {}", error_message);
229 Some(Err(err)) => { 228 self.show_message(lsp_types::MessageType::Error, error_message);
230 log::error!("failed to fetch build data: {:#}", err); 229 if !self.workspaces.is_empty() {
231 self.show_message(
232 lsp_types::MessageType::Error,
233 format!("rust-analyzer failed to fetch build data: {:#}", err),
234 );
235 return; 230 return;
236 } 231 }
237 None => None, 232 }
238 };
239 233
240 if *self.workspaces == workspaces && self.workspace_build_data == workspace_build_data { 234 if let Some(error_message) = self.build_data_error() {
241 return; 235 log::error!("failed to switch build data: {}", error_message);
236 self.show_message(lsp_types::MessageType::Error, error_message);
242 } 237 }
243 238
244 if !self.workspaces.is_empty() && has_errors { 239 let workspaces = self
240 .fetch_workspaces_queue
241 .last_op_result()
242 .iter()
243 .filter_map(|res| res.as_ref().ok().cloned())
244 .collect::<Vec<_>>();
245
246 let workspace_build_data = match self.fetch_build_data_queue.last_op_result() {
247 Some(Ok(it)) => Some(it.clone()),
248 None | Some(Err(_)) => None,
249 };
250
251 if *self.workspaces == workspaces && self.workspace_build_data == workspace_build_data {
245 return; 252 return;
246 } 253 }
247 254
@@ -337,14 +344,6 @@ impl GlobalState {
337 }; 344 };
338 change.set_crate_graph(crate_graph); 345 change.set_crate_graph(crate_graph);
339 346
340 if self.config.run_build_scripts() && workspace_build_data.is_none() {
341 let mut collector = BuildDataCollector::default();
342 for ws in &workspaces {
343 ws.collect_build_data_configs(&mut collector);
344 }
345 self.fetch_build_data_request(collector)
346 }
347
348 self.source_root_config = project_folders.source_root_config; 347 self.source_root_config = project_folders.source_root_config;
349 self.workspaces = Arc::new(workspaces); 348 self.workspaces = Arc::new(workspaces);
350 self.workspace_build_data = workspace_build_data; 349 self.workspace_build_data = workspace_build_data;
@@ -355,6 +354,32 @@ impl GlobalState {
355 log::info!("did switch workspaces"); 354 log::info!("did switch workspaces");
356 } 355 }
357 356
357 fn fetch_workspace_error(&self) -> Option<String> {
358 let mut buf = String::new();
359
360 for ws in self.fetch_workspaces_queue.last_op_result() {
361 if let Err(err) = ws {
362 stdx::format_to!(buf, "rust-analyzer failed to load workspace: {:#}\n", err);
363 }
364 }
365
366 if buf.is_empty() {
367 return None;
368 }
369
370 Some(buf)
371 }
372
373 fn build_data_error(&self) -> Option<String> {
374 match self.fetch_build_data_queue.last_op_result() {
375 Some(Err(err)) => {
376 Some(format!("rust-analyzer failed to fetch build data: {:#}\n", err))
377 }
378 Some(Ok(data)) => data.error(),
379 None => None,
380 }
381 }
382
358 fn reload_flycheck(&mut self) { 383 fn reload_flycheck(&mut self) {
359 let _p = profile::span("GlobalState::reload_flycheck"); 384 let _p = profile::span("GlobalState::reload_flycheck");
360 let config = match self.config.flycheck() { 385 let config = match self.config.flycheck() {
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index c3820944b..9fac562ff 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -145,6 +145,23 @@ pub(crate) fn text_edit(line_index: &LineIndex, indel: Indel) -> lsp_types::Text
145 lsp_types::TextEdit { range, new_text } 145 lsp_types::TextEdit { range, new_text }
146} 146}
147 147
148pub(crate) fn completion_text_edit(
149 line_index: &LineIndex,
150 insert_replace_support: Option<lsp_types::Position>,
151 indel: Indel,
152) -> lsp_types::CompletionTextEdit {
153 let text_edit = text_edit(line_index, indel);
154 match insert_replace_support {
155 Some(cursor_pos) => lsp_types::InsertReplaceEdit {
156 new_text: text_edit.new_text,
157 insert: lsp_types::Range { start: text_edit.range.start, end: cursor_pos },
158 replace: text_edit.range,
159 }
160 .into(),
161 None => text_edit.into(),
162 }
163}
164
148pub(crate) fn snippet_text_edit( 165pub(crate) fn snippet_text_edit(
149 line_index: &LineIndex, 166 line_index: &LineIndex,
150 is_snippet: bool, 167 is_snippet: bool,
@@ -179,6 +196,7 @@ pub(crate) fn snippet_text_edit_vec(
179} 196}
180 197
181pub(crate) fn completion_item( 198pub(crate) fn completion_item(
199 insert_replace_support: Option<lsp_types::Position>,
182 line_index: &LineIndex, 200 line_index: &LineIndex,
183 item: CompletionItem, 201 item: CompletionItem,
184) -> Vec<lsp_types::CompletionItem> { 202) -> Vec<lsp_types::CompletionItem> {
@@ -190,7 +208,7 @@ pub(crate) fn completion_item(
190 for indel in item.text_edit().iter() { 208 for indel in item.text_edit().iter() {
191 if indel.delete.contains_range(source_range) { 209 if indel.delete.contains_range(source_range) {
192 text_edit = Some(if indel.delete == source_range { 210 text_edit = Some(if indel.delete == source_range {
193 self::text_edit(line_index, indel.clone()) 211 self::completion_text_edit(line_index, insert_replace_support, indel.clone())
194 } else { 212 } else {
195 assert!(source_range.end() == indel.delete.end()); 213 assert!(source_range.end() == indel.delete.end());
196 let range1 = TextRange::new(indel.delete.start(), source_range.start()); 214 let range1 = TextRange::new(indel.delete.start(), source_range.start());
@@ -198,7 +216,7 @@ pub(crate) fn completion_item(
198 let indel1 = Indel::replace(range1, String::new()); 216 let indel1 = Indel::replace(range1, String::new());
199 let indel2 = Indel::replace(range2, indel.insert.clone()); 217 let indel2 = Indel::replace(range2, indel.insert.clone());
200 additional_text_edits.push(self::text_edit(line_index, indel1)); 218 additional_text_edits.push(self::text_edit(line_index, indel1));
201 self::text_edit(line_index, indel2) 219 self::completion_text_edit(line_index, insert_replace_support, indel2)
202 }) 220 })
203 } else { 221 } else {
204 assert!(source_range.intersect(indel.delete).is_none()); 222 assert!(source_range.intersect(indel.delete).is_none());
@@ -213,7 +231,7 @@ pub(crate) fn completion_item(
213 detail: item.detail().map(|it| it.to_string()), 231 detail: item.detail().map(|it| it.to_string()),
214 filter_text: Some(item.lookup().to_string()), 232 filter_text: Some(item.lookup().to_string()),
215 kind: item.kind().map(completion_item_kind), 233 kind: item.kind().map(completion_item_kind),
216 text_edit: Some(text_edit.into()), 234 text_edit: Some(text_edit),
217 additional_text_edits: Some(additional_text_edits), 235 additional_text_edits: Some(additional_text_edits),
218 documentation: item.documentation().map(documentation), 236 documentation: item.documentation().map(documentation),
219 deprecated: Some(item.deprecated()), 237 deprecated: Some(item.deprecated()),
@@ -497,7 +515,8 @@ pub(crate) fn folding_range(
497 | FoldKind::Block 515 | FoldKind::Block
498 | FoldKind::ArgList 516 | FoldKind::ArgList
499 | FoldKind::Consts 517 | FoldKind::Consts
500 | FoldKind::Statics => None, 518 | FoldKind::Statics
519 | FoldKind::Array => None,
501 }; 520 };
502 521
503 let range = range(line_index, fold.range); 522 let range = range(line_index, fold.range);
@@ -1135,7 +1154,7 @@ mod tests {
1135 .unwrap() 1154 .unwrap()
1136 .into_iter() 1155 .into_iter()
1137 .filter(|c| c.label().ends_with("arg")) 1156 .filter(|c| c.label().ends_with("arg"))
1138 .map(|c| completion_item(&line_index, c)) 1157 .map(|c| completion_item(None, &line_index, c))
1139 .flat_map(|comps| comps.into_iter().map(|c| (c.label, c.sort_text))) 1158 .flat_map(|comps| comps.into_iter().map(|c| (c.label, c.sort_text)))
1140 .collect(); 1159 .collect();
1141 expect_test::expect![[r#" 1160 expect_test::expect![[r#"
diff --git a/crates/rust-analyzer/tests/rust-analyzer/support.rs b/crates/rust-analyzer/tests/rust-analyzer/support.rs
index 95bf26f01..8d68f1b7d 100644
--- a/crates/rust-analyzer/tests/rust-analyzer/support.rs
+++ b/crates/rust-analyzer/tests/rust-analyzer/support.rs
@@ -103,7 +103,7 @@ impl<'a> Project<'a> {
103 ..Default::default() 103 ..Default::default()
104 }), 104 }),
105 experimental: Some(json!({ 105 experimental: Some(json!({
106 "statusNotification": true, 106 "serverStatusNotification": true,
107 })), 107 })),
108 ..Default::default() 108 ..Default::default()
109 }, 109 },
@@ -213,13 +213,12 @@ impl Server {
213 } 213 }
214 pub(crate) fn wait_until_workspace_is_loaded(self) -> Server { 214 pub(crate) fn wait_until_workspace_is_loaded(self) -> Server {
215 self.wait_for_message_cond(1, &|msg: &Message| match msg { 215 self.wait_for_message_cond(1, &|msg: &Message| match msg {
216 Message::Notification(n) if n.method == "rust-analyzer/status" => { 216 Message::Notification(n) if n.method == "experimental/serverStatus" => {
217 let status = n 217 let status = n
218 .clone() 218 .clone()
219 .extract::<lsp_ext::StatusParams>("rust-analyzer/status") 219 .extract::<lsp_ext::ServerStatusParams>("experimental/serverStatus")
220 .unwrap() 220 .unwrap();
221 .status; 221 status.quiescent
222 matches!(status, lsp_ext::Status::Ready)
223 } 222 }
224 _ => false, 223 _ => false,
225 }) 224 })
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs
index d26be4853..b0a18d58d 100644
--- a/crates/stdx/src/lib.rs
+++ b/crates/stdx/src/lib.rs
@@ -178,6 +178,7 @@ where
178 start..start + len 178 start..start + len
179} 179}
180 180
181#[repr(transparent)]
181pub struct JodChild(pub process::Child); 182pub struct JodChild(pub process::Child);
182 183
183impl ops::Deref for JodChild { 184impl ops::Deref for JodChild {
@@ -200,6 +201,13 @@ impl Drop for JodChild {
200 } 201 }
201} 202}
202 203
204impl JodChild {
205 pub fn into_inner(self) -> process::Child {
206 // SAFETY: repr transparent
207 unsafe { std::mem::transmute::<JodChild, process::Child>(self) }
208 }
209}
210
203#[cfg(test)] 211#[cfg(test)]
204mod tests { 212mod tests {
205 use super::*; 213 use super::*;
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml
index 10024366e..f09cdf28a 100644
--- a/crates/syntax/Cargo.toml
+++ b/crates/syntax/Cargo.toml
@@ -14,7 +14,7 @@ doctest = false
14cov-mark = { version = "1.1", features = ["thread-local"] } 14cov-mark = { version = "1.1", features = ["thread-local"] }
15itertools = "0.10.0" 15itertools = "0.10.0"
16rowan = "0.13.0-pre.3" 16rowan = "0.13.0-pre.3"
17rustc_lexer = { version = "710.0.0", package = "rustc-ap-rustc_lexer" } 17rustc_lexer = { version = "714.0.0", package = "rustc-ap-rustc_lexer" }
18rustc-hash = "1.1.0" 18rustc-hash = "1.1.0"
19arrayvec = "0.7" 19arrayvec = "0.7"
20once_cell = "1.3.1" 20once_cell = "1.3.1"
diff --git a/crates/test_utils/src/bench_fixture.rs b/crates/test_utils/src/bench_fixture.rs
index 3a37c4473..979156263 100644
--- a/crates/test_utils/src/bench_fixture.rs
+++ b/crates/test_utils/src/bench_fixture.rs
@@ -8,7 +8,10 @@ use crate::project_root;
8 8
9pub fn big_struct() -> String { 9pub fn big_struct() -> String {
10 let n = 1_000; 10 let n = 1_000;
11 big_struct_n(n)
12}
11 13
14pub fn big_struct_n(n: u32) -> String {
12 let mut buf = "pub struct RegisterBlock {".to_string(); 15 let mut buf = "pub struct RegisterBlock {".to_string();
13 for i in 0..n { 16 for i in 0..n {
14 format_to!(buf, " /// Doc comment for {}.\n", i); 17 format_to!(buf, " /// Doc comment for {}.\n", i);
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);
diff --git a/crates/vfs/Cargo.toml b/crates/vfs/Cargo.toml
index c318a68f7..894944b18 100644
--- a/crates/vfs/Cargo.toml
+++ b/crates/vfs/Cargo.toml
@@ -14,3 +14,4 @@ rustc-hash = "1.0"
14fst = "0.4" 14fst = "0.4"
15 15
16paths = { path = "../paths", version = "0.0.0" } 16paths = { path = "../paths", version = "0.0.0" }
17indexmap = "1.6.2"
diff --git a/crates/vfs/src/path_interner.rs b/crates/vfs/src/path_interner.rs
index 2189e5e25..6e049f0d4 100644
--- a/crates/vfs/src/path_interner.rs
+++ b/crates/vfs/src/path_interner.rs
@@ -1,15 +1,22 @@
1//! Maps paths to compact integer ids. We don't care about clearings paths which 1//! Maps paths to compact integer ids. We don't care about clearings paths which
2//! no longer exist -- the assumption is total size of paths we ever look at is 2//! no longer exist -- the assumption is total size of paths we ever look at is
3//! not too big. 3//! not too big.
4use rustc_hash::FxHashMap; 4use std::hash::BuildHasherDefault;
5
6use indexmap::IndexSet;
7use rustc_hash::FxHasher;
5 8
6use crate::{FileId, VfsPath}; 9use crate::{FileId, VfsPath};
7 10
8/// Structure to map between [`VfsPath`] and [`FileId`]. 11/// Structure to map between [`VfsPath`] and [`FileId`].
9#[derive(Default)]
10pub(crate) struct PathInterner { 12pub(crate) struct PathInterner {
11 map: FxHashMap<VfsPath, FileId>, 13 map: IndexSet<VfsPath, BuildHasherDefault<FxHasher>>,
12 vec: Vec<VfsPath>, 14}
15
16impl Default for PathInterner {
17 fn default() -> Self {
18 Self { map: IndexSet::default() }
19 }
13} 20}
14 21
15impl PathInterner { 22impl PathInterner {
@@ -17,7 +24,7 @@ impl PathInterner {
17 /// 24 ///
18 /// If `path` does not exists in `self`, returns [`None`]. 25 /// If `path` does not exists in `self`, returns [`None`].
19 pub(crate) fn get(&self, path: &VfsPath) -> Option<FileId> { 26 pub(crate) fn get(&self, path: &VfsPath) -> Option<FileId> {
20 self.map.get(path).copied() 27 self.map.get_index_of(path).map(|i| FileId(i as u32))
21 } 28 }
22 29
23 /// Insert `path` in `self`. 30 /// Insert `path` in `self`.
@@ -25,13 +32,9 @@ impl PathInterner {
25 /// - If `path` already exists in `self`, returns its associated id; 32 /// - If `path` already exists in `self`, returns its associated id;
26 /// - Else, returns a newly allocated id. 33 /// - Else, returns a newly allocated id.
27 pub(crate) fn intern(&mut self, path: VfsPath) -> FileId { 34 pub(crate) fn intern(&mut self, path: VfsPath) -> FileId {
28 if let Some(id) = self.get(&path) { 35 let (id, _added) = self.map.insert_full(path);
29 return id; 36 assert!(id < u32::MAX as usize);
30 } 37 FileId(id as u32)
31 let id = FileId(self.vec.len() as u32);
32 self.map.insert(path.clone(), id);
33 self.vec.push(path);
34 id
35 } 38 }
36 39
37 /// Returns the path corresponding to `id`. 40 /// Returns the path corresponding to `id`.
@@ -40,6 +43,6 @@ impl PathInterner {
40 /// 43 ///
41 /// Panics if `id` does not exists in `self`. 44 /// Panics if `id` does not exists in `self`.
42 pub(crate) fn lookup(&self, id: FileId) -> &VfsPath { 45 pub(crate) fn lookup(&self, id: FileId) -> &VfsPath {
43 &self.vec[id.0 as usize] 46 self.map.get_index(id.0 as usize).unwrap()
44 } 47 }
45} 48}