aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/flycheck/Cargo.toml4
-rw-r--r--crates/flycheck/src/lib.rs5
-rw-r--r--crates/hir/src/code_model.rs165
-rw-r--r--crates/hir/src/source_analyzer.rs16
-rw-r--r--crates/hir_def/src/body/lower.rs17
-rw-r--r--crates/hir_def/src/builtin_type.rs132
-rw-r--r--crates/hir_def/src/expr.rs3
-rw-r--r--crates/hir_def/src/find_path.rs59
-rw-r--r--crates/hir_def/src/item_scope.rs22
-rw-r--r--crates/hir_def/src/lib.rs23
-rw-r--r--crates/hir_def/src/nameres.rs12
-rw-r--r--crates/hir_def/src/path/lower.rs13
-rw-r--r--crates/hir_ty/Cargo.toml6
-rw-r--r--crates/hir_ty/src/autoderef.rs11
-rw-r--r--crates/hir_ty/src/diagnostics/expr.rs11
-rw-r--r--crates/hir_ty/src/diagnostics/match_check.rs8
-rw-r--r--crates/hir_ty/src/diagnostics/unsafe_check.rs6
-rw-r--r--crates/hir_ty/src/display.rs206
-rw-r--r--crates/hir_ty/src/infer.rs46
-rw-r--r--crates/hir_ty/src/infer/coerce.rs87
-rw-r--r--crates/hir_ty/src/infer/expr.rs236
-rw-r--r--crates/hir_ty/src/infer/pat.rs34
-rw-r--r--crates/hir_ty/src/infer/unify.rs200
-rw-r--r--crates/hir_ty/src/lib.rs607
-rw-r--r--crates/hir_ty/src/lower.rs88
-rw-r--r--crates/hir_ty/src/method_resolution.rs167
-rw-r--r--crates/hir_ty/src/op.rs50
-rw-r--r--crates/hir_ty/src/primitive.rs160
-rw-r--r--crates/hir_ty/src/tests/simple.rs55
-rw-r--r--crates/hir_ty/src/traits.rs2
-rw-r--r--crates/hir_ty/src/traits/chalk.rs24
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs332
-rw-r--r--crates/ide/src/hover.rs29
-rw-r--r--crates/ide/src/references.rs9
-rw-r--r--crates/ide/src/references/rename.rs9
-rw-r--r--crates/ide_assists/src/handlers/convert_comment_block.rs419
-rw-r--r--crates/ide_assists/src/handlers/replace_for_loop_with_for_each.rs (renamed from crates/ide_assists/src/handlers/convert_for_to_iter_for_each.rs)38
-rw-r--r--crates/ide_assists/src/handlers/replace_let_with_if_let.rs2
-rw-r--r--crates/ide_assists/src/lib.rs14
-rw-r--r--crates/ide_assists/src/tests.rs2
-rw-r--r--crates/ide_assists/src/tests/generated.rs46
-rw-r--r--crates/mbe/Cargo.toml3
-rw-r--r--crates/mbe/src/benchmark.rs2
-rw-r--r--crates/proc_macro_srv/Cargo.toml2
-rw-r--r--crates/proc_macro_srv/src/rustc_server.rs40
-rw-r--r--crates/proc_macro_srv/src/tests/utils.rs3
-rw-r--r--crates/project_model/Cargo.toml10
-rw-r--r--crates/project_model/src/build_data.rs23
-rw-r--r--crates/project_model/src/cargo_workspace.rs9
-rw-r--r--crates/rust-analyzer/Cargo.toml2
-rw-r--r--crates/rust-analyzer/src/bin/args.rs274
-rw-r--r--crates/rust-analyzer/src/bin/flags.rs251
-rw-r--r--crates/rust-analyzer/src/bin/main.rs85
-rw-r--r--crates/rust-analyzer/src/cli/analysis_bench.rs3
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs2
-rw-r--r--crates/rust-analyzer/src/cli/diagnostics.rs3
-rw-r--r--crates/rust-analyzer/src/cli/load_cargo.rs9
-rw-r--r--crates/rust-analyzer/src/cli/ssr.rs4
-rw-r--r--crates/rust-analyzer/src/diagnostics/to_proto.rs2
-rw-r--r--crates/rust-analyzer/tests/rust-analyzer/main.rs18
-rw-r--r--crates/rust-analyzer/tests/rust-analyzer/support.rs12
-rw-r--r--crates/syntax/src/ast/edit.rs11
-rw-r--r--crates/syntax/src/ast/token_ext.rs3
63 files changed, 2238 insertions, 1908 deletions
diff --git a/crates/flycheck/Cargo.toml b/crates/flycheck/Cargo.toml
index 1d19c7886..2a1a21b28 100644
--- a/crates/flycheck/Cargo.toml
+++ b/crates/flycheck/Cargo.toml
@@ -12,9 +12,9 @@ doctest = false
12[dependencies] 12[dependencies]
13crossbeam-channel = "0.5.0" 13crossbeam-channel = "0.5.0"
14log = "0.4.8" 14log = "0.4.8"
15cargo_metadata = "0.12.2" 15cargo_metadata = "0.13"
16serde_json = "1.0.48" 16serde_json = "1.0.48"
17jod-thread = "0.1.1" 17jod-thread = "0.1.1"
18 18
19toolchain = { path = "../toolchain", version = "0.0.0" } 19toolchain = { path = "../toolchain", version = "0.0.0" }
20stdx = { path = "../stdx", version = "0.0.0" } 20stdx = { path = "../stdx", version = "0.0.0" }
diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs
index e04208006..e2a59497a 100644
--- a/crates/flycheck/src/lib.rs
+++ b/crates/flycheck/src/lib.rs
@@ -194,7 +194,7 @@ impl FlycheckActor {
194 cargo_metadata::Message::BuildScriptExecuted(_) 194 cargo_metadata::Message::BuildScriptExecuted(_)
195 | cargo_metadata::Message::BuildFinished(_) 195 | cargo_metadata::Message::BuildFinished(_)
196 | cargo_metadata::Message::TextLine(_) 196 | cargo_metadata::Message::TextLine(_)
197 | cargo_metadata::Message::Unknown => {} 197 | _ => {}
198 }, 198 },
199 } 199 }
200 } 200 }
@@ -329,8 +329,7 @@ impl CargoActor {
329 // Skip certain kinds of messages to only spend time on what's useful 329 // Skip certain kinds of messages to only spend time on what's useful
330 match &message { 330 match &message {
331 cargo_metadata::Message::CompilerArtifact(artifact) if artifact.fresh => (), 331 cargo_metadata::Message::CompilerArtifact(artifact) if artifact.fresh => (),
332 cargo_metadata::Message::BuildScriptExecuted(_) 332 cargo_metadata::Message::BuildScriptExecuted(_) => (),
333 | cargo_metadata::Message::Unknown => (),
334 _ => self.sender.send(message).unwrap(), 333 _ => self.sender.send(message).unwrap(),
335 } 334 }
336 } 335 }
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index b3218833d..fc1a74641 100644
--- a/crates/hir/src/code_model.rs
+++ b/crates/hir/src/code_model.rs
@@ -14,7 +14,7 @@ use hir_def::{
14 per_ns::PerNs, 14 per_ns::PerNs,
15 resolver::{HasResolver, Resolver}, 15 resolver::{HasResolver, Resolver},
16 src::HasSource as _, 16 src::HasSource as _,
17 type_ref::{Mutability, TypeRef}, 17 type_ref::TypeRef,
18 AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, 18 AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId,
19 DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, 19 DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId,
20 LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, 20 LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId,
@@ -31,9 +31,9 @@ use hir_ty::{
31 display::{write_bounds_like_dyn_trait_with_prefix, HirDisplayError, HirFormatter}, 31 display::{write_bounds_like_dyn_trait_with_prefix, HirDisplayError, HirFormatter},
32 method_resolution, 32 method_resolution,
33 traits::{FnTrait, Solution, SolutionVariables}, 33 traits::{FnTrait, Solution, SolutionVariables},
34 ApplicationTy, BoundVar, CallableDefId, Canonical, DebruijnIndex, FnSig, GenericPredicate, 34 AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate,
35 InEnvironment, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, Ty, 35 InEnvironment, Mutability, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs,
36 TyDefId, TyKind, TypeCtor, 36 TraitEnvironment, Ty, TyDefId, TyVariableKind,
37}; 37};
38use rustc_hash::FxHashSet; 38use rustc_hash::FxHashSet;
39use stdx::{format_to, impl_from}; 39use stdx::{format_to, impl_from};
@@ -836,7 +836,7 @@ pub enum Access {
836impl From<Mutability> for Access { 836impl From<Mutability> for Access {
837 fn from(mutability: Mutability) -> Access { 837 fn from(mutability: Mutability) -> Access {
838 match mutability { 838 match mutability {
839 Mutability::Shared => Access::Shared, 839 Mutability::Not => Access::Shared,
840 Mutability::Mut => Access::Exclusive, 840 Mutability::Mut => Access::Exclusive,
841 } 841 }
842 } 842 }
@@ -865,7 +865,10 @@ impl SelfParam {
865 .params 865 .params
866 .first() 866 .first()
867 .map(|param| match *param { 867 .map(|param| match *param {
868 TypeRef::Reference(.., mutability) => mutability.into(), 868 TypeRef::Reference(.., mutability) => match mutability {
869 hir_def::type_ref::Mutability::Shared => Access::Shared,
870 hir_def::type_ref::Mutability::Mut => Access::Exclusive,
871 },
869 _ => Access::Owned, 872 _ => Access::Owned,
870 }) 873 })
871 .unwrap_or(Access::Owned) 874 .unwrap_or(Access::Owned)
@@ -1547,25 +1550,19 @@ impl Type {
1547 } 1550 }
1548 1551
1549 pub fn is_unit(&self) -> bool { 1552 pub fn is_unit(&self) -> bool {
1550 matches!( 1553 matches!(self.ty.value, Ty::Tuple(0, ..))
1551 self.ty.value,
1552 Ty::Apply(ApplicationTy { ctor: TypeCtor::Tuple { cardinality: 0 }, .. })
1553 )
1554 } 1554 }
1555 pub fn is_bool(&self) -> bool { 1555 pub fn is_bool(&self) -> bool {
1556 matches!(self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. })) 1556 matches!(self.ty.value, Ty::Scalar(Scalar::Bool))
1557 } 1557 }
1558 1558
1559 pub fn is_mutable_reference(&self) -> bool { 1559 pub fn is_mutable_reference(&self) -> bool {
1560 matches!( 1560 matches!(self.ty.value, Ty::Ref(Mutability::Mut, ..))
1561 self.ty.value,
1562 Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(Mutability::Mut), .. })
1563 )
1564 } 1561 }
1565 1562
1566 pub fn remove_ref(&self) -> Option<Type> { 1563 pub fn remove_ref(&self) -> Option<Type> {
1567 if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(_), .. }) = self.ty.value { 1564 if let Ty::Ref(.., substs) = &self.ty.value {
1568 self.ty.value.substs().map(|substs| self.derived(substs[0].clone())) 1565 Some(self.derived(substs[0].clone()))
1569 } else { 1566 } else {
1570 None 1567 None
1571 } 1568 }
@@ -1654,14 +1651,14 @@ impl Type {
1654 .build(); 1651 .build();
1655 let predicate = ProjectionPredicate { 1652 let predicate = ProjectionPredicate {
1656 projection_ty: ProjectionTy { associated_ty: alias.id, parameters: subst }, 1653 projection_ty: ProjectionTy { associated_ty: alias.id, parameters: subst },
1657 ty: Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)), 1654 ty: Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)),
1658 }; 1655 };
1659 let goal = Canonical { 1656 let goal = Canonical {
1660 value: InEnvironment::new( 1657 value: InEnvironment::new(
1661 self.ty.environment.clone(), 1658 self.ty.environment.clone(),
1662 Obligation::Projection(predicate), 1659 Obligation::Projection(predicate),
1663 ), 1660 ),
1664 kinds: Arc::new([TyKind::General]), 1661 kinds: Arc::new([TyVariableKind::General]),
1665 }; 1662 };
1666 1663
1667 match db.trait_solve(self.krate, goal)? { 1664 match db.trait_solve(self.krate, goal)? {
@@ -1685,7 +1682,7 @@ impl Type {
1685 1682
1686 pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> { 1683 pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
1687 let def = match self.ty.value { 1684 let def = match self.ty.value {
1688 Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(def), parameters: _ }) => Some(def), 1685 Ty::FnDef(def, _) => Some(def),
1689 _ => None, 1686 _ => None,
1690 }; 1687 };
1691 1688
@@ -1694,20 +1691,16 @@ impl Type {
1694 } 1691 }
1695 1692
1696 pub fn is_closure(&self) -> bool { 1693 pub fn is_closure(&self) -> bool {
1697 matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { .. }, .. })) 1694 matches!(&self.ty.value, Ty::Closure { .. })
1698 } 1695 }
1699 1696
1700 pub fn is_fn(&self) -> bool { 1697 pub fn is_fn(&self) -> bool {
1701 matches!( 1698 matches!(&self.ty.value, Ty::FnDef(..) | Ty::Function { .. })
1702 &self.ty.value,
1703 Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(..), .. })
1704 | Ty::Apply(ApplicationTy { ctor: TypeCtor::FnPtr { .. }, .. })
1705 )
1706 } 1699 }
1707 1700
1708 pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { 1701 pub fn is_packed(&self, db: &dyn HirDatabase) -> bool {
1709 let adt_id = match self.ty.value { 1702 let adt_id = match self.ty.value {
1710 Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(adt_id), .. }) => adt_id, 1703 Ty::Adt(adt_id, ..) => adt_id,
1711 _ => return false, 1704 _ => return false,
1712 }; 1705 };
1713 1706
@@ -1719,7 +1712,7 @@ impl Type {
1719 } 1712 }
1720 1713
1721 pub fn is_raw_ptr(&self) -> bool { 1714 pub fn is_raw_ptr(&self) -> bool {
1722 matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. })) 1715 matches!(&self.ty.value, Ty::Raw(..))
1723 } 1716 }
1724 1717
1725 pub fn contains_unknown(&self) -> bool { 1718 pub fn contains_unknown(&self) -> bool {
@@ -1728,44 +1721,34 @@ impl Type {
1728 fn go(ty: &Ty) -> bool { 1721 fn go(ty: &Ty) -> bool {
1729 match ty { 1722 match ty {
1730 Ty::Unknown => true, 1723 Ty::Unknown => true,
1731 Ty::Apply(a_ty) => a_ty.parameters.iter().any(go), 1724 _ => ty.substs().map_or(false, |substs| substs.iter().any(go)),
1732 _ => false,
1733 } 1725 }
1734 } 1726 }
1735 } 1727 }
1736 1728
1737 pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> { 1729 pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> {
1738 if let Ty::Apply(a_ty) = &self.ty.value { 1730 let (variant_id, substs) = match self.ty.value {
1739 let variant_id = match a_ty.ctor { 1731 Ty::Adt(AdtId::StructId(s), ref substs) => (s.into(), substs),
1740 TypeCtor::Adt(AdtId::StructId(s)) => s.into(), 1732 Ty::Adt(AdtId::UnionId(u), ref substs) => (u.into(), substs),
1741 TypeCtor::Adt(AdtId::UnionId(u)) => u.into(), 1733 _ => return Vec::new(),
1742 _ => return Vec::new(),
1743 };
1744
1745 return db
1746 .field_types(variant_id)
1747 .iter()
1748 .map(|(local_id, ty)| {
1749 let def = Field { parent: variant_id.into(), id: local_id };
1750 let ty = ty.clone().subst(&a_ty.parameters);
1751 (def, self.derived(ty))
1752 })
1753 .collect();
1754 }; 1734 };
1755 Vec::new() 1735
1736 db.field_types(variant_id)
1737 .iter()
1738 .map(|(local_id, ty)| {
1739 let def = Field { parent: variant_id.into(), id: local_id };
1740 let ty = ty.clone().subst(substs);
1741 (def, self.derived(ty))
1742 })
1743 .collect()
1756 } 1744 }
1757 1745
1758 pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> { 1746 pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> {
1759 let mut res = Vec::new(); 1747 if let Ty::Tuple(_, substs) = &self.ty.value {
1760 if let Ty::Apply(a_ty) = &self.ty.value { 1748 substs.iter().map(|ty| self.derived(ty.clone())).collect()
1761 if let TypeCtor::Tuple { .. } = a_ty.ctor { 1749 } else {
1762 for ty in a_ty.parameters.iter() { 1750 Vec::new()
1763 let ty = ty.clone(); 1751 }
1764 res.push(self.derived(ty));
1765 }
1766 }
1767 };
1768 res
1769 } 1752 }
1770 1753
1771 pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a { 1754 pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a {
@@ -1802,15 +1785,13 @@ impl Type {
1802 } 1785 }
1803 1786
1804 pub fn type_parameters(&self) -> impl Iterator<Item = Type> + '_ { 1787 pub fn type_parameters(&self) -> impl Iterator<Item = Type> + '_ {
1805 let ty = self.ty.value.strip_references(); 1788 self.ty
1806 let substs = match ty { 1789 .value
1807 Ty::Apply(apply_ty) => &apply_ty.parameters, 1790 .strip_references()
1808 Ty::Opaque(opaque_ty) => &opaque_ty.parameters, 1791 .substs()
1809 _ => return Either::Left(iter::empty()), 1792 .into_iter()
1810 }; 1793 .flat_map(|substs| substs.iter())
1811 1794 .map(move |ty| self.derived(ty.clone()))
1812 let iter = substs.iter().map(move |ty| self.derived(ty.clone()));
1813 Either::Right(iter)
1814 } 1795 }
1815 1796
1816 pub fn iterate_method_candidates<T>( 1797 pub fn iterate_method_candidates<T>(
@@ -1900,17 +1881,8 @@ impl Type {
1900 1881
1901 // FIXME: provide required accessors such that it becomes implementable from outside. 1882 // FIXME: provide required accessors such that it becomes implementable from outside.
1902 pub fn is_equal_for_find_impls(&self, other: &Type) -> bool { 1883 pub fn is_equal_for_find_impls(&self, other: &Type) -> bool {
1903 match (&self.ty.value, &other.ty.value) { 1884 let rref = other.remove_ref();
1904 (Ty::Apply(a_original_ty), Ty::Apply(ApplicationTy { ctor, parameters })) => match ctor 1885 self.ty.value.equals_ctor(rref.as_ref().map_or(&other.ty.value, |it| &it.ty.value))
1905 {
1906 TypeCtor::Ref(..) => match parameters.as_single() {
1907 Ty::Apply(a_ty) => a_original_ty.ctor == a_ty.ctor,
1908 _ => false,
1909 },
1910 _ => a_original_ty.ctor == *ctor,
1911 },
1912 _ => false,
1913 }
1914 } 1886 }
1915 1887
1916 fn derived(&self, ty: Ty) -> Type { 1888 fn derived(&self, ty: Ty) -> Type {
@@ -1955,28 +1927,20 @@ impl Type {
1955 fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) { 1927 fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
1956 let ty = type_.ty.value.strip_references(); 1928 let ty = type_.ty.value.strip_references();
1957 match ty { 1929 match ty {
1958 Ty::Apply(ApplicationTy { ctor, parameters }) => { 1930 Ty::Adt(..) => {
1959 match ctor { 1931 cb(type_.derived(ty.clone()));
1960 TypeCtor::Adt(_) => { 1932 }
1961 cb(type_.derived(ty.clone())); 1933 Ty::AssociatedType(..) => {
1962 } 1934 if let Some(_) = ty.associated_type_parent_trait(db) {
1963 TypeCtor::AssociatedType(_) => { 1935 cb(type_.derived(ty.clone()));
1964 if let Some(_) = ty.associated_type_parent_trait(db) {
1965 cb(type_.derived(ty.clone()));
1966 }
1967 }
1968 TypeCtor::OpaqueType(..) => {
1969 if let Some(bounds) = ty.impl_trait_bounds(db) {
1970 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
1971 }
1972 }
1973 _ => (),
1974 } 1936 }
1975
1976 // adt params, tuples, etc...
1977 walk_substs(db, type_, parameters, cb);
1978 } 1937 }
1979 Ty::Opaque(opaque_ty) => { 1938 Ty::OpaqueType(..) => {
1939 if let Some(bounds) = ty.impl_trait_bounds(db) {
1940 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
1941 }
1942 }
1943 Ty::Alias(AliasTy::Opaque(opaque_ty)) => {
1980 if let Some(bounds) = ty.impl_trait_bounds(db) { 1944 if let Some(bounds) = ty.impl_trait_bounds(db) {
1981 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); 1945 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
1982 } 1946 }
@@ -1992,7 +1956,10 @@ impl Type {
1992 walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb); 1956 walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb);
1993 } 1957 }
1994 1958
1995 _ => (), 1959 _ => {}
1960 }
1961 if let Some(substs) = ty.substs() {
1962 walk_substs(db, type_, &substs, cb);
1996 } 1963 }
1997 } 1964 }
1998 1965
@@ -2010,7 +1977,7 @@ impl HirDisplay for Type {
2010#[derive(Debug)] 1977#[derive(Debug)]
2011pub struct Callable { 1978pub struct Callable {
2012 ty: Type, 1979 ty: Type,
2013 sig: FnSig, 1980 sig: CallableSig,
2014 def: Option<CallableDefId>, 1981 def: Option<CallableDefId>,
2015 pub(crate) is_bound_method: bool, 1982 pub(crate) is_bound_method: bool,
2016} 1983}
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index dc21f6051..64ce4add1 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, Substs, Ty, 23 InferenceResult, Substs,
24}; 24};
25use syntax::{ 25use syntax::{
26 ast::{self, AstNode}, 26 ast::{self, AstNode},
@@ -299,14 +299,11 @@ impl SourceAnalyzer {
299 let infer = self.infer.as_ref()?; 299 let infer = self.infer.as_ref()?;
300 300
301 let expr_id = self.expr_id(db, &literal.clone().into())?; 301 let expr_id = self.expr_id(db, &literal.clone().into())?;
302 let substs = match &infer.type_of_expr[expr_id] { 302 let substs = infer.type_of_expr[expr_id].substs()?;
303 Ty::Apply(a_ty) => &a_ty.parameters,
304 _ => return None,
305 };
306 303
307 let (variant, missing_fields, _exhaustive) = 304 let (variant, missing_fields, _exhaustive) =
308 record_literal_missing_fields(db, infer, expr_id, &body[expr_id])?; 305 record_literal_missing_fields(db, infer, expr_id, &body[expr_id])?;
309 let res = self.missing_fields(db, krate, substs, variant, missing_fields); 306 let res = self.missing_fields(db, krate, &substs, variant, missing_fields);
310 Some(res) 307 Some(res)
311 } 308 }
312 309
@@ -320,14 +317,11 @@ impl SourceAnalyzer {
320 let infer = self.infer.as_ref()?; 317 let infer = self.infer.as_ref()?;
321 318
322 let pat_id = self.pat_id(&pattern.clone().into())?; 319 let pat_id = self.pat_id(&pattern.clone().into())?;
323 let substs = match &infer.type_of_pat[pat_id] { 320 let substs = infer.type_of_pat[pat_id].substs()?;
324 Ty::Apply(a_ty) => &a_ty.parameters,
325 _ => return None,
326 };
327 321
328 let (variant, missing_fields, _exhaustive) = 322 let (variant, missing_fields, _exhaustive) =
329 record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?; 323 record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?;
330 let res = self.missing_fields(db, krate, substs, variant, missing_fields); 324 let res = self.missing_fields(db, krate, &substs, variant, missing_fields);
331 Some(res) 325 Some(res)
332 } 326 }
333 327
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index c18001e15..40beb2f7a 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -24,7 +24,7 @@ use test_utils::mark;
24use crate::{ 24use crate::{
25 adt::StructKind, 25 adt::StructKind,
26 body::{Body, BodySourceMap, Expander, LabelSource, PatPtr, SyntheticSyntax}, 26 body::{Body, BodySourceMap, Expander, LabelSource, PatPtr, SyntheticSyntax},
27 builtin_type::{BuiltinFloat, BuiltinInt}, 27 builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
28 db::DefDatabase, 28 db::DefDatabase,
29 diagnostics::{InactiveCode, MacroError, UnresolvedProcMacro}, 29 diagnostics::{InactiveCode, MacroError, UnresolvedProcMacro},
30 expr::{ 30 expr::{
@@ -1065,11 +1065,16 @@ impl From<ast::LiteralKind> for Literal {
1065 fn from(ast_lit_kind: ast::LiteralKind) -> Self { 1065 fn from(ast_lit_kind: ast::LiteralKind) -> Self {
1066 match ast_lit_kind { 1066 match ast_lit_kind {
1067 LiteralKind::IntNumber(lit) => { 1067 LiteralKind::IntNumber(lit) => {
1068 if let Some(float_suffix) = lit.suffix().and_then(BuiltinFloat::from_suffix) { 1068 if let builtin @ Some(_) = lit.suffix().and_then(BuiltinFloat::from_suffix) {
1069 return Literal::Float(Default::default(), Some(float_suffix)); 1069 return Literal::Float(Default::default(), builtin);
1070 } else if let builtin @ Some(_) =
1071 lit.suffix().and_then(|it| BuiltinInt::from_suffix(&it))
1072 {
1073 Literal::Int(Default::default(), builtin)
1074 } else {
1075 let builtin = lit.suffix().and_then(|it| BuiltinUint::from_suffix(&it));
1076 Literal::Uint(Default::default(), builtin)
1070 } 1077 }
1071 let ty = lit.suffix().and_then(|it| BuiltinInt::from_suffix(&it));
1072 Literal::Int(Default::default(), ty)
1073 } 1078 }
1074 LiteralKind::FloatNumber(lit) => { 1079 LiteralKind::FloatNumber(lit) => {
1075 let ty = lit.suffix().and_then(|it| BuiltinFloat::from_suffix(&it)); 1080 let ty = lit.suffix().and_then(|it| BuiltinFloat::from_suffix(&it));
@@ -1077,7 +1082,7 @@ impl From<ast::LiteralKind> for Literal {
1077 } 1082 }
1078 LiteralKind::ByteString(_) => Literal::ByteString(Default::default()), 1083 LiteralKind::ByteString(_) => Literal::ByteString(Default::default()),
1079 LiteralKind::String(_) => Literal::String(Default::default()), 1084 LiteralKind::String(_) => Literal::String(Default::default()),
1080 LiteralKind::Byte => Literal::Int(Default::default(), Some(BuiltinInt::U8)), 1085 LiteralKind::Byte => Literal::Uint(Default::default(), Some(BuiltinUint::U8)),
1081 LiteralKind::Bool(val) => Literal::Bool(val), 1086 LiteralKind::Bool(val) => Literal::Bool(val),
1082 LiteralKind::Char => Literal::Char(Default::default()), 1087 LiteralKind::Char => Literal::Char(Default::default()),
1083 } 1088 }
diff --git a/crates/hir_def/src/builtin_type.rs b/crates/hir_def/src/builtin_type.rs
index 0f872b5c0..7cbaf30b8 100644
--- a/crates/hir_def/src/builtin_type.rs
+++ b/crates/hir_def/src/builtin_type.rs
@@ -6,38 +6,32 @@
6use std::fmt; 6use std::fmt;
7 7
8use hir_expand::name::{name, AsName, Name}; 8use hir_expand::name::{name, AsName, Name};
9 9/// Different signed int types.
10#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 10#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
11pub enum Signedness { 11pub enum BuiltinInt {
12 Signed, 12 Isize,
13 Unsigned, 13 I8,
14} 14 I16,
15 15 I32,
16#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 16 I64,
17pub enum IntBitness { 17 I128,
18 Xsize,
19 X8,
20 X16,
21 X32,
22 X64,
23 X128,
24}
25
26#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
27pub enum FloatBitness {
28 X32,
29 X64,
30} 18}
31 19
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 20/// Different unsigned int types.
33pub struct BuiltinInt { 21#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
34 pub signedness: Signedness, 22pub enum BuiltinUint {
35 pub bitness: IntBitness, 23 Usize,
24 U8,
25 U16,
26 U32,
27 U64,
28 U128,
36} 29}
37 30
38#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 31#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
39pub struct BuiltinFloat { 32pub enum BuiltinFloat {
40 pub bitness: FloatBitness, 33 F32,
34 F64,
41} 35}
42 36
43#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 37#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -46,6 +40,7 @@ pub enum BuiltinType {
46 Bool, 40 Bool,
47 Str, 41 Str,
48 Int(BuiltinInt), 42 Int(BuiltinInt),
43 Uint(BuiltinUint),
49 Float(BuiltinFloat), 44 Float(BuiltinFloat),
50} 45}
51 46
@@ -56,19 +51,19 @@ impl BuiltinType {
56 (name![bool], BuiltinType::Bool), 51 (name![bool], BuiltinType::Bool),
57 (name![str], BuiltinType::Str), 52 (name![str], BuiltinType::Str),
58 53
59 (name![isize], BuiltinType::Int(BuiltinInt::ISIZE)), 54 (name![isize], BuiltinType::Int(BuiltinInt::Isize)),
60 (name![i8], BuiltinType::Int(BuiltinInt::I8)), 55 (name![i8], BuiltinType::Int(BuiltinInt::I8)),
61 (name![i16], BuiltinType::Int(BuiltinInt::I16)), 56 (name![i16], BuiltinType::Int(BuiltinInt::I16)),
62 (name![i32], BuiltinType::Int(BuiltinInt::I32)), 57 (name![i32], BuiltinType::Int(BuiltinInt::I32)),
63 (name![i64], BuiltinType::Int(BuiltinInt::I64)), 58 (name![i64], BuiltinType::Int(BuiltinInt::I64)),
64 (name![i128], BuiltinType::Int(BuiltinInt::I128)), 59 (name![i128], BuiltinType::Int(BuiltinInt::I128)),
65 60
66 (name![usize], BuiltinType::Int(BuiltinInt::USIZE)), 61 (name![usize], BuiltinType::Uint(BuiltinUint::Usize)),
67 (name![u8], BuiltinType::Int(BuiltinInt::U8)), 62 (name![u8], BuiltinType::Uint(BuiltinUint::U8)),
68 (name![u16], BuiltinType::Int(BuiltinInt::U16)), 63 (name![u16], BuiltinType::Uint(BuiltinUint::U16)),
69 (name![u32], BuiltinType::Int(BuiltinInt::U32)), 64 (name![u32], BuiltinType::Uint(BuiltinUint::U32)),
70 (name![u64], BuiltinType::Int(BuiltinInt::U64)), 65 (name![u64], BuiltinType::Uint(BuiltinUint::U64)),
71 (name![u128], BuiltinType::Int(BuiltinInt::U128)), 66 (name![u128], BuiltinType::Uint(BuiltinUint::U128)),
72 67
73 (name![f32], BuiltinType::Float(BuiltinFloat::F32)), 68 (name![f32], BuiltinType::Float(BuiltinFloat::F32)),
74 (name![f64], BuiltinType::Float(BuiltinFloat::F64)), 69 (name![f64], BuiltinType::Float(BuiltinFloat::F64)),
@@ -81,24 +76,25 @@ impl AsName for BuiltinType {
81 BuiltinType::Char => name![char], 76 BuiltinType::Char => name![char],
82 BuiltinType::Bool => name![bool], 77 BuiltinType::Bool => name![bool],
83 BuiltinType::Str => name![str], 78 BuiltinType::Str => name![str],
84 BuiltinType::Int(BuiltinInt { signedness, bitness }) => match (signedness, bitness) { 79 BuiltinType::Int(it) => match it {
85 (Signedness::Signed, IntBitness::Xsize) => name![isize], 80 BuiltinInt::Isize => name![isize],
86 (Signedness::Signed, IntBitness::X8) => name![i8], 81 BuiltinInt::I8 => name![i8],
87 (Signedness::Signed, IntBitness::X16) => name![i16], 82 BuiltinInt::I16 => name![i16],
88 (Signedness::Signed, IntBitness::X32) => name![i32], 83 BuiltinInt::I32 => name![i32],
89 (Signedness::Signed, IntBitness::X64) => name![i64], 84 BuiltinInt::I64 => name![i64],
90 (Signedness::Signed, IntBitness::X128) => name![i128], 85 BuiltinInt::I128 => name![i128],
91 86 },
92 (Signedness::Unsigned, IntBitness::Xsize) => name![usize], 87 BuiltinType::Uint(it) => match it {
93 (Signedness::Unsigned, IntBitness::X8) => name![u8], 88 BuiltinUint::Usize => name![usize],
94 (Signedness::Unsigned, IntBitness::X16) => name![u16], 89 BuiltinUint::U8 => name![u8],
95 (Signedness::Unsigned, IntBitness::X32) => name![u32], 90 BuiltinUint::U16 => name![u16],
96 (Signedness::Unsigned, IntBitness::X64) => name![u64], 91 BuiltinUint::U32 => name![u32],
97 (Signedness::Unsigned, IntBitness::X128) => name![u128], 92 BuiltinUint::U64 => name![u64],
93 BuiltinUint::U128 => name![u128],
98 }, 94 },
99 BuiltinType::Float(BuiltinFloat { bitness }) => match bitness { 95 BuiltinType::Float(it) => match it {
100 FloatBitness::X32 => name![f32], 96 BuiltinFloat::F32 => name![f32],
101 FloatBitness::X64 => name![f64], 97 BuiltinFloat::F64 => name![f64],
102 }, 98 },
103 } 99 }
104 } 100 }
@@ -113,31 +109,26 @@ impl fmt::Display for BuiltinType {
113 109
114#[rustfmt::skip] 110#[rustfmt::skip]
115impl BuiltinInt { 111impl BuiltinInt {
116 pub const ISIZE: BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::Xsize };
117 pub const I8 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X8 };
118 pub const I16 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X16 };
119 pub const I32 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X32 };
120 pub const I64 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X64 };
121 pub const I128 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X128 };
122
123 pub const USIZE: BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::Xsize };
124 pub const U8 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X8 };
125 pub const U16 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X16 };
126 pub const U32 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X32 };
127 pub const U64 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X64 };
128 pub const U128 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X128 };
129
130
131 pub fn from_suffix(suffix: &str) -> Option<BuiltinInt> { 112 pub fn from_suffix(suffix: &str) -> Option<BuiltinInt> {
132 let res = match suffix { 113 let res = match suffix {
133 "isize" => Self::ISIZE, 114 "isize" => Self::Isize,
134 "i8" => Self::I8, 115 "i8" => Self::I8,
135 "i16" => Self::I16, 116 "i16" => Self::I16,
136 "i32" => Self::I32, 117 "i32" => Self::I32,
137 "i64" => Self::I64, 118 "i64" => Self::I64,
138 "i128" => Self::I128, 119 "i128" => Self::I128,
139 120
140 "usize" => Self::USIZE, 121 _ => return None,
122 };
123 Some(res)
124 }
125}
126
127#[rustfmt::skip]
128impl BuiltinUint {
129 pub fn from_suffix(suffix: &str) -> Option<BuiltinUint> {
130 let res = match suffix {
131 "usize" => Self::Usize,
141 "u8" => Self::U8, 132 "u8" => Self::U8,
142 "u16" => Self::U16, 133 "u16" => Self::U16,
143 "u32" => Self::U32, 134 "u32" => Self::U32,
@@ -152,9 +143,6 @@ impl BuiltinInt {
152 143
153#[rustfmt::skip] 144#[rustfmt::skip]
154impl BuiltinFloat { 145impl BuiltinFloat {
155 pub const F32: BuiltinFloat = BuiltinFloat { bitness: FloatBitness::X32 };
156 pub const F64: BuiltinFloat = BuiltinFloat { bitness: FloatBitness::X64 };
157
158 pub fn from_suffix(suffix: &str) -> Option<BuiltinFloat> { 146 pub fn from_suffix(suffix: &str) -> Option<BuiltinFloat> {
159 let res = match suffix { 147 let res = match suffix {
160 "f32" => BuiltinFloat::F32, 148 "f32" => BuiltinFloat::F32,
diff --git a/crates/hir_def/src/expr.rs b/crates/hir_def/src/expr.rs
index 4d72eaeaf..24be93773 100644
--- a/crates/hir_def/src/expr.rs
+++ b/crates/hir_def/src/expr.rs
@@ -17,7 +17,7 @@ use la_arena::{Idx, RawIdx};
17use syntax::ast::RangeOp; 17use syntax::ast::RangeOp;
18 18
19use crate::{ 19use crate::{
20 builtin_type::{BuiltinFloat, BuiltinInt}, 20 builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
21 path::{GenericArgs, Path}, 21 path::{GenericArgs, Path},
22 type_ref::{Mutability, Rawness, TypeRef}, 22 type_ref::{Mutability, Rawness, TypeRef},
23 BlockId, 23 BlockId,
@@ -43,6 +43,7 @@ pub enum Literal {
43 Char(char), 43 Char(char),
44 Bool(bool), 44 Bool(bool),
45 Int(u64, Option<BuiltinInt>), 45 Int(u64, Option<BuiltinInt>),
46 Uint(u64, Option<BuiltinUint>),
46 Float(u64, Option<BuiltinFloat>), // FIXME: f64 is not Eq 47 Float(u64, Option<BuiltinFloat>), // FIXME: f64 is not Eq
47} 48}
48 49
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs
index 5e2a711b8..3e19a7702 100644
--- a/crates/hir_def/src/find_path.rs
+++ b/crates/hir_def/src/find_path.rs
@@ -1,5 +1,7 @@
1//! An algorithm to find a path to refer to a certain item. 1//! An algorithm to find a path to refer to a certain item.
2 2
3use std::iter;
4
3use hir_expand::name::{known, AsName, Name}; 5use hir_expand::name::{known, AsName, Name};
4use rustc_hash::FxHashSet; 6use rustc_hash::FxHashSet;
5use test_utils::mark; 7use test_utils::mark;
@@ -95,7 +97,7 @@ fn find_path_inner(
95 item: ItemInNs, 97 item: ItemInNs,
96 from: ModuleId, 98 from: ModuleId,
97 max_len: usize, 99 max_len: usize,
98 prefixed: Option<PrefixKind>, 100 mut prefixed: Option<PrefixKind>,
99) -> Option<ModPath> { 101) -> Option<ModPath> {
100 if max_len == 0 { 102 if max_len == 0 {
101 return None; 103 return None;
@@ -114,8 +116,9 @@ fn find_path_inner(
114 } 116 }
115 117
116 // - if the item is the crate root, return `crate` 118 // - if the item is the crate root, return `crate`
117 let root = def_map.module_id(def_map.root()); 119 let root = def_map.crate_root(db);
118 if item == ItemInNs::Types(ModuleDefId::ModuleId(root)) && def_map.block_id().is_none() { 120 if item == ItemInNs::Types(ModuleDefId::ModuleId(root)) && def_map.block_id().is_none() {
121 // FIXME: the `block_id()` check should be unnecessary, but affects the result
119 return Some(ModPath::from_segments(PathKind::Crate, Vec::new())); 122 return Some(ModPath::from_segments(PathKind::Crate, Vec::new()));
120 } 123 }
121 124
@@ -165,7 +168,7 @@ fn find_path_inner(
165 168
166 // - otherwise, look for modules containing (reexporting) it and import it from one of those 169 // - otherwise, look for modules containing (reexporting) it and import it from one of those
167 170
168 let crate_root = def_map.module_id(def_map.root()); 171 let crate_root = def_map.crate_root(db);
169 let crate_attrs = db.attrs(crate_root.into()); 172 let crate_attrs = db.attrs(crate_root.into());
170 let prefer_no_std = crate_attrs.by_key("no_std").exists(); 173 let prefer_no_std = crate_attrs.by_key("no_std").exists();
171 let mut best_path = None; 174 let mut best_path = None;
@@ -228,12 +231,16 @@ fn find_path_inner(
228 } 231 }
229 } 232 }
230 233
231 if let Some(mut prefix) = prefixed.map(PrefixKind::prefix) { 234 // If the item is declared inside a block expression, don't use a prefix, as we don't handle
232 if matches!(prefix, PathKind::Crate | PathKind::Super(0)) && def_map.block_id().is_some() { 235 // that correctly (FIXME).
233 // Inner items cannot be referred to via `crate::` or `self::` paths. 236 if let Some(item_module) = item.as_module_def_id().and_then(|did| did.module(db)) {
234 prefix = PathKind::Plain; 237 if item_module.def_map(db).block_id().is_some() && prefixed.is_some() {
238 mark::hit!(prefixed_in_block_expression);
239 prefixed = Some(PrefixKind::Plain);
235 } 240 }
241 }
236 242
243 if let Some(prefix) = prefixed.map(PrefixKind::prefix) {
237 best_path.or_else(|| { 244 best_path.or_else(|| {
238 scope_name.map(|scope_name| ModPath::from_segments(prefix, vec![scope_name])) 245 scope_name.map(|scope_name| ModPath::from_segments(prefix, vec![scope_name]))
239 }) 246 })
@@ -285,12 +292,12 @@ fn find_local_import_locations(
285 let data = &def_map[from.local_id]; 292 let data = &def_map[from.local_id];
286 let mut worklist = 293 let mut worklist =
287 data.children.values().map(|child| def_map.module_id(*child)).collect::<Vec<_>>(); 294 data.children.values().map(|child| def_map.module_id(*child)).collect::<Vec<_>>();
288 let mut parent = data.parent; 295 for ancestor in iter::successors(from.containing_module(db), |m| m.containing_module(db)) {
289 while let Some(p) = parent { 296 worklist.push(ancestor);
290 worklist.push(def_map.module_id(p));
291 parent = def_map[p].parent;
292 } 297 }
293 298
299 let def_map = def_map.crate_root(db).def_map(db);
300
294 let mut seen: FxHashSet<_> = FxHashSet::default(); 301 let mut seen: FxHashSet<_> = FxHashSet::default();
295 302
296 let mut locations = Vec::new(); 303 let mut locations = Vec::new();
@@ -301,7 +308,14 @@ fn find_local_import_locations(
301 308
302 let ext_def_map; 309 let ext_def_map;
303 let data = if module.krate == from.krate { 310 let data = if module.krate == from.krate {
304 &def_map[module.local_id] 311 if module.block.is_some() {
312 // Re-query the block's DefMap
313 ext_def_map = module.def_map(db);
314 &ext_def_map[module.local_id]
315 } else {
316 // Reuse the root DefMap
317 &def_map[module.local_id]
318 }
305 } else { 319 } else {
306 // The crate might reexport a module defined in another crate. 320 // The crate might reexport a module defined in another crate.
307 ext_def_map = module.def_map(db); 321 ext_def_map = module.def_map(db);
@@ -828,6 +842,7 @@ mod tests {
828 842
829 #[test] 843 #[test]
830 fn inner_items_from_inner_module() { 844 fn inner_items_from_inner_module() {
845 mark::check!(prefixed_in_block_expression);
831 check_found_path( 846 check_found_path(
832 r#" 847 r#"
833 fn main() { 848 fn main() {
@@ -869,4 +884,24 @@ mod tests {
869 "super::Struct", 884 "super::Struct",
870 ); 885 );
871 } 886 }
887
888 #[test]
889 fn outer_items_with_inner_items_present() {
890 check_found_path(
891 r#"
892 mod module {
893 pub struct CompleteMe;
894 }
895
896 fn main() {
897 fn inner() {}
898 $0
899 }
900 "#,
901 "module::CompleteMe",
902 "module::CompleteMe",
903 "crate::module::CompleteMe",
904 "self::module::CompleteMe",
905 )
906 }
872} 907}
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs
index ee46c3330..4e5daa2ff 100644
--- a/crates/hir_def/src/item_scope.rs
+++ b/crates/hir_def/src/item_scope.rs
@@ -12,8 +12,8 @@ use stdx::format_to;
12use test_utils::mark; 12use test_utils::mark;
13 13
14use crate::{ 14use crate::{
15 db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId, 15 db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ImplId,
16 LocalModuleId, Lookup, MacroDefId, ModuleDefId, ModuleId, TraitId, 16 LocalModuleId, MacroDefId, ModuleDefId, ModuleId, TraitId,
17}; 17};
18 18
19#[derive(Copy, Clone)] 19#[derive(Copy, Clone)]
@@ -375,19 +375,9 @@ impl ItemInNs {
375 375
376 /// Returns the crate defining this item (or `None` if `self` is built-in). 376 /// Returns the crate defining this item (or `None` if `self` is built-in).
377 pub fn krate(&self, db: &dyn DefDatabase) -> Option<CrateId> { 377 pub fn krate(&self, db: &dyn DefDatabase) -> Option<CrateId> {
378 Some(match self { 378 match self {
379 ItemInNs::Types(did) | ItemInNs::Values(did) => match did { 379 ItemInNs::Types(did) | ItemInNs::Values(did) => did.module(db).map(|m| m.krate),
380 ModuleDefId::ModuleId(id) => id.krate, 380 ItemInNs::Macros(id) => Some(id.krate),
381 ModuleDefId::FunctionId(id) => id.lookup(db).module(db).krate, 381 }
382 ModuleDefId::AdtId(id) => id.module(db).krate,
383 ModuleDefId::EnumVariantId(id) => id.parent.lookup(db).container.module(db).krate,
384 ModuleDefId::ConstId(id) => id.lookup(db).container.module(db).krate,
385 ModuleDefId::StaticId(id) => id.lookup(db).container.module(db).krate,
386 ModuleDefId::TraitId(id) => id.lookup(db).container.module(db).krate,
387 ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db).krate,
388 ModuleDefId::BuiltinType(_) => return None,
389 },
390 ItemInNs::Macros(id) => return Some(id.krate),
391 })
392 } 382 }
393} 383}
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs
index 6802bc250..4498d94bb 100644
--- a/crates/hir_def/src/lib.rs
+++ b/crates/hir_def/src/lib.rs
@@ -97,6 +97,10 @@ impl ModuleId {
97 pub fn krate(&self) -> CrateId { 97 pub fn krate(&self) -> CrateId {
98 self.krate 98 self.krate
99 } 99 }
100
101 pub fn containing_module(&self, db: &dyn db::DefDatabase) -> Option<ModuleId> {
102 self.def_map(db).containing_module(self.local_id)
103 }
100} 104}
101 105
102/// An ID of a module, **local** to a specific crate 106/// An ID of a module, **local** to a specific crate
@@ -529,6 +533,25 @@ impl HasModule for StaticLoc {
529 } 533 }
530} 534}
531 535
536impl ModuleDefId {
537 /// Returns the module containing `self` (or `self`, if `self` is itself a module).
538 ///
539 /// Returns `None` if `self` refers to a primitive type.
540 pub fn module(&self, db: &dyn db::DefDatabase) -> Option<ModuleId> {
541 Some(match self {
542 ModuleDefId::ModuleId(id) => *id,
543 ModuleDefId::FunctionId(id) => id.lookup(db).module(db),
544 ModuleDefId::AdtId(id) => id.module(db),
545 ModuleDefId::EnumVariantId(id) => id.parent.lookup(db).container.module(db),
546 ModuleDefId::ConstId(id) => id.lookup(db).container.module(db),
547 ModuleDefId::StaticId(id) => id.lookup(db).container.module(db),
548 ModuleDefId::TraitId(id) => id.lookup(db).container.module(db),
549 ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db),
550 ModuleDefId::BuiltinType(_) => return None,
551 })
552 }
553}
554
532impl AttrDefId { 555impl AttrDefId {
533 pub fn krate(&self, db: &dyn db::DefDatabase) -> CrateId { 556 pub fn krate(&self, db: &dyn db::DefDatabase) -> CrateId {
534 match self { 557 match self {
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs
index 6a3456f2e..003d668ca 100644
--- a/crates/hir_def/src/nameres.rs
+++ b/crates/hir_def/src/nameres.rs
@@ -343,6 +343,18 @@ impl DefMap {
343 Some(self.block?.parent) 343 Some(self.block?.parent)
344 } 344 }
345 345
346 /// Returns the module containing `local_mod`, either the parent `mod`, or the module containing
347 /// the block, if `self` corresponds to a block expression.
348 pub fn containing_module(&self, local_mod: LocalModuleId) -> Option<ModuleId> {
349 match &self[local_mod].parent {
350 Some(parent) => Some(self.module_id(*parent)),
351 None => match &self.block {
352 Some(block) => Some(block.parent),
353 None => None,
354 },
355 }
356 }
357
346 // FIXME: this can use some more human-readable format (ideally, an IR 358 // FIXME: this can use some more human-readable format (ideally, an IR
347 // even), as this should be a great debugging aid. 359 // even), as this should be a great debugging aid.
348 pub fn dump(&self, db: &dyn DefDatabase) -> String { 360 pub fn dump(&self, db: &dyn DefDatabase) -> String {
diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs
index a469546c1..505493a74 100644
--- a/crates/hir_def/src/path/lower.rs
+++ b/crates/hir_def/src/path/lower.rs
@@ -101,8 +101,12 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
101 break; 101 break;
102 } 102 }
103 ast::PathSegmentKind::SelfKw => { 103 ast::PathSegmentKind::SelfKw => {
104 kind = PathKind::Super(0); 104 // don't break out if `self` is the last segment of a path, this mean we got an
105 break; 105 // use tree like `foo::{self}` which we want to resolve as `foo`
106 if !segments.is_empty() {
107 kind = PathKind::Super(0);
108 break;
109 }
106 } 110 }
107 ast::PathSegmentKind::SuperKw => { 111 ast::PathSegmentKind::SuperKw => {
108 let nested_super_count = if let PathKind::Super(n) = kind { n } else { 0 }; 112 let nested_super_count = if let PathKind::Super(n) = kind { n } else { 0 };
@@ -117,6 +121,11 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
117 segments.reverse(); 121 segments.reverse();
118 generic_args.reverse(); 122 generic_args.reverse();
119 123
124 if segments.is_empty() && kind == PathKind::Plain && type_anchor.is_none() {
125 // plain empty paths don't exist, this means we got a single `self` segment as our path
126 kind = PathKind::Super(0);
127 }
128
120 // handle local_inner_macros : 129 // handle local_inner_macros :
121 // Basically, even in rustc it is quite hacky: 130 // Basically, even in rustc it is quite hacky:
122 // https://github.com/rust-lang/rust/blob/614f273e9388ddd7804d5cbc80b8865068a3744e/src/librustc_resolve/macros.rs#L456 131 // https://github.com/rust-lang/rust/blob/614f273e9388ddd7804d5cbc80b8865068a3744e/src/librustc_resolve/macros.rs#L456
diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml
index 6ef9d1e7e..d1302d749 100644
--- a/crates/hir_ty/Cargo.toml
+++ b/crates/hir_ty/Cargo.toml
@@ -17,9 +17,9 @@ ena = "0.14.0"
17log = "0.4.8" 17log = "0.4.8"
18rustc-hash = "1.1.0" 18rustc-hash = "1.1.0"
19scoped-tls = "1" 19scoped-tls = "1"
20chalk-solve = { version = "0.58", default-features = false } 20chalk-solve = { version = "0.59", default-features = false }
21chalk-ir = "0.58" 21chalk-ir = "0.59"
22chalk-recursive = "0.58" 22chalk-recursive = "0.59"
23la-arena = { version = "0.2.0", path = "../../lib/arena" } 23la-arena = { version = "0.2.0", path = "../../lib/arena" }
24 24
25stdx = { path = "../stdx", version = "0.0.0" } 25stdx = { path = "../stdx", version = "0.0.0" }
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs
index ece68183e..be1fd1f13 100644
--- a/crates/hir_ty/src/autoderef.rs
+++ b/crates/hir_ty/src/autoderef.rs
@@ -81,7 +81,7 @@ fn deref_by_trait(
81 81
82 // Now do the assoc type projection 82 // Now do the assoc type projection
83 let projection = super::traits::ProjectionPredicate { 83 let projection = super::traits::ProjectionPredicate {
84 ty: Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len())), 84 ty: Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len())),
85 projection_ty: super::ProjectionTy { associated_ty: target, parameters }, 85 projection_ty: super::ProjectionTy { associated_ty: target, parameters },
86 }; 86 };
87 87
@@ -89,8 +89,10 @@ fn deref_by_trait(
89 89
90 let in_env = InEnvironment { value: obligation, environment: ty.environment }; 90 let in_env = InEnvironment { value: obligation, environment: ty.environment };
91 91
92 let canonical = 92 let canonical = Canonical::new(
93 Canonical::new(in_env, ty.value.kinds.iter().copied().chain(Some(super::TyKind::General))); 93 in_env,
94 ty.value.kinds.iter().copied().chain(Some(chalk_ir::TyVariableKind::General)),
95 );
94 96
95 let solution = db.trait_solve(krate, canonical)?; 97 let solution = db.trait_solve(krate, canonical)?;
96 98
@@ -112,7 +114,8 @@ fn deref_by_trait(
112 // new variables in that case 114 // new variables in that case
113 115
114 for i in 1..vars.0.kinds.len() { 116 for i in 1..vars.0.kinds.len() {
115 if vars.0.value[i - 1] != Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) 117 if vars.0.value[i - 1]
118 != Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1))
116 { 119 {
117 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution); 120 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution);
118 return None; 121 return None;
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs
index d740b7265..66a88e2b6 100644
--- a/crates/hir_ty/src/diagnostics/expr.rs
+++ b/crates/hir_ty/src/diagnostics/expr.rs
@@ -17,7 +17,7 @@ use crate::{
17 MissingPatFields, RemoveThisSemicolon, 17 MissingPatFields, RemoveThisSemicolon,
18 }, 18 },
19 utils::variant_data, 19 utils::variant_data,
20 ApplicationTy, InferenceResult, Ty, TypeCtor, 20 InferenceResult, Ty,
21}; 21};
22 22
23pub(crate) use hir_def::{ 23pub(crate) use hir_def::{
@@ -381,14 +381,11 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
381 _ => return, 381 _ => return,
382 }; 382 };
383 383
384 let core_result_ctor = TypeCtor::Adt(AdtId::EnumId(core_result_enum)); 384 let (params, required) = match mismatch.expected {
385 let core_option_ctor = TypeCtor::Adt(AdtId::EnumId(core_option_enum)); 385 Ty::Adt(AdtId::EnumId(enum_id), ref parameters) if enum_id == core_result_enum => {
386
387 let (params, required) = match &mismatch.expected {
388 Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &core_result_ctor => {
389 (parameters, "Ok".to_string()) 386 (parameters, "Ok".to_string())
390 } 387 }
391 Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &core_option_ctor => { 388 Ty::Adt(AdtId::EnumId(enum_id), ref parameters) if enum_id == core_option_enum => {
392 (parameters, "Some".to_string()) 389 (parameters, "Some".to_string())
393 } 390 }
394 _ => return, 391 _ => return,
diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs
index 1c1423fbf..86fee0050 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, ApplicationTy, InferenceResult, Ty, TypeCtor}; 230use crate::{db::HirDatabase, InferenceResult, Ty};
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
@@ -627,14 +627,12 @@ pub(super) fn is_useful(
627 // - `!` type 627 // - `!` type
628 // In those cases, no match arm is useful. 628 // In those cases, no match arm is useful.
629 match cx.infer[cx.match_expr].strip_references() { 629 match cx.infer[cx.match_expr].strip_references() {
630 Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(AdtId::EnumId(enum_id)), .. }) => { 630 Ty::Adt(AdtId::EnumId(enum_id), ..) => {
631 if cx.db.enum_data(*enum_id).variants.is_empty() { 631 if cx.db.enum_data(*enum_id).variants.is_empty() {
632 return Ok(Usefulness::NotUseful); 632 return Ok(Usefulness::NotUseful);
633 } 633 }
634 } 634 }
635 Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. }) => { 635 Ty::Never => return Ok(Usefulness::NotUseful),
636 return Ok(Usefulness::NotUseful);
637 }
638 _ => (), 636 _ => (),
639 } 637 }
640 638
diff --git a/crates/hir_ty/src/diagnostics/unsafe_check.rs b/crates/hir_ty/src/diagnostics/unsafe_check.rs
index 9c506112d..e77a20fea 100644
--- a/crates/hir_ty/src/diagnostics/unsafe_check.rs
+++ b/crates/hir_ty/src/diagnostics/unsafe_check.rs
@@ -11,9 +11,7 @@ use hir_def::{
11}; 11};
12use hir_expand::diagnostics::DiagnosticSink; 12use hir_expand::diagnostics::DiagnosticSink;
13 13
14use crate::{ 14use crate::{db::HirDatabase, diagnostics::MissingUnsafe, InferenceResult, Ty};
15 db::HirDatabase, diagnostics::MissingUnsafe, ApplicationTy, InferenceResult, Ty, TypeCtor,
16};
17 15
18pub(super) struct UnsafeValidator<'a, 'b: 'a> { 16pub(super) struct UnsafeValidator<'a, 'b: 'a> {
19 owner: DefWithBodyId, 17 owner: DefWithBodyId,
@@ -112,7 +110,7 @@ fn walk_unsafe(
112 } 110 }
113 } 111 }
114 Expr::UnaryOp { expr, op: UnaryOp::Deref } => { 112 Expr::UnaryOp { expr, op: UnaryOp::Deref } => {
115 if let Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. }) = &infer[*expr] { 113 if let Ty::Raw(..) = &infer[*expr] {
116 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); 114 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
117 } 115 }
118 } 116 }
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index 271fcbfaf..d4a8b48e6 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -3,10 +3,12 @@
3use std::{borrow::Cow, fmt}; 3use std::{borrow::Cow, fmt};
4 4
5use crate::{ 5use crate::{
6 db::HirDatabase, utils::generics, ApplicationTy, CallableDefId, FnSig, GenericPredicate, 6 db::HirDatabase, primitive, utils::generics, AliasTy, CallableDefId, CallableSig,
7 Lifetime, Obligation, OpaqueTy, OpaqueTyId, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, 7 GenericPredicate, Lifetime, Obligation, OpaqueTy, OpaqueTyId, ProjectionTy, Scalar, Substs,
8 TraitRef, Ty,
8}; 9};
9use arrayvec::ArrayVec; 10use arrayvec::ArrayVec;
11use chalk_ir::Mutability;
10use hir_def::{ 12use hir_def::{
11 db::DefDatabase, find_path, generics::TypeParamProvenance, item_scope::ItemInNs, AdtId, 13 db::DefDatabase, find_path, generics::TypeParamProvenance, item_scope::ItemInNs, AdtId,
12 AssocContainerId, HasModule, Lookup, ModuleId, TraitId, 14 AssocContainerId, HasModule, Lookup, ModuleId, TraitId,
@@ -234,39 +236,79 @@ impl HirDisplay for &Ty {
234 } 236 }
235} 237}
236 238
237impl HirDisplay for ApplicationTy { 239impl HirDisplay for ProjectionTy {
238 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 240 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
239 if f.should_truncate() { 241 if f.should_truncate() {
240 return write!(f, "{}", TYPE_HINT_TRUNCATION); 242 return write!(f, "{}", TYPE_HINT_TRUNCATION);
241 } 243 }
242 244
243 match self.ctor { 245 let trait_ = f.db.trait_data(self.trait_(f.db));
244 TypeCtor::Bool => write!(f, "bool")?, 246 let first_parameter = self.parameters[0].into_displayable(
245 TypeCtor::Char => write!(f, "char")?, 247 f.db,
246 TypeCtor::Int(t) => write!(f, "{}", t)?, 248 f.max_size,
247 TypeCtor::Float(t) => write!(f, "{}", t)?, 249 f.omit_verbose_types,
248 TypeCtor::Str => write!(f, "str")?, 250 f.display_target,
249 TypeCtor::Slice => { 251 );
250 let t = self.parameters.as_single(); 252 write!(f, "<{} as {}", first_parameter, trait_.name)?;
253 if self.parameters.len() > 1 {
254 write!(f, "<")?;
255 f.write_joined(&self.parameters[1..], ", ")?;
256 write!(f, ">")?;
257 }
258 write!(f, ">::{}", f.db.type_alias_data(self.associated_ty).name)?;
259 Ok(())
260 }
261}
262
263impl HirDisplay for Ty {
264 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
265 if f.should_truncate() {
266 return write!(f, "{}", TYPE_HINT_TRUNCATION);
267 }
268
269 match self {
270 Ty::Never => write!(f, "!")?,
271 Ty::Str => write!(f, "str")?,
272 Ty::Scalar(Scalar::Bool) => write!(f, "bool")?,
273 Ty::Scalar(Scalar::Char) => write!(f, "char")?,
274 &Ty::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?,
275 &Ty::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?,
276 &Ty::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?,
277 Ty::Slice(parameters) => {
278 let t = parameters.as_single();
251 write!(f, "[")?; 279 write!(f, "[")?;
252 t.hir_fmt(f)?; 280 t.hir_fmt(f)?;
253 write!(f, "]")?; 281 write!(f, "]")?;
254 } 282 }
255 TypeCtor::Array => { 283 Ty::Array(parameters) => {
256 let t = self.parameters.as_single(); 284 let t = parameters.as_single();
257 write!(f, "[")?; 285 write!(f, "[")?;
258 t.hir_fmt(f)?; 286 t.hir_fmt(f)?;
259 write!(f, "; _]")?; 287 write!(f, "; _]")?;
260 } 288 }
261 TypeCtor::RawPtr(m) | TypeCtor::Ref(m) => { 289 Ty::Raw(m, parameters) | Ty::Ref(m, parameters) => {
262 let t = self.parameters.as_single(); 290 let t = parameters.as_single();
263 let ty_display = 291 let ty_display =
264 t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); 292 t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target);
265 293
266 if matches!(self.ctor, TypeCtor::RawPtr(_)) { 294 if matches!(self, Ty::Raw(..)) {
267 write!(f, "*{}", m.as_keyword_for_ptr())?; 295 write!(
296 f,
297 "*{}",
298 match m {
299 Mutability::Not => "const ",
300 Mutability::Mut => "mut ",
301 }
302 )?;
268 } else { 303 } else {
269 write!(f, "&{}", m.as_keyword_for_ref())?; 304 write!(
305 f,
306 "&{}",
307 match m {
308 Mutability::Not => "",
309 Mutability::Mut => "mut ",
310 }
311 )?;
270 } 312 }
271 313
272 let datas; 314 let datas;
@@ -274,10 +316,10 @@ impl HirDisplay for ApplicationTy {
274 Ty::Dyn(predicates) if predicates.len() > 1 => { 316 Ty::Dyn(predicates) if predicates.len() > 1 => {
275 Cow::Borrowed(predicates.as_ref()) 317 Cow::Borrowed(predicates.as_ref())
276 } 318 }
277 &Ty::Opaque(OpaqueTy { 319 &Ty::Alias(AliasTy::Opaque(OpaqueTy {
278 opaque_ty_id: OpaqueTyId::ReturnTypeImplTrait(func, idx), 320 opaque_ty_id: OpaqueTyId::ReturnTypeImplTrait(func, idx),
279 ref parameters, 321 ref parameters,
280 }) => { 322 })) => {
281 datas = 323 datas =
282 f.db.return_type_impl_traits(func).expect("impl trait id without data"); 324 f.db.return_type_impl_traits(func).expect("impl trait id without data");
283 let data = (*datas) 325 let data = (*datas)
@@ -304,25 +346,24 @@ impl HirDisplay for ApplicationTy {
304 write!(f, "{}", ty_display)?; 346 write!(f, "{}", ty_display)?;
305 } 347 }
306 } 348 }
307 TypeCtor::Never => write!(f, "!")?, 349 Ty::Tuple(_, substs) => {
308 TypeCtor::Tuple { .. } => { 350 if substs.len() == 1 {
309 let ts = &self.parameters;
310 if ts.len() == 1 {
311 write!(f, "(")?; 351 write!(f, "(")?;
312 ts[0].hir_fmt(f)?; 352 substs[0].hir_fmt(f)?;
313 write!(f, ",)")?; 353 write!(f, ",)")?;
314 } else { 354 } else {
315 write!(f, "(")?; 355 write!(f, "(")?;
316 f.write_joined(&*ts.0, ", ")?; 356 f.write_joined(&*substs.0, ", ")?;
317 write!(f, ")")?; 357 write!(f, ")")?;
318 } 358 }
319 } 359 }
320 TypeCtor::FnPtr { is_varargs, .. } => { 360 Ty::Function(fn_ptr) => {
321 let sig = FnSig::from_fn_ptr_substs(&self.parameters, is_varargs); 361 let sig = CallableSig::from_fn_ptr(fn_ptr);
322 sig.hir_fmt(f)?; 362 sig.hir_fmt(f)?;
323 } 363 }
324 TypeCtor::FnDef(def) => { 364 Ty::FnDef(def, parameters) => {
325 let sig = f.db.callable_item_signature(def).subst(&self.parameters); 365 let def = *def;
366 let sig = f.db.callable_item_signature(def).subst(parameters);
326 match def { 367 match def {
327 CallableDefId::FunctionId(ff) => { 368 CallableDefId::FunctionId(ff) => {
328 write!(f, "fn {}", f.db.function_data(ff).name)? 369 write!(f, "fn {}", f.db.function_data(ff).name)?
@@ -332,7 +373,7 @@ impl HirDisplay for ApplicationTy {
332 write!(f, "{}", f.db.enum_data(e.parent).variants[e.local_id].name)? 373 write!(f, "{}", f.db.enum_data(e.parent).variants[e.local_id].name)?
333 } 374 }
334 }; 375 };
335 if self.parameters.len() > 0 { 376 if parameters.len() > 0 {
336 let generics = generics(f.db.upcast(), def.into()); 377 let generics = generics(f.db.upcast(), def.into());
337 let (parent_params, self_param, type_params, _impl_trait_params) = 378 let (parent_params, self_param, type_params, _impl_trait_params) =
338 generics.provenance_split(); 379 generics.provenance_split();
@@ -340,7 +381,7 @@ impl HirDisplay for ApplicationTy {
340 // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self? 381 // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
341 if total_len > 0 { 382 if total_len > 0 {
342 write!(f, "<")?; 383 write!(f, "<")?;
343 f.write_joined(&self.parameters.0[..total_len], ", ")?; 384 f.write_joined(&parameters.0[..total_len], ", ")?;
344 write!(f, ">")?; 385 write!(f, ">")?;
345 } 386 }
346 } 387 }
@@ -359,10 +400,10 @@ impl HirDisplay for ApplicationTy {
359 write!(f, " -> {}", ret_display)?; 400 write!(f, " -> {}", ret_display)?;
360 } 401 }
361 } 402 }
362 TypeCtor::Adt(def_id) => { 403 Ty::Adt(def_id, parameters) => {
363 match f.display_target { 404 match f.display_target {
364 DisplayTarget::Diagnostics | DisplayTarget::Test => { 405 DisplayTarget::Diagnostics | DisplayTarget::Test => {
365 let name = match def_id { 406 let name = match *def_id {
366 AdtId::StructId(it) => f.db.struct_data(it).name.clone(), 407 AdtId::StructId(it) => f.db.struct_data(it).name.clone(),
367 AdtId::UnionId(it) => f.db.union_data(it).name.clone(), 408 AdtId::UnionId(it) => f.db.union_data(it).name.clone(),
368 AdtId::EnumId(it) => f.db.enum_data(it).name.clone(), 409 AdtId::EnumId(it) => f.db.enum_data(it).name.clone(),
@@ -372,7 +413,7 @@ impl HirDisplay for ApplicationTy {
372 DisplayTarget::SourceCode { module_id } => { 413 DisplayTarget::SourceCode { module_id } => {
373 if let Some(path) = find_path::find_path( 414 if let Some(path) = find_path::find_path(
374 f.db.upcast(), 415 f.db.upcast(),
375 ItemInNs::Types(def_id.into()), 416 ItemInNs::Types((*def_id).into()),
376 module_id, 417 module_id,
377 ) { 418 ) {
378 write!(f, "{}", path)?; 419 write!(f, "{}", path)?;
@@ -384,19 +425,18 @@ impl HirDisplay for ApplicationTy {
384 } 425 }
385 } 426 }
386 427
387 if self.parameters.len() > 0 { 428 if parameters.len() > 0 {
388 let parameters_to_write = 429 let parameters_to_write =
389 if f.display_target.is_source_code() || f.omit_verbose_types() { 430 if f.display_target.is_source_code() || f.omit_verbose_types() {
390 match self 431 match self
391 .ctor
392 .as_generic_def() 432 .as_generic_def()
393 .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) 433 .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
394 .filter(|defaults| !defaults.is_empty()) 434 .filter(|defaults| !defaults.is_empty())
395 { 435 {
396 None => self.parameters.0.as_ref(), 436 None => parameters.0.as_ref(),
397 Some(default_parameters) => { 437 Some(default_parameters) => {
398 let mut default_from = 0; 438 let mut default_from = 0;
399 for (i, parameter) in self.parameters.iter().enumerate() { 439 for (i, parameter) in parameters.iter().enumerate() {
400 match (parameter, default_parameters.get(i)) { 440 match (parameter, default_parameters.get(i)) {
401 (&Ty::Unknown, _) | (_, None) => { 441 (&Ty::Unknown, _) | (_, None) => {
402 default_from = i + 1; 442 default_from = i + 1;
@@ -404,18 +444,18 @@ impl HirDisplay for ApplicationTy {
404 (_, Some(default_parameter)) => { 444 (_, Some(default_parameter)) => {
405 let actual_default = default_parameter 445 let actual_default = default_parameter
406 .clone() 446 .clone()
407 .subst(&self.parameters.prefix(i)); 447 .subst(&parameters.prefix(i));
408 if parameter != &actual_default { 448 if parameter != &actual_default {
409 default_from = i + 1; 449 default_from = i + 1;
410 } 450 }
411 } 451 }
412 } 452 }
413 } 453 }
414 &self.parameters.0[0..default_from] 454 &parameters.0[0..default_from]
415 } 455 }
416 } 456 }
417 } else { 457 } else {
418 self.parameters.0.as_ref() 458 parameters.0.as_ref()
419 }; 459 };
420 if !parameters_to_write.is_empty() { 460 if !parameters_to_write.is_empty() {
421 write!(f, "<")?; 461 write!(f, "<")?;
@@ -424,61 +464,54 @@ impl HirDisplay for ApplicationTy {
424 } 464 }
425 } 465 }
426 } 466 }
427 TypeCtor::AssociatedType(type_alias) => { 467 Ty::AssociatedType(type_alias, parameters) => {
428 let trait_ = match type_alias.lookup(f.db.upcast()).container { 468 let trait_ = match type_alias.lookup(f.db.upcast()).container {
429 AssocContainerId::TraitId(it) => it, 469 AssocContainerId::TraitId(it) => it,
430 _ => panic!("not an associated type"), 470 _ => panic!("not an associated type"),
431 }; 471 };
432 let trait_ = f.db.trait_data(trait_); 472 let trait_ = f.db.trait_data(trait_);
433 let type_alias_data = f.db.type_alias_data(type_alias); 473 let type_alias_data = f.db.type_alias_data(*type_alias);
434 474
435 // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) 475 // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types)
436 if f.display_target.is_test() { 476 if f.display_target.is_test() {
437 write!(f, "{}::{}", trait_.name, type_alias_data.name)?; 477 write!(f, "{}::{}", trait_.name, type_alias_data.name)?;
438 if self.parameters.len() > 0 { 478 if parameters.len() > 0 {
439 write!(f, "<")?; 479 write!(f, "<")?;
440 f.write_joined(&*self.parameters.0, ", ")?; 480 f.write_joined(&*parameters.0, ", ")?;
441 write!(f, ">")?; 481 write!(f, ">")?;
442 } 482 }
443 } else { 483 } else {
444 let projection_ty = ProjectionTy { 484 let projection_ty =
445 associated_ty: type_alias, 485 ProjectionTy { associated_ty: *type_alias, parameters: parameters.clone() };
446 parameters: self.parameters.clone(),
447 };
448 486
449 projection_ty.hir_fmt(f)?; 487 projection_ty.hir_fmt(f)?;
450 } 488 }
451 } 489 }
452 TypeCtor::ForeignType(type_alias) => { 490 Ty::ForeignType(type_alias) => {
453 let type_alias = f.db.type_alias_data(type_alias); 491 let type_alias = f.db.type_alias_data(*type_alias);
454 write!(f, "{}", type_alias.name)?; 492 write!(f, "{}", type_alias.name)?;
455 if self.parameters.len() > 0 {
456 write!(f, "<")?;
457 f.write_joined(&*self.parameters.0, ", ")?;
458 write!(f, ">")?;
459 }
460 } 493 }
461 TypeCtor::OpaqueType(opaque_ty_id) => { 494 Ty::OpaqueType(opaque_ty_id, parameters) => {
462 match opaque_ty_id { 495 match opaque_ty_id {
463 OpaqueTyId::ReturnTypeImplTrait(func, idx) => { 496 &OpaqueTyId::ReturnTypeImplTrait(func, idx) => {
464 let datas = 497 let datas =
465 f.db.return_type_impl_traits(func).expect("impl trait id without data"); 498 f.db.return_type_impl_traits(func).expect("impl trait id without data");
466 let data = (*datas) 499 let data = (*datas)
467 .as_ref() 500 .as_ref()
468 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 501 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
469 let bounds = data.subst(&self.parameters); 502 let bounds = data.subst(&parameters);
470 write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; 503 write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?;
471 // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution 504 // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
472 } 505 }
473 OpaqueTyId::AsyncBlockTypeImplTrait(..) => { 506 OpaqueTyId::AsyncBlockTypeImplTrait(..) => {
474 write!(f, "impl Future<Output = ")?; 507 write!(f, "impl Future<Output = ")?;
475 self.parameters[0].hir_fmt(f)?; 508 parameters[0].hir_fmt(f)?;
476 write!(f, ">")?; 509 write!(f, ">")?;
477 } 510 }
478 } 511 }
479 } 512 }
480 TypeCtor::Closure { .. } => { 513 Ty::Closure(.., substs) => {
481 let sig = self.parameters[0].callable_sig(f.db); 514 let sig = substs[0].callable_sig(f.db);
482 if let Some(sig) = sig { 515 if let Some(sig) = sig {
483 if sig.params().is_empty() { 516 if sig.params().is_empty() {
484 write!(f, "||")?; 517 write!(f, "||")?;
@@ -501,44 +534,6 @@ impl HirDisplay for ApplicationTy {
501 write!(f, "{{closure}}")?; 534 write!(f, "{{closure}}")?;
502 } 535 }
503 } 536 }
504 }
505 Ok(())
506 }
507}
508
509impl HirDisplay for ProjectionTy {
510 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
511 if f.should_truncate() {
512 return write!(f, "{}", TYPE_HINT_TRUNCATION);
513 }
514
515 let trait_ = f.db.trait_data(self.trait_(f.db));
516 let first_parameter = self.parameters[0].into_displayable(
517 f.db,
518 f.max_size,
519 f.omit_verbose_types,
520 f.display_target,
521 );
522 write!(f, "<{} as {}", first_parameter, trait_.name)?;
523 if self.parameters.len() > 1 {
524 write!(f, "<")?;
525 f.write_joined(&self.parameters[1..], ", ")?;
526 write!(f, ">")?;
527 }
528 write!(f, ">::{}", f.db.type_alias_data(self.associated_ty).name)?;
529 Ok(())
530 }
531}
532
533impl HirDisplay for Ty {
534 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
535 if f.should_truncate() {
536 return write!(f, "{}", TYPE_HINT_TRUNCATION);
537 }
538
539 match self {
540 Ty::Apply(a_ty) => a_ty.hir_fmt(f)?,
541 Ty::Projection(p_ty) => p_ty.hir_fmt(f)?,
542 Ty::Placeholder(id) => { 537 Ty::Placeholder(id) => {
543 let generics = generics(f.db.upcast(), id.parent); 538 let generics = generics(f.db.upcast(), id.parent);
544 let param_data = &generics.params.types[id.local_id]; 539 let param_data = &generics.params.types[id.local_id];
@@ -557,11 +552,12 @@ impl HirDisplay for Ty {
557 } 552 }
558 } 553 }
559 } 554 }
560 Ty::Bound(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, 555 Ty::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?,
561 Ty::Dyn(predicates) => { 556 Ty::Dyn(predicates) => {
562 write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?; 557 write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?;
563 } 558 }
564 Ty::Opaque(opaque_ty) => { 559 Ty::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?,
560 Ty::Alias(AliasTy::Opaque(opaque_ty)) => {
565 match opaque_ty.opaque_ty_id { 561 match opaque_ty.opaque_ty_id {
566 OpaqueTyId::ReturnTypeImplTrait(func, idx) => { 562 OpaqueTyId::ReturnTypeImplTrait(func, idx) => {
567 let datas = 563 let datas =
@@ -585,13 +581,13 @@ impl HirDisplay for Ty {
585 } 581 }
586 write!(f, "{{unknown}}")?; 582 write!(f, "{{unknown}}")?;
587 } 583 }
588 Ty::Infer(..) => write!(f, "_")?, 584 Ty::InferenceVar(..) => write!(f, "_")?,
589 } 585 }
590 Ok(()) 586 Ok(())
591 } 587 }
592} 588}
593 589
594impl HirDisplay for FnSig { 590impl HirDisplay for CallableSig {
595 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 591 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
596 write!(f, "fn(")?; 592 write!(f, "fn(")?;
597 f.write_joined(self.params(), ", ")?; 593 f.write_joined(self.params(), ", ")?;
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index 4b683c5a7..4d771a91e 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -18,6 +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::Mutability;
21use hir_def::{ 22use hir_def::{
22 body::Body, 23 body::Body,
23 data::{ConstData, FunctionData, StaticData}, 24 data::{ConstData, FunctionData, StaticData},
@@ -25,7 +26,7 @@ use hir_def::{
25 lang_item::LangItemTarget, 26 lang_item::LangItemTarget,
26 path::{path, Path}, 27 path::{path, Path},
27 resolver::{HasResolver, Resolver, TypeNs}, 28 resolver::{HasResolver, Resolver, TypeNs},
28 type_ref::{Mutability, TypeRef}, 29 type_ref::TypeRef,
29 AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, Lookup, TraitId, 30 AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, Lookup, TraitId,
30 TypeAliasId, VariantId, 31 TypeAliasId, VariantId,
31}; 32};
@@ -36,25 +37,15 @@ use stdx::impl_from;
36use syntax::SmolStr; 37use syntax::SmolStr;
37 38
38use super::{ 39use super::{
39 primitive::{FloatTy, IntTy},
40 traits::{Guidance, Obligation, ProjectionPredicate, Solution}, 40 traits::{Guidance, Obligation, ProjectionPredicate, Solution},
41 InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, 41 InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeWalk,
42}; 42};
43use crate::{ 43use crate::{
44 db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, 44 db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, AliasTy,
45}; 45};
46 46
47pub(crate) use unify::unify; 47pub(crate) use unify::unify;
48 48
49macro_rules! ty_app {
50 ($ctor:pat, $param:pat) => {
51 crate::Ty::Apply(crate::ApplicationTy { ctor: $ctor, parameters: $param })
52 };
53 ($ctor:pat) => {
54 ty_app!($ctor, _)
55 };
56}
57
58mod unify; 49mod unify;
59mod path; 50mod path;
60mod expr; 51mod expr;
@@ -97,7 +88,7 @@ impl BindingMode {
97 fn convert(annotation: BindingAnnotation) -> BindingMode { 88 fn convert(annotation: BindingAnnotation) -> BindingMode {
98 match annotation { 89 match annotation {
99 BindingAnnotation::Unannotated | BindingAnnotation::Mutable => BindingMode::Move, 90 BindingAnnotation::Unannotated | BindingAnnotation::Mutable => BindingMode::Move,
100 BindingAnnotation::Ref => BindingMode::Ref(Mutability::Shared), 91 BindingAnnotation::Ref => BindingMode::Ref(Mutability::Not),
101 BindingAnnotation::RefMut => BindingMode::Ref(Mutability::Mut), 92 BindingAnnotation::RefMut => BindingMode::Ref(Mutability::Mut),
102 } 93 }
103 } 94 }
@@ -405,7 +396,7 @@ impl<'a> InferenceContext<'a> {
405 fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { 396 fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty {
406 let ty = self.resolve_ty_as_possible(ty); 397 let ty = self.resolve_ty_as_possible(ty);
407 ty.fold(&mut |ty| match ty { 398 ty.fold(&mut |ty| match ty {
408 Ty::Projection(proj_ty) => self.normalize_projection_ty(proj_ty), 399 Ty::Alias(AliasTy::Projection(proj_ty)) => self.normalize_projection_ty(proj_ty),
409 _ => ty, 400 _ => ty,
410 }) 401 })
411 } 402 }
@@ -664,30 +655,17 @@ impl<'a> InferenceContext<'a> {
664/// two are used for inference of literal values (e.g. `100` could be one of 655/// two are used for inference of literal values (e.g. `100` could be one of
665/// several integer types). 656/// several integer types).
666#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] 657#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
667pub enum InferTy { 658pub struct InferenceVar {
668 TypeVar(unify::TypeVarId), 659 index: u32,
669 IntVar(unify::TypeVarId),
670 FloatVar(unify::TypeVarId),
671 MaybeNeverTypeVar(unify::TypeVarId),
672} 660}
673 661
674impl InferTy { 662impl InferenceVar {
675 fn to_inner(self) -> unify::TypeVarId { 663 fn to_inner(self) -> unify::TypeVarId {
676 match self { 664 unify::TypeVarId(self.index)
677 InferTy::TypeVar(ty)
678 | InferTy::IntVar(ty)
679 | InferTy::FloatVar(ty)
680 | InferTy::MaybeNeverTypeVar(ty) => ty,
681 }
682 } 665 }
683 666
684 fn fallback_value(self) -> Ty { 667 fn from_inner(unify::TypeVarId(index): unify::TypeVarId) -> Self {
685 match self { 668 InferenceVar { index }
686 InferTy::TypeVar(..) => Ty::Unknown,
687 InferTy::IntVar(..) => Ty::simple(TypeCtor::Int(IntTy::i32())),
688 InferTy::FloatVar(..) => Ty::simple(TypeCtor::Float(FloatTy::f64())),
689 InferTy::MaybeNeverTypeVar(..) => Ty::simple(TypeCtor::Never),
690 }
691 } 669 }
692} 670}
693 671
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs
index 32c7c57cd..cf0a3add4 100644
--- a/crates/hir_ty/src/infer/coerce.rs
+++ b/crates/hir_ty/src/infer/coerce.rs
@@ -4,12 +4,13 @@
4//! 4//!
5//! See: https://doc.rust-lang.org/nomicon/coercions.html 5//! See: https://doc.rust-lang.org/nomicon/coercions.html
6 6
7use hir_def::{lang_item::LangItemTarget, type_ref::Mutability}; 7use chalk_ir::{Mutability, TyVariableKind};
8use hir_def::lang_item::LangItemTarget;
8use test_utils::mark; 9use test_utils::mark;
9 10
10use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty, TypeCtor}; 11use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty};
11 12
12use super::{unify::TypeVarValue, InEnvironment, InferTy, InferenceContext}; 13use super::{InEnvironment, InferenceContext};
13 14
14impl<'a> InferenceContext<'a> { 15impl<'a> InferenceContext<'a> {
15 /// Unify two types, but may coerce the first one to the second one 16 /// Unify two types, but may coerce the first one to the second one
@@ -33,7 +34,7 @@ impl<'a> InferenceContext<'a> {
33 } else if self.coerce(ty2, ty1) { 34 } else if self.coerce(ty2, ty1) {
34 ty1.clone() 35 ty1.clone()
35 } else { 36 } else {
36 if let (ty_app!(TypeCtor::FnDef(_)), ty_app!(TypeCtor::FnDef(_))) = (ty1, ty2) { 37 if let (Ty::FnDef(..), Ty::FnDef(..)) = (ty1, ty2) {
37 mark::hit!(coerce_fn_reification); 38 mark::hit!(coerce_fn_reification);
38 // Special case: two function types. Try to coerce both to 39 // Special case: two function types. Try to coerce both to
39 // pointers to have a chance at getting a match. See 40 // pointers to have a chance at getting a match. See
@@ -53,12 +54,11 @@ impl<'a> InferenceContext<'a> {
53 fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool { 54 fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool {
54 match (&from_ty, to_ty) { 55 match (&from_ty, to_ty) {
55 // Never type will make type variable to fallback to Never Type instead of Unknown. 56 // Never type will make type variable to fallback to Never Type instead of Unknown.
56 (ty_app!(TypeCtor::Never), Ty::Infer(InferTy::TypeVar(tv))) => { 57 (Ty::Never, Ty::InferenceVar(tv, TyVariableKind::General)) => {
57 let var = self.table.new_maybe_never_type_var(); 58 self.table.type_variable_table.set_diverging(*tv, true);
58 self.table.var_unification_table.union_value(*tv, TypeVarValue::Known(var));
59 return true; 59 return true;
60 } 60 }
61 (ty_app!(TypeCtor::Never), _) => return true, 61 (Ty::Never, _) => return true,
62 62
63 // Trivial cases, this should go after `never` check to 63 // Trivial cases, this should go after `never` check to
64 // avoid infer result type to be never 64 // avoid infer result type to be never
@@ -71,38 +71,33 @@ impl<'a> InferenceContext<'a> {
71 71
72 // Pointer weakening and function to pointer 72 // Pointer weakening and function to pointer
73 match (&mut from_ty, to_ty) { 73 match (&mut from_ty, to_ty) {
74 // `*mut T`, `&mut T, `&T`` -> `*const T` 74 // `*mut T` -> `*const T`
75 // `&mut T` -> `&T` 75 // `&mut T` -> `&T`
76 // `&mut T` -> `*mut T` 76 (Ty::Raw(m1, ..), Ty::Raw(m2 @ Mutability::Not, ..))
77 (ty_app!(c1@TypeCtor::RawPtr(_)), ty_app!(c2@TypeCtor::RawPtr(Mutability::Shared))) 77 | (Ty::Ref(m1, ..), Ty::Ref(m2 @ Mutability::Not, ..)) => {
78 | (ty_app!(c1@TypeCtor::Ref(_)), ty_app!(c2@TypeCtor::RawPtr(Mutability::Shared))) 78 *m1 = *m2;
79 | (ty_app!(c1@TypeCtor::Ref(_)), ty_app!(c2@TypeCtor::Ref(Mutability::Shared))) 79 }
80 | (ty_app!(c1@TypeCtor::Ref(Mutability::Mut)), ty_app!(c2@TypeCtor::RawPtr(_))) => { 80 // `&T` -> `*const T`
81 *c1 = *c2; 81 // `&mut T` -> `*mut T`/`*const T`
82 (Ty::Ref(.., substs), &Ty::Raw(m2 @ Mutability::Not, ..))
83 | (Ty::Ref(Mutability::Mut, substs), &Ty::Raw(m2, ..)) => {
84 from_ty = Ty::Raw(m2, substs.clone());
82 } 85 }
83 86
84 // Illegal mutablity conversion 87 // Illegal mutability conversion
85 ( 88 (Ty::Raw(Mutability::Not, ..), Ty::Raw(Mutability::Mut, ..))
86 ty_app!(TypeCtor::RawPtr(Mutability::Shared)), 89 | (Ty::Ref(Mutability::Not, ..), Ty::Ref(Mutability::Mut, ..)) => return false,
87 ty_app!(TypeCtor::RawPtr(Mutability::Mut)),
88 )
89 | (
90 ty_app!(TypeCtor::Ref(Mutability::Shared)),
91 ty_app!(TypeCtor::Ref(Mutability::Mut)),
92 ) => return false,
93 90
94 // `{function_type}` -> `fn()` 91 // `{function_type}` -> `fn()`
95 (ty_app!(TypeCtor::FnDef(_)), ty_app!(TypeCtor::FnPtr { .. })) => { 92 (Ty::FnDef(..), Ty::Function { .. }) => match from_ty.callable_sig(self.db) {
96 match from_ty.callable_sig(self.db) { 93 None => return false,
97 None => return false, 94 Some(sig) => {
98 Some(sig) => { 95 from_ty = Ty::fn_ptr(sig);
99 from_ty = Ty::fn_ptr(sig);
100 }
101 } 96 }
102 } 97 },
103 98
104 (ty_app!(TypeCtor::Closure { .. }, params), ty_app!(TypeCtor::FnPtr { .. })) => { 99 (Ty::Closure(.., substs), Ty::Function { .. }) => {
105 from_ty = params[0].clone(); 100 from_ty = substs[0].clone();
106 } 101 }
107 102
108 _ => {} 103 _ => {}
@@ -115,9 +110,7 @@ impl<'a> InferenceContext<'a> {
115 // Auto Deref if cannot coerce 110 // Auto Deref if cannot coerce
116 match (&from_ty, to_ty) { 111 match (&from_ty, to_ty) {
117 // FIXME: DerefMut 112 // FIXME: DerefMut
118 (ty_app!(TypeCtor::Ref(_), st1), ty_app!(TypeCtor::Ref(_), st2)) => { 113 (Ty::Ref(_, st1), Ty::Ref(_, st2)) => self.unify_autoderef_behind_ref(&st1[0], &st2[0]),
119 self.unify_autoderef_behind_ref(&st1[0], &st2[0])
120 }
121 114
122 // Otherwise, normal unify 115 // Otherwise, normal unify
123 _ => self.unify(&from_ty, to_ty), 116 _ => self.unify(&from_ty, to_ty),
@@ -178,17 +171,17 @@ impl<'a> InferenceContext<'a> {
178 }, 171 },
179 ) { 172 ) {
180 let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); 173 let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value);
181 match (&*self.resolve_ty_shallow(&derefed_ty), &*to_ty) { 174 let from_ty = self.resolve_ty_shallow(&derefed_ty);
182 // Stop when constructor matches. 175 // Stop when constructor matches.
183 (ty_app!(from_ctor, st1), ty_app!(to_ctor, st2)) if from_ctor == to_ctor => { 176 if from_ty.equals_ctor(&to_ty) {
184 // It will not recurse to `coerce`. 177 // It will not recurse to `coerce`.
185 return self.table.unify_substs(st1, st2, 0); 178 return match (from_ty.substs(), to_ty.substs()) {
186 } 179 (Some(st1), Some(st2)) => self.table.unify_substs(st1, st2, 0),
187 _ => { 180 (None, None) => true,
188 if self.table.unify_inner_trivial(&derefed_ty, &to_ty, 0) { 181 _ => false,
189 return true; 182 };
190 } 183 } else if self.table.unify_inner_trivial(&derefed_ty, &to_ty, 0) {
191 } 184 return true;
192 } 185 }
193 } 186 }
194 187
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index cb59a6937..cf1f1038a 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -3,8 +3,8 @@
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::{Mutability, TyVariableKind};
6use hir_def::{ 7use hir_def::{
7 builtin_type::Signedness,
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},
10 resolver::resolver_for_expr, 10 resolver::resolver_for_expr,
@@ -15,11 +15,14 @@ use syntax::ast::RangeOp;
15use test_utils::mark; 15use test_utils::mark;
16 16
17use crate::{ 17use crate::{
18 autoderef, method_resolution, op, 18 autoderef,
19 lower::lower_to_chalk_mutability,
20 method_resolution, op,
21 primitive::{self, UintTy},
19 traits::{FnTrait, InEnvironment}, 22 traits::{FnTrait, InEnvironment},
20 utils::{generics, variant_data, Generics}, 23 utils::{generics, variant_data, Generics},
21 ApplicationTy, Binders, CallableDefId, InferTy, IntTy, Mutability, Obligation, OpaqueTyId, 24 Binders, CallableDefId, FnPointer, FnSig, Obligation, OpaqueTyId, Rawness, Scalar, Substs,
22 Rawness, Substs, TraitRef, Ty, TypeCtor, 25 TraitRef, Ty,
23}; 26};
24 27
25use super::{ 28use super::{
@@ -82,10 +85,7 @@ impl<'a> InferenceContext<'a> {
82 arg_tys.push(arg); 85 arg_tys.push(arg);
83 } 86 }
84 let parameters = param_builder.build(); 87 let parameters = param_builder.build();
85 let arg_ty = Ty::Apply(ApplicationTy { 88 let arg_ty = Ty::Tuple(num_args, parameters);
86 ctor: TypeCtor::Tuple { cardinality: num_args as u16 },
87 parameters,
88 });
89 let substs = 89 let substs =
90 Substs::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); 90 Substs::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build();
91 91
@@ -120,7 +120,7 @@ impl<'a> InferenceContext<'a> {
120 Expr::Missing => Ty::Unknown, 120 Expr::Missing => Ty::Unknown,
121 Expr::If { condition, then_branch, else_branch } => { 121 Expr::If { condition, then_branch, else_branch } => {
122 // if let is desugared to match, so this is always simple if 122 // if let is desugared to match, so this is always simple if
123 self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); 123 self.infer_expr(*condition, &Expectation::has_type(Ty::Scalar(Scalar::Bool)));
124 124
125 let condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); 125 let condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
126 let mut both_arms_diverge = Diverges::Always; 126 let mut both_arms_diverge = Diverges::Always;
@@ -175,7 +175,7 @@ impl<'a> InferenceContext<'a> {
175 // existenail type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType> 175 // existenail type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType>
176 let inner_ty = self.infer_expr(*body, &Expectation::none()); 176 let inner_ty = self.infer_expr(*body, &Expectation::none());
177 let opaque_ty_id = OpaqueTyId::AsyncBlockTypeImplTrait(self.owner, *body); 177 let opaque_ty_id = OpaqueTyId::AsyncBlockTypeImplTrait(self.owner, *body);
178 Ty::apply_one(TypeCtor::OpaqueType(opaque_ty_id), inner_ty) 178 Ty::OpaqueType(opaque_ty_id, Substs::single(inner_ty))
179 } 179 }
180 Expr::Loop { body, label } => { 180 Expr::Loop { body, label } => {
181 self.breakables.push(BreakableContext { 181 self.breakables.push(BreakableContext {
@@ -193,7 +193,7 @@ impl<'a> InferenceContext<'a> {
193 if ctxt.may_break { 193 if ctxt.may_break {
194 ctxt.break_ty 194 ctxt.break_ty
195 } else { 195 } else {
196 Ty::simple(TypeCtor::Never) 196 Ty::Never
197 } 197 }
198 } 198 }
199 Expr::While { condition, body, label } => { 199 Expr::While { condition, body, label } => {
@@ -203,7 +203,7 @@ impl<'a> InferenceContext<'a> {
203 label: label.map(|label| self.body[label].name.clone()), 203 label: label.map(|label| self.body[label].name.clone()),
204 }); 204 });
205 // while let is desugared to a match loop, so this is always simple while 205 // while let is desugared to a match loop, so this is always simple while
206 self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); 206 self.infer_expr(*condition, &Expectation::has_type(Ty::Scalar(Scalar::Bool)));
207 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 207 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
208 let _ctxt = self.breakables.pop().expect("breakable stack broken"); 208 let _ctxt = self.breakables.pop().expect("breakable stack broken");
209 // the body may not run, so it diverging doesn't mean we diverge 209 // the body may not run, so it diverging doesn't mean we diverge
@@ -250,12 +250,12 @@ impl<'a> InferenceContext<'a> {
250 None => self.table.new_type_var(), 250 None => self.table.new_type_var(),
251 }; 251 };
252 sig_tys.push(ret_ty.clone()); 252 sig_tys.push(ret_ty.clone());
253 let sig_ty = Ty::apply( 253 let sig_ty = Ty::Function(FnPointer {
254 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1, is_varargs: false }, 254 num_args: sig_tys.len() - 1,
255 Substs(sig_tys.clone().into()), 255 sig: FnSig { variadic: false },
256 ); 256 substs: Substs(sig_tys.clone().into()),
257 let closure_ty = 257 });
258 Ty::apply_one(TypeCtor::Closure { def: self.owner, expr: tgt_expr }, sig_ty); 258 let closure_ty = Ty::Closure(self.owner, tgt_expr, Substs::single(sig_ty));
259 259
260 // Eagerly try to relate the closure type with the expected 260 // Eagerly try to relate the closure type with the expected
261 // type, otherwise we often won't have enough information to 261 // type, otherwise we often won't have enough information to
@@ -306,11 +306,8 @@ impl<'a> InferenceContext<'a> {
306 Expr::Match { expr, arms } => { 306 Expr::Match { expr, arms } => {
307 let input_ty = self.infer_expr(*expr, &Expectation::none()); 307 let input_ty = self.infer_expr(*expr, &Expectation::none());
308 308
309 let mut result_ty = if arms.is_empty() { 309 let mut result_ty =
310 Ty::simple(TypeCtor::Never) 310 if arms.is_empty() { Ty::Never } else { self.table.new_type_var() };
311 } else {
312 self.table.new_type_var()
313 };
314 311
315 let matchee_diverges = self.diverges; 312 let matchee_diverges = self.diverges;
316 let mut all_arms_diverge = Diverges::Always; 313 let mut all_arms_diverge = Diverges::Always;
@@ -321,7 +318,7 @@ impl<'a> InferenceContext<'a> {
321 if let Some(guard_expr) = arm.guard { 318 if let Some(guard_expr) = arm.guard {
322 self.infer_expr( 319 self.infer_expr(
323 guard_expr, 320 guard_expr,
324 &Expectation::has_type(Ty::simple(TypeCtor::Bool)), 321 &Expectation::has_type(Ty::Scalar(Scalar::Bool)),
325 ); 322 );
326 } 323 }
327 324
@@ -339,7 +336,7 @@ impl<'a> InferenceContext<'a> {
339 let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); 336 let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr);
340 self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown) 337 self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown)
341 } 338 }
342 Expr::Continue { .. } => Ty::simple(TypeCtor::Never), 339 Expr::Continue { .. } => Ty::Never,
343 Expr::Break { expr, label } => { 340 Expr::Break { expr, label } => {
344 let val_ty = if let Some(expr) = expr { 341 let val_ty = if let Some(expr) = expr {
345 self.infer_expr(*expr, &Expectation::none()) 342 self.infer_expr(*expr, &Expectation::none())
@@ -364,8 +361,7 @@ impl<'a> InferenceContext<'a> {
364 expr: tgt_expr, 361 expr: tgt_expr,
365 }); 362 });
366 } 363 }
367 364 Ty::Never
368 Ty::simple(TypeCtor::Never)
369 } 365 }
370 Expr::Return { expr } => { 366 Expr::Return { expr } => {
371 if let Some(expr) = expr { 367 if let Some(expr) = expr {
@@ -374,14 +370,14 @@ impl<'a> InferenceContext<'a> {
374 let unit = Ty::unit(); 370 let unit = Ty::unit();
375 self.coerce(&unit, &self.return_ty.clone()); 371 self.coerce(&unit, &self.return_ty.clone());
376 } 372 }
377 Ty::simple(TypeCtor::Never) 373 Ty::Never
378 } 374 }
379 Expr::Yield { expr } => { 375 Expr::Yield { expr } => {
380 // FIXME: track yield type for coercion 376 // FIXME: track yield type for coercion
381 if let Some(expr) = expr { 377 if let Some(expr) = expr {
382 self.infer_expr(*expr, &Expectation::none()); 378 self.infer_expr(*expr, &Expectation::none());
383 } 379 }
384 Ty::simple(TypeCtor::Never) 380 Ty::Never
385 } 381 }
386 Expr::RecordLit { path, fields, spread } => { 382 Expr::RecordLit { path, fields, spread } => {
387 let (ty, def_id) = self.resolve_variant(path.as_ref()); 383 let (ty, def_id) = self.resolve_variant(path.as_ref());
@@ -391,7 +387,7 @@ impl<'a> InferenceContext<'a> {
391 387
392 self.unify(&ty, &expected.ty); 388 self.unify(&ty, &expected.ty);
393 389
394 let substs = ty.substs().unwrap_or_else(Substs::empty); 390 let substs = ty.substs().cloned().unwrap_or_else(Substs::empty);
395 let field_types = def_id.map(|it| self.db.field_types(it)).unwrap_or_default(); 391 let field_types = def_id.map(|it| self.db.field_types(it)).unwrap_or_default();
396 let variant_data = def_id.map(|it| variant_data(self.db.upcast(), it)); 392 let variant_data = def_id.map(|it| variant_data(self.db.upcast(), it));
397 for (field_idx, field) in fields.iter().enumerate() { 393 for (field_idx, field) in fields.iter().enumerate() {
@@ -430,30 +426,23 @@ impl<'a> InferenceContext<'a> {
430 }, 426 },
431 ) 427 )
432 .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) { 428 .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) {
433 Ty::Apply(a_ty) => match a_ty.ctor { 429 Ty::Tuple(_, substs) => {
434 TypeCtor::Tuple { .. } => name 430 name.as_tuple_index().and_then(|idx| substs.0.get(idx).cloned())
435 .as_tuple_index() 431 }
436 .and_then(|idx| a_ty.parameters.0.get(idx).cloned()), 432 Ty::Adt(AdtId::StructId(s), parameters) => {
437 TypeCtor::Adt(AdtId::StructId(s)) => { 433 self.db.struct_data(s).variant_data.field(name).map(|local_id| {
438 self.db.struct_data(s).variant_data.field(name).map(|local_id| { 434 let field = FieldId { parent: s.into(), local_id };
439 let field = FieldId { parent: s.into(), local_id }; 435 self.write_field_resolution(tgt_expr, field);
440 self.write_field_resolution(tgt_expr, field); 436 self.db.field_types(s.into())[field.local_id].clone().subst(&parameters)
441 self.db.field_types(s.into())[field.local_id] 437 })
442 .clone() 438 }
443 .subst(&a_ty.parameters) 439 Ty::Adt(AdtId::UnionId(u), parameters) => {
444 }) 440 self.db.union_data(u).variant_data.field(name).map(|local_id| {
445 } 441 let field = FieldId { parent: u.into(), local_id };
446 TypeCtor::Adt(AdtId::UnionId(u)) => { 442 self.write_field_resolution(tgt_expr, field);
447 self.db.union_data(u).variant_data.field(name).map(|local_id| { 443 self.db.field_types(u.into())[field.local_id].clone().subst(&parameters)
448 let field = FieldId { parent: u.into(), local_id }; 444 })
449 self.write_field_resolution(tgt_expr, field); 445 }
450 self.db.field_types(u.into())[field.local_id]
451 .clone()
452 .subst(&a_ty.parameters)
453 })
454 }
455 _ => None,
456 },
457 _ => None, 446 _ => None,
458 }) 447 })
459 .unwrap_or(Ty::Unknown); 448 .unwrap_or(Ty::Unknown);
@@ -475,10 +464,11 @@ impl<'a> InferenceContext<'a> {
475 cast_ty 464 cast_ty
476 } 465 }
477 Expr::Ref { expr, rawness, mutability } => { 466 Expr::Ref { expr, rawness, mutability } => {
467 let mutability = lower_to_chalk_mutability(*mutability);
478 let expectation = if let Some((exp_inner, exp_rawness, exp_mutability)) = 468 let expectation = if let Some((exp_inner, exp_rawness, exp_mutability)) =
479 &expected.ty.as_reference_or_ptr() 469 &expected.ty.as_reference_or_ptr()
480 { 470 {
481 if *exp_mutability == Mutability::Mut && *mutability == Mutability::Shared { 471 if *exp_mutability == Mutability::Mut && mutability == Mutability::Not {
482 // FIXME: throw type error - expected mut reference but found shared ref, 472 // FIXME: throw type error - expected mut reference but found shared ref,
483 // which cannot be coerced 473 // which cannot be coerced
484 } 474 }
@@ -491,19 +481,24 @@ impl<'a> InferenceContext<'a> {
491 Expectation::none() 481 Expectation::none()
492 }; 482 };
493 let inner_ty = self.infer_expr_inner(*expr, &expectation); 483 let inner_ty = self.infer_expr_inner(*expr, &expectation);
494 let ty = match rawness { 484 match rawness {
495 Rawness::RawPtr => TypeCtor::RawPtr(*mutability), 485 Rawness::RawPtr => Ty::Raw(mutability, Substs::single(inner_ty)),
496 Rawness::Ref => TypeCtor::Ref(*mutability), 486 Rawness::Ref => Ty::Ref(mutability, Substs::single(inner_ty)),
497 }; 487 }
498 Ty::apply_one(ty, inner_ty)
499 } 488 }
500 Expr::Box { expr } => { 489 Expr::Box { expr } => {
501 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); 490 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
502 if let Some(box_) = self.resolve_boxed_box() { 491 if let Some(box_) = self.resolve_boxed_box() {
503 let mut sb = Substs::build_for_type_ctor(self.db, TypeCtor::Adt(box_)); 492 let mut sb = Substs::builder(generics(self.db.upcast(), box_.into()).len());
504 sb = sb.push(inner_ty); 493 sb = sb.push(inner_ty);
494 match self.db.generic_defaults(box_.into()).as_ref() {
495 [_, alloc_ty, ..] if !alloc_ty.value.is_unknown() => {
496 sb = sb.push(alloc_ty.value.clone());
497 }
498 _ => (),
499 }
505 sb = sb.fill(repeat_with(|| self.table.new_type_var())); 500 sb = sb.fill(repeat_with(|| self.table.new_type_var()));
506 Ty::apply(TypeCtor::Adt(box_), sb.build()) 501 Ty::Adt(box_, sb.build())
507 } else { 502 } else {
508 Ty::Unknown 503 Ty::Unknown
509 } 504 }
@@ -533,13 +528,11 @@ impl<'a> InferenceContext<'a> {
533 UnaryOp::Neg => { 528 UnaryOp::Neg => {
534 match &inner_ty { 529 match &inner_ty {
535 // Fast path for builtins 530 // Fast path for builtins
536 Ty::Apply(ApplicationTy { 531 Ty::Scalar(Scalar::Int(_))
537 ctor: TypeCtor::Int(IntTy { signedness: Signedness::Signed, .. }), 532 | Ty::Scalar(Scalar::Uint(_))
538 .. 533 | Ty::Scalar(Scalar::Float(_))
539 }) 534 | Ty::InferenceVar(_, TyVariableKind::Integer)
540 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Float(_), .. }) 535 | Ty::InferenceVar(_, TyVariableKind::Float) => inner_ty,
541 | Ty::Infer(InferTy::IntVar(..))
542 | Ty::Infer(InferTy::FloatVar(..)) => inner_ty,
543 // Otherwise we resolve via the std::ops::Neg trait 536 // Otherwise we resolve via the std::ops::Neg trait
544 _ => self 537 _ => self
545 .resolve_associated_type(inner_ty, self.resolve_ops_neg_output()), 538 .resolve_associated_type(inner_ty, self.resolve_ops_neg_output()),
@@ -548,9 +541,10 @@ impl<'a> InferenceContext<'a> {
548 UnaryOp::Not => { 541 UnaryOp::Not => {
549 match &inner_ty { 542 match &inner_ty {
550 // Fast path for builtins 543 // Fast path for builtins
551 Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. }) 544 Ty::Scalar(Scalar::Bool)
552 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Int(_), .. }) 545 | Ty::Scalar(Scalar::Int(_))
553 | Ty::Infer(InferTy::IntVar(..)) => inner_ty, 546 | Ty::Scalar(Scalar::Uint(_))
547 | Ty::InferenceVar(_, TyVariableKind::Integer) => inner_ty,
554 // Otherwise we resolve via the std::ops::Not trait 548 // Otherwise we resolve via the std::ops::Not trait
555 _ => self 549 _ => self
556 .resolve_associated_type(inner_ty, self.resolve_ops_not_output()), 550 .resolve_associated_type(inner_ty, self.resolve_ops_not_output()),
@@ -561,7 +555,7 @@ impl<'a> InferenceContext<'a> {
561 Expr::BinaryOp { lhs, rhs, op } => match op { 555 Expr::BinaryOp { lhs, rhs, op } => match op {
562 Some(op) => { 556 Some(op) => {
563 let lhs_expectation = match op { 557 let lhs_expectation = match op {
564 BinaryOp::LogicOp(..) => Expectation::has_type(Ty::simple(TypeCtor::Bool)), 558 BinaryOp::LogicOp(..) => Expectation::has_type(Ty::Scalar(Scalar::Bool)),
565 _ => Expectation::none(), 559 _ => Expectation::none(),
566 }; 560 };
567 let lhs_ty = self.infer_expr(*lhs, &lhs_expectation); 561 let lhs_ty = self.infer_expr(*lhs, &lhs_expectation);
@@ -592,31 +586,31 @@ impl<'a> InferenceContext<'a> {
592 let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect)); 586 let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect));
593 match (range_type, lhs_ty, rhs_ty) { 587 match (range_type, lhs_ty, rhs_ty) {
594 (RangeOp::Exclusive, None, None) => match self.resolve_range_full() { 588 (RangeOp::Exclusive, None, None) => match self.resolve_range_full() {
595 Some(adt) => Ty::simple(TypeCtor::Adt(adt)), 589 Some(adt) => Ty::Adt(adt, Substs::empty()),
596 None => Ty::Unknown, 590 None => Ty::Unknown,
597 }, 591 },
598 (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() { 592 (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() {
599 Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), 593 Some(adt) => Ty::Adt(adt, Substs::single(ty)),
600 None => Ty::Unknown, 594 None => Ty::Unknown,
601 }, 595 },
602 (RangeOp::Inclusive, None, Some(ty)) => { 596 (RangeOp::Inclusive, None, Some(ty)) => {
603 match self.resolve_range_to_inclusive() { 597 match self.resolve_range_to_inclusive() {
604 Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), 598 Some(adt) => Ty::Adt(adt, Substs::single(ty)),
605 None => Ty::Unknown, 599 None => Ty::Unknown,
606 } 600 }
607 } 601 }
608 (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() { 602 (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() {
609 Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), 603 Some(adt) => Ty::Adt(adt, Substs::single(ty)),
610 None => Ty::Unknown, 604 None => Ty::Unknown,
611 }, 605 },
612 (RangeOp::Inclusive, Some(_), Some(ty)) => { 606 (RangeOp::Inclusive, Some(_), Some(ty)) => {
613 match self.resolve_range_inclusive() { 607 match self.resolve_range_inclusive() {
614 Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), 608 Some(adt) => Ty::Adt(adt, Substs::single(ty)),
615 None => Ty::Unknown, 609 None => Ty::Unknown,
616 } 610 }
617 } 611 }
618 (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() { 612 (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() {
619 Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), 613 Some(adt) => Ty::Adt(adt, Substs::single(ty)),
620 None => Ty::Unknown, 614 None => Ty::Unknown,
621 }, 615 },
622 (RangeOp::Inclusive, _, None) => Ty::Unknown, 616 (RangeOp::Inclusive, _, None) => Ty::Unknown,
@@ -650,7 +644,7 @@ impl<'a> InferenceContext<'a> {
650 } 644 }
651 Expr::Tuple { exprs } => { 645 Expr::Tuple { exprs } => {
652 let mut tys = match &expected.ty { 646 let mut tys = match &expected.ty {
653 ty_app!(TypeCtor::Tuple { .. }, st) => st 647 Ty::Tuple(_, substs) => substs
654 .iter() 648 .iter()
655 .cloned() 649 .cloned()
656 .chain(repeat_with(|| self.table.new_type_var())) 650 .chain(repeat_with(|| self.table.new_type_var()))
@@ -663,15 +657,11 @@ impl<'a> InferenceContext<'a> {
663 self.infer_expr_coerce(*expr, &Expectation::has_type(ty.clone())); 657 self.infer_expr_coerce(*expr, &Expectation::has_type(ty.clone()));
664 } 658 }
665 659
666 Ty::apply(TypeCtor::Tuple { cardinality: tys.len() as u16 }, Substs(tys.into())) 660 Ty::Tuple(tys.len(), Substs(tys.into()))
667 } 661 }
668 Expr::Array(array) => { 662 Expr::Array(array) => {
669 let elem_ty = match &expected.ty { 663 let elem_ty = match &expected.ty {
670 // FIXME: remove when https://github.com/rust-lang/rust/issues/80501 is fixed 664 Ty::Array(st) | Ty::Slice(st) => st.as_single().clone(),
671 #[allow(unreachable_patterns)]
672 ty_app!(TypeCtor::Array, st) | ty_app!(TypeCtor::Slice, st) => {
673 st.as_single().clone()
674 }
675 _ => self.table.new_type_var(), 665 _ => self.table.new_type_var(),
676 }; 666 };
677 667
@@ -688,30 +678,38 @@ impl<'a> InferenceContext<'a> {
688 ); 678 );
689 self.infer_expr( 679 self.infer_expr(
690 *repeat, 680 *repeat,
691 &Expectation::has_type(Ty::simple(TypeCtor::Int(IntTy::usize()))), 681 &Expectation::has_type(Ty::Scalar(Scalar::Uint(UintTy::Usize))),
692 ); 682 );
693 } 683 }
694 } 684 }
695 685
696 Ty::apply_one(TypeCtor::Array, elem_ty) 686 Ty::Array(Substs::single(elem_ty))
697 } 687 }
698 Expr::Literal(lit) => match lit { 688 Expr::Literal(lit) => match lit {
699 Literal::Bool(..) => Ty::simple(TypeCtor::Bool), 689 Literal::Bool(..) => Ty::Scalar(Scalar::Bool),
700 Literal::String(..) => { 690 Literal::String(..) => Ty::Ref(Mutability::Not, Substs::single(Ty::Str)),
701 Ty::apply_one(TypeCtor::Ref(Mutability::Shared), Ty::simple(TypeCtor::Str))
702 }
703 Literal::ByteString(..) => { 691 Literal::ByteString(..) => {
704 let byte_type = Ty::simple(TypeCtor::Int(IntTy::u8())); 692 let byte_type = Ty::Scalar(Scalar::Uint(UintTy::U8));
705 let array_type = Ty::apply_one(TypeCtor::Array, byte_type); 693 let array_type = Ty::Array(Substs::single(byte_type));
706 Ty::apply_one(TypeCtor::Ref(Mutability::Shared), array_type) 694 Ty::Ref(Mutability::Not, Substs::single(array_type))
707 } 695 }
708 Literal::Char(..) => Ty::simple(TypeCtor::Char), 696 Literal::Char(..) => Ty::Scalar(Scalar::Char),
709 Literal::Int(_v, ty) => match ty { 697 Literal::Int(_v, ty) => match ty {
710 Some(int_ty) => Ty::simple(TypeCtor::Int((*int_ty).into())), 698 Some(int_ty) => {
699 Ty::Scalar(Scalar::Int(primitive::int_ty_from_builtin(*int_ty)))
700 }
701 None => self.table.new_integer_var(),
702 },
703 Literal::Uint(_v, ty) => match ty {
704 Some(int_ty) => {
705 Ty::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(*int_ty)))
706 }
711 None => self.table.new_integer_var(), 707 None => self.table.new_integer_var(),
712 }, 708 },
713 Literal::Float(_v, ty) => match ty { 709 Literal::Float(_v, ty) => match ty {
714 Some(float_ty) => Ty::simple(TypeCtor::Float((*float_ty).into())), 710 Some(float_ty) => {
711 Ty::Scalar(Scalar::Float(primitive::float_ty_from_builtin(*float_ty)))
712 }
715 None => self.table.new_float_var(), 713 None => self.table.new_float_var(),
716 }, 714 },
717 }, 715 },
@@ -767,7 +765,7 @@ impl<'a> InferenceContext<'a> {
767 // `!`). 765 // `!`).
768 if self.diverges.is_always() { 766 if self.diverges.is_always() {
769 // we don't even make an attempt at coercion 767 // we don't even make an attempt at coercion
770 self.table.new_maybe_never_type_var() 768 self.table.new_maybe_never_var()
771 } else { 769 } else {
772 self.coerce(&Ty::unit(), expected.coercion_target()); 770 self.coerce(&Ty::unit(), expected.coercion_target());
773 Ty::unit() 771 Ty::unit()
@@ -824,7 +822,7 @@ impl<'a> InferenceContext<'a> {
824 // Apply autoref so the below unification works correctly 822 // Apply autoref so the below unification works correctly
825 // FIXME: return correct autorefs from lookup_method 823 // FIXME: return correct autorefs from lookup_method
826 let actual_receiver_ty = match expected_receiver_ty.as_reference() { 824 let actual_receiver_ty = match expected_receiver_ty.as_reference() {
827 Some((_, mutability)) => Ty::apply_one(TypeCtor::Ref(mutability), derefed_receiver_ty), 825 Some((_, mutability)) => Ty::Ref(mutability, Substs::single(derefed_receiver_ty)),
828 _ => derefed_receiver_ty, 826 _ => derefed_receiver_ty,
829 }; 827 };
830 self.unify(&expected_receiver_ty, &actual_receiver_ty); 828 self.unify(&expected_receiver_ty, &actual_receiver_ty);
@@ -901,30 +899,26 @@ impl<'a> InferenceContext<'a> {
901 } 899 }
902 900
903 fn register_obligations_for_call(&mut self, callable_ty: &Ty) { 901 fn register_obligations_for_call(&mut self, callable_ty: &Ty) {
904 if let Ty::Apply(a_ty) = callable_ty { 902 if let &Ty::FnDef(def, ref parameters) = callable_ty {
905 if let TypeCtor::FnDef(def) = a_ty.ctor { 903 let generic_predicates = self.db.generic_predicates(def.into());
906 let generic_predicates = self.db.generic_predicates(def.into()); 904 for predicate in generic_predicates.iter() {
907 for predicate in generic_predicates.iter() { 905 let predicate = predicate.clone().subst(parameters);
908 let predicate = predicate.clone().subst(&a_ty.parameters); 906 if let Some(obligation) = Obligation::from_predicate(predicate) {
909 if let Some(obligation) = Obligation::from_predicate(predicate) { 907 self.obligations.push(obligation);
910 self.obligations.push(obligation);
911 }
912 } 908 }
913 // add obligation for trait implementation, if this is a trait method 909 }
914 match def { 910 // add obligation for trait implementation, if this is a trait method
915 CallableDefId::FunctionId(f) => { 911 match def {
916 if let AssocContainerId::TraitId(trait_) = 912 CallableDefId::FunctionId(f) => {
917 f.lookup(self.db.upcast()).container 913 if let AssocContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container
918 { 914 {
919 // construct a TraitDef 915 // construct a TraitDef
920 let substs = a_ty 916 let substs =
921 .parameters 917 parameters.prefix(generics(self.db.upcast(), trait_.into()).len());
922 .prefix(generics(self.db.upcast(), trait_.into()).len()); 918 self.obligations.push(Obligation::Trait(TraitRef { trait_, substs }));
923 self.obligations.push(Obligation::Trait(TraitRef { trait_, substs }));
924 }
925 } 919 }
926 CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {}
927 } 920 }
921 CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {}
928 } 922 }
929 } 923 }
930 } 924 }
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index d974f805b..eb099311c 100644
--- a/crates/hir_ty/src/infer/pat.rs
+++ b/crates/hir_ty/src/infer/pat.rs
@@ -3,17 +3,17 @@
3use std::iter::repeat; 3use std::iter::repeat;
4use std::sync::Arc; 4use std::sync::Arc;
5 5
6use chalk_ir::Mutability;
6use hir_def::{ 7use hir_def::{
7 expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat}, 8 expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat},
8 path::Path, 9 path::Path,
9 type_ref::Mutability,
10 FieldId, 10 FieldId,
11}; 11};
12use hir_expand::name::Name; 12use hir_expand::name::Name;
13use test_utils::mark; 13use test_utils::mark;
14 14
15use super::{BindingMode, Expectation, InferenceContext}; 15use super::{BindingMode, Expectation, InferenceContext};
16use crate::{utils::variant_data, Substs, Ty, TypeCtor}; 16use crate::{lower::lower_to_chalk_mutability, utils::variant_data, Substs, Ty};
17 17
18impl<'a> InferenceContext<'a> { 18impl<'a> InferenceContext<'a> {
19 fn infer_tuple_struct_pat( 19 fn infer_tuple_struct_pat(
@@ -32,7 +32,7 @@ impl<'a> InferenceContext<'a> {
32 } 32 }
33 self.unify(&ty, expected); 33 self.unify(&ty, expected);
34 34
35 let substs = ty.substs().unwrap_or_else(Substs::empty); 35 let substs = ty.substs().cloned().unwrap_or_else(Substs::empty);
36 36
37 let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); 37 let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default();
38 let (pre, post) = match ellipsis { 38 let (pre, post) = match ellipsis {
@@ -71,7 +71,7 @@ impl<'a> InferenceContext<'a> {
71 71
72 self.unify(&ty, expected); 72 self.unify(&ty, expected);
73 73
74 let substs = ty.substs().unwrap_or_else(Substs::empty); 74 let substs = ty.substs().cloned().unwrap_or_else(Substs::empty);
75 75
76 let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); 76 let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default();
77 for subpat in subpats { 77 for subpat in subpats {
@@ -103,7 +103,7 @@ impl<'a> InferenceContext<'a> {
103 expected = inner; 103 expected = inner;
104 default_bm = match default_bm { 104 default_bm = match default_bm {
105 BindingMode::Move => BindingMode::Ref(mutability), 105 BindingMode::Move => BindingMode::Ref(mutability),
106 BindingMode::Ref(Mutability::Shared) => BindingMode::Ref(Mutability::Shared), 106 BindingMode::Ref(Mutability::Not) => BindingMode::Ref(Mutability::Not),
107 BindingMode::Ref(Mutability::Mut) => BindingMode::Ref(mutability), 107 BindingMode::Ref(Mutability::Mut) => BindingMode::Ref(mutability),
108 } 108 }
109 } 109 }
@@ -138,10 +138,7 @@ impl<'a> InferenceContext<'a> {
138 inner_tys.extend(expectations_iter.by_ref().take(n_uncovered_patterns).cloned()); 138 inner_tys.extend(expectations_iter.by_ref().take(n_uncovered_patterns).cloned());
139 inner_tys.extend(post.iter().zip(expectations_iter).map(infer_pat)); 139 inner_tys.extend(post.iter().zip(expectations_iter).map(infer_pat));
140 140
141 Ty::apply( 141 Ty::Tuple(inner_tys.len(), Substs(inner_tys.into()))
142 TypeCtor::Tuple { cardinality: inner_tys.len() as u16 },
143 Substs(inner_tys.into()),
144 )
145 } 142 }
146 Pat::Or(ref pats) => { 143 Pat::Or(ref pats) => {
147 if let Some((first_pat, rest)) = pats.split_first() { 144 if let Some((first_pat, rest)) = pats.split_first() {
@@ -155,9 +152,10 @@ impl<'a> InferenceContext<'a> {
155 } 152 }
156 } 153 }
157 Pat::Ref { pat, mutability } => { 154 Pat::Ref { pat, mutability } => {
155 let mutability = lower_to_chalk_mutability(*mutability);
158 let expectation = match expected.as_reference() { 156 let expectation = match expected.as_reference() {
159 Some((inner_ty, exp_mut)) => { 157 Some((inner_ty, exp_mut)) => {
160 if *mutability != exp_mut { 158 if mutability != exp_mut {
161 // FIXME: emit type error? 159 // FIXME: emit type error?
162 } 160 }
163 inner_ty 161 inner_ty
@@ -165,7 +163,7 @@ impl<'a> InferenceContext<'a> {
165 _ => &Ty::Unknown, 163 _ => &Ty::Unknown,
166 }; 164 };
167 let subty = self.infer_pat(*pat, expectation, default_bm); 165 let subty = self.infer_pat(*pat, expectation, default_bm);
168 Ty::apply_one(TypeCtor::Ref(*mutability), subty) 166 Ty::Ref(mutability, Substs::single(subty))
169 } 167 }
170 Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat( 168 Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat(
171 p.as_ref(), 169 p.as_ref(),
@@ -198,7 +196,7 @@ impl<'a> InferenceContext<'a> {
198 196
199 let bound_ty = match mode { 197 let bound_ty = match mode {
200 BindingMode::Ref(mutability) => { 198 BindingMode::Ref(mutability) => {
201 Ty::apply_one(TypeCtor::Ref(mutability), inner_ty.clone()) 199 Ty::Ref(mutability, Substs::single(inner_ty.clone()))
202 } 200 }
203 BindingMode::Move => inner_ty.clone(), 201 BindingMode::Move => inner_ty.clone(),
204 }; 202 };
@@ -207,17 +205,17 @@ impl<'a> InferenceContext<'a> {
207 return inner_ty; 205 return inner_ty;
208 } 206 }
209 Pat::Slice { prefix, slice, suffix } => { 207 Pat::Slice { prefix, slice, suffix } => {
210 let (container_ty, elem_ty) = match &expected { 208 let (container_ty, elem_ty): (fn(_) -> _, _) = match &expected {
211 ty_app!(TypeCtor::Array, st) => (TypeCtor::Array, st.as_single().clone()), 209 Ty::Array(st) => (Ty::Array, st.as_single().clone()),
212 ty_app!(TypeCtor::Slice, st) => (TypeCtor::Slice, st.as_single().clone()), 210 Ty::Slice(st) => (Ty::Slice, st.as_single().clone()),
213 _ => (TypeCtor::Slice, Ty::Unknown), 211 _ => (Ty::Slice, Ty::Unknown),
214 }; 212 };
215 213
216 for pat_id in prefix.iter().chain(suffix) { 214 for pat_id in prefix.iter().chain(suffix) {
217 self.infer_pat(*pat_id, &elem_ty, default_bm); 215 self.infer_pat(*pat_id, &elem_ty, default_bm);
218 } 216 }
219 217
220 let pat_ty = Ty::apply_one(container_ty, elem_ty); 218 let pat_ty = container_ty(Substs::single(elem_ty));
221 if let Some(slice_pat_id) = slice { 219 if let Some(slice_pat_id) = slice {
222 self.infer_pat(*slice_pat_id, &pat_ty, default_bm); 220 self.infer_pat(*slice_pat_id, &pat_ty, default_bm);
223 } 221 }
@@ -239,7 +237,7 @@ impl<'a> InferenceContext<'a> {
239 }; 237 };
240 238
241 let inner_ty = self.infer_pat(*inner, inner_expected, default_bm); 239 let inner_ty = self.infer_pat(*inner, inner_expected, default_bm);
242 Ty::apply_one(TypeCtor::Adt(box_adt), inner_ty) 240 Ty::Adt(box_adt, Substs::single(inner_ty))
243 } 241 }
244 None => Ty::Unknown, 242 None => Ty::Unknown,
245 }, 243 },
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs
index 76984242e..99a89a7f3 100644
--- a/crates/hir_ty/src/infer/unify.rs
+++ b/crates/hir_ty/src/infer/unify.rs
@@ -2,14 +2,15 @@
2 2
3use std::borrow::Cow; 3use std::borrow::Cow;
4 4
5use chalk_ir::{FloatTy, IntTy, TyVariableKind};
5use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; 6use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
6 7
7use test_utils::mark; 8use test_utils::mark;
8 9
9use super::{InferenceContext, Obligation}; 10use super::{InferenceContext, Obligation};
10use crate::{ 11use crate::{
11 BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferTy, Substs, Ty, 12 BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferenceVar, Scalar,
12 TyKind, TypeCtor, TypeWalk, 13 Substs, Ty, TypeWalk,
13}; 14};
14 15
15impl<'a> InferenceContext<'a> { 16impl<'a> InferenceContext<'a> {
@@ -26,7 +27,7 @@ where
26 'a: 'b, 27 'a: 'b,
27{ 28{
28 ctx: &'b mut InferenceContext<'a>, 29 ctx: &'b mut InferenceContext<'a>,
29 free_vars: Vec<InferTy>, 30 free_vars: Vec<(InferenceVar, TyVariableKind)>,
30 /// A stack of type variables that is used to detect recursive types (which 31 /// A stack of type variables that is used to detect recursive types (which
31 /// are an error, but we need to protect against them to avoid stack 32 /// are an error, but we need to protect against them to avoid stack
32 /// overflows). 33 /// overflows).
@@ -36,17 +37,14 @@ where
36#[derive(Debug)] 37#[derive(Debug)]
37pub(super) struct Canonicalized<T> { 38pub(super) struct Canonicalized<T> {
38 pub(super) value: Canonical<T>, 39 pub(super) value: Canonical<T>,
39 free_vars: Vec<InferTy>, 40 free_vars: Vec<(InferenceVar, TyVariableKind)>,
40} 41}
41 42
42impl<'a, 'b> Canonicalizer<'a, 'b> 43impl<'a, 'b> Canonicalizer<'a, 'b> {
43where 44 fn add(&mut self, free_var: InferenceVar, kind: TyVariableKind) -> usize {
44 'a: 'b, 45 self.free_vars.iter().position(|&(v, _)| v == free_var).unwrap_or_else(|| {
45{
46 fn add(&mut self, free_var: InferTy) -> usize {
47 self.free_vars.iter().position(|&v| v == free_var).unwrap_or_else(|| {
48 let next_index = self.free_vars.len(); 46 let next_index = self.free_vars.len();
49 self.free_vars.push(free_var); 47 self.free_vars.push((free_var, kind));
50 next_index 48 next_index
51 }) 49 })
52 } 50 }
@@ -54,11 +52,11 @@ where
54 fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: DebruijnIndex) -> T { 52 fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: DebruijnIndex) -> T {
55 t.fold_binders( 53 t.fold_binders(
56 &mut |ty, binders| match ty { 54 &mut |ty, binders| match ty {
57 Ty::Infer(tv) => { 55 Ty::InferenceVar(var, kind) => {
58 let inner = tv.to_inner(); 56 let inner = var.to_inner();
59 if self.var_stack.contains(&inner) { 57 if self.var_stack.contains(&inner) {
60 // recursive type 58 // recursive type
61 return tv.fallback_value(); 59 return self.ctx.table.type_variable_table.fallback_value(var, kind);
62 } 60 }
63 if let Some(known_ty) = 61 if let Some(known_ty) =
64 self.ctx.table.var_unification_table.inlined_probe_value(inner).known() 62 self.ctx.table.var_unification_table.inlined_probe_value(inner).known()
@@ -69,14 +67,8 @@ where
69 result 67 result
70 } else { 68 } else {
71 let root = self.ctx.table.var_unification_table.find(inner); 69 let root = self.ctx.table.var_unification_table.find(inner);
72 let free_var = match tv { 70 let position = self.add(InferenceVar::from_inner(root), kind);
73 InferTy::TypeVar(_) => InferTy::TypeVar(root), 71 Ty::BoundVar(BoundVar::new(binders, position))
74 InferTy::IntVar(_) => InferTy::IntVar(root),
75 InferTy::FloatVar(_) => InferTy::FloatVar(root),
76 InferTy::MaybeNeverTypeVar(_) => InferTy::MaybeNeverTypeVar(root),
77 };
78 let position = self.add(free_var);
79 Ty::Bound(BoundVar::new(binders, position))
80 } 72 }
81 } 73 }
82 _ => ty, 74 _ => ty,
@@ -86,19 +78,7 @@ where
86 } 78 }
87 79
88 fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { 80 fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> {
89 let kinds = self 81 let kinds = self.free_vars.iter().map(|&(_, k)| k).collect();
90 .free_vars
91 .iter()
92 .map(|v| match v {
93 // mapping MaybeNeverTypeVar to the same kind as general ones
94 // should be fine, because as opposed to int or float type vars,
95 // they don't restrict what kind of type can go into them, they
96 // just affect fallback.
97 InferTy::TypeVar(_) | InferTy::MaybeNeverTypeVar(_) => TyKind::General,
98 InferTy::IntVar(_) => TyKind::Integer,
99 InferTy::FloatVar(_) => TyKind::Float,
100 })
101 .collect();
102 Canonicalized { value: Canonical { value: result, kinds }, free_vars: self.free_vars } 82 Canonicalized { value: Canonical { value: result, kinds }, free_vars: self.free_vars }
103 } 83 }
104 84
@@ -130,9 +110,10 @@ impl<T> Canonicalized<T> {
130 pub(super) fn decanonicalize_ty(&self, mut ty: Ty) -> Ty { 110 pub(super) fn decanonicalize_ty(&self, mut ty: Ty) -> Ty {
131 ty.walk_mut_binders( 111 ty.walk_mut_binders(
132 &mut |ty, binders| { 112 &mut |ty, binders| {
133 if let &mut Ty::Bound(bound) = ty { 113 if let &mut Ty::BoundVar(bound) = ty {
134 if bound.debruijn >= binders { 114 if bound.debruijn >= binders {
135 *ty = Ty::Infer(self.free_vars[bound.index]); 115 let (v, k) = self.free_vars[bound.index];
116 *ty = Ty::InferenceVar(v, k);
136 } 117 }
137 } 118 }
138 }, 119 },
@@ -152,18 +133,18 @@ impl<T> Canonicalized<T> {
152 .kinds 133 .kinds
153 .iter() 134 .iter()
154 .map(|k| match k { 135 .map(|k| match k {
155 TyKind::General => ctx.table.new_type_var(), 136 TyVariableKind::General => ctx.table.new_type_var(),
156 TyKind::Integer => ctx.table.new_integer_var(), 137 TyVariableKind::Integer => ctx.table.new_integer_var(),
157 TyKind::Float => ctx.table.new_float_var(), 138 TyVariableKind::Float => ctx.table.new_float_var(),
158 }) 139 })
159 .collect(), 140 .collect(),
160 ); 141 );
161 for (i, ty) in solution.value.into_iter().enumerate() { 142 for (i, ty) in solution.value.into_iter().enumerate() {
162 let var = self.free_vars[i]; 143 let (v, k) = self.free_vars[i];
163 // eagerly replace projections in the type; we may be getting types 144 // eagerly replace projections in the type; we may be getting types
164 // e.g. from where clauses where this hasn't happened yet 145 // e.g. from where clauses where this hasn't happened yet
165 let ty = ctx.normalize_associated_types_in(ty.clone().subst_bound_vars(&new_vars)); 146 let ty = ctx.normalize_associated_types_in(ty.clone().subst_bound_vars(&new_vars));
166 ctx.table.unify(&Ty::Infer(var), &ty); 147 ctx.table.unify(&Ty::InferenceVar(v, k), &ty);
167 } 148 }
168 } 149 }
169} 150}
@@ -187,7 +168,7 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substs> {
187 // (kind of hacky) 168 // (kind of hacky)
188 for (i, var) in vars.iter().enumerate() { 169 for (i, var) in vars.iter().enumerate() {
189 if &*table.resolve_ty_shallow(var) == var { 170 if &*table.resolve_ty_shallow(var) == var {
190 table.unify(var, &Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, i))); 171 table.unify(var, &Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i)));
191 } 172 }
192 } 173 }
193 Some( 174 Some(
@@ -198,31 +179,73 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substs> {
198} 179}
199 180
200#[derive(Clone, Debug)] 181#[derive(Clone, Debug)]
182pub(super) struct TypeVariableTable {
183 inner: Vec<TypeVariableData>,
184}
185
186impl TypeVariableTable {
187 fn push(&mut self, data: TypeVariableData) {
188 self.inner.push(data);
189 }
190
191 pub(super) fn set_diverging(&mut self, iv: InferenceVar, diverging: bool) {
192 self.inner[iv.to_inner().0 as usize].diverging = diverging;
193 }
194
195 fn is_diverging(&mut self, iv: InferenceVar) -> bool {
196 self.inner[iv.to_inner().0 as usize].diverging
197 }
198
199 fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty {
200 match kind {
201 _ if self.inner[iv.to_inner().0 as usize].diverging => Ty::Never,
202 TyVariableKind::General => Ty::Unknown,
203 TyVariableKind::Integer => Ty::Scalar(Scalar::Int(IntTy::I32)),
204 TyVariableKind::Float => Ty::Scalar(Scalar::Float(FloatTy::F64)),
205 }
206 }
207}
208
209#[derive(Copy, Clone, Debug)]
210pub(crate) struct TypeVariableData {
211 diverging: bool,
212}
213
214#[derive(Clone, Debug)]
201pub(crate) struct InferenceTable { 215pub(crate) struct InferenceTable {
202 pub(super) var_unification_table: InPlaceUnificationTable<TypeVarId>, 216 pub(super) var_unification_table: InPlaceUnificationTable<TypeVarId>,
217 pub(super) type_variable_table: TypeVariableTable,
203} 218}
204 219
205impl InferenceTable { 220impl InferenceTable {
206 pub(crate) fn new() -> Self { 221 pub(crate) fn new() -> Self {
207 InferenceTable { var_unification_table: InPlaceUnificationTable::new() } 222 InferenceTable {
223 var_unification_table: InPlaceUnificationTable::new(),
224 type_variable_table: TypeVariableTable { inner: Vec::new() },
225 }
226 }
227
228 fn new_var(&mut self, kind: TyVariableKind, diverging: bool) -> Ty {
229 self.type_variable_table.push(TypeVariableData { diverging });
230 let key = self.var_unification_table.new_key(TypeVarValue::Unknown);
231 assert_eq!(key.0 as usize, self.type_variable_table.inner.len() - 1);
232 Ty::InferenceVar(InferenceVar::from_inner(key), kind)
208 } 233 }
209 234
210 pub(crate) fn new_type_var(&mut self) -> Ty { 235 pub(crate) fn new_type_var(&mut self) -> Ty {
211 Ty::Infer(InferTy::TypeVar(self.var_unification_table.new_key(TypeVarValue::Unknown))) 236 self.new_var(TyVariableKind::General, false)
212 } 237 }
213 238
214 pub(crate) fn new_integer_var(&mut self) -> Ty { 239 pub(crate) fn new_integer_var(&mut self) -> Ty {
215 Ty::Infer(InferTy::IntVar(self.var_unification_table.new_key(TypeVarValue::Unknown))) 240 self.new_var(TyVariableKind::Integer, false)
216 } 241 }
217 242
218 pub(crate) fn new_float_var(&mut self) -> Ty { 243 pub(crate) fn new_float_var(&mut self) -> Ty {
219 Ty::Infer(InferTy::FloatVar(self.var_unification_table.new_key(TypeVarValue::Unknown))) 244 self.new_var(TyVariableKind::Float, false)
220 } 245 }
221 246
222 pub(crate) fn new_maybe_never_type_var(&mut self) -> Ty { 247 pub(crate) fn new_maybe_never_var(&mut self) -> Ty {
223 Ty::Infer(InferTy::MaybeNeverTypeVar( 248 self.new_var(TyVariableKind::General, true)
224 self.var_unification_table.new_key(TypeVarValue::Unknown),
225 ))
226 } 249 }
227 250
228 pub(crate) fn resolve_ty_completely(&mut self, ty: Ty) -> Ty { 251 pub(crate) fn resolve_ty_completely(&mut self, ty: Ty) -> Ty {
@@ -257,12 +280,14 @@ impl InferenceTable {
257 // try to resolve type vars first 280 // try to resolve type vars first
258 let ty1 = self.resolve_ty_shallow(ty1); 281 let ty1 = self.resolve_ty_shallow(ty1);
259 let ty2 = self.resolve_ty_shallow(ty2); 282 let ty2 = self.resolve_ty_shallow(ty2);
260 match (&*ty1, &*ty2) { 283 if ty1.equals_ctor(&ty2) {
261 (Ty::Apply(a_ty1), Ty::Apply(a_ty2)) if a_ty1.ctor == a_ty2.ctor => { 284 match (ty1.substs(), ty2.substs()) {
262 self.unify_substs(&a_ty1.parameters, &a_ty2.parameters, depth + 1) 285 (Some(st1), Some(st2)) => self.unify_substs(st1, st2, depth + 1),
286 (None, None) => true,
287 _ => false,
263 } 288 }
264 289 } else {
265 _ => self.unify_inner_trivial(&ty1, &ty2, depth), 290 self.unify_inner_trivial(&ty1, &ty2, depth)
266 } 291 }
267 } 292 }
268 293
@@ -281,31 +306,46 @@ impl InferenceTable {
281 true 306 true
282 } 307 }
283 308
284 (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) 309 (
285 | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2))) 310 Ty::InferenceVar(tv1, TyVariableKind::General),
286 | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2))) 311 Ty::InferenceVar(tv2, TyVariableKind::General),
312 )
287 | ( 313 | (
288 Ty::Infer(InferTy::MaybeNeverTypeVar(tv1)), 314 Ty::InferenceVar(tv1, TyVariableKind::Integer),
289 Ty::Infer(InferTy::MaybeNeverTypeVar(tv2)), 315 Ty::InferenceVar(tv2, TyVariableKind::Integer),
290 ) => { 316 )
317 | (
318 Ty::InferenceVar(tv1, TyVariableKind::Float),
319 Ty::InferenceVar(tv2, TyVariableKind::Float),
320 ) if self.type_variable_table.is_diverging(*tv1)
321 == self.type_variable_table.is_diverging(*tv2) =>
322 {
291 // both type vars are unknown since we tried to resolve them 323 // both type vars are unknown since we tried to resolve them
292 self.var_unification_table.union(*tv1, *tv2); 324 self.var_unification_table.union(tv1.to_inner(), tv2.to_inner());
293 true 325 true
294 } 326 }
295 327
296 // The order of MaybeNeverTypeVar matters here. 328 // The order of MaybeNeverTypeVar matters here.
297 // Unifying MaybeNeverTypeVar and TypeVar will let the latter become MaybeNeverTypeVar. 329 // Unifying MaybeNeverTypeVar and TypeVar will let the latter become MaybeNeverTypeVar.
298 // Unifying MaybeNeverTypeVar and other concrete type will let the former become it. 330 // Unifying MaybeNeverTypeVar and other concrete type will let the former become it.
299 (Ty::Infer(InferTy::TypeVar(tv)), other) 331 (Ty::InferenceVar(tv, TyVariableKind::General), other)
300 | (other, Ty::Infer(InferTy::TypeVar(tv))) 332 | (other, Ty::InferenceVar(tv, TyVariableKind::General))
301 | (Ty::Infer(InferTy::MaybeNeverTypeVar(tv)), other) 333 | (Ty::InferenceVar(tv, TyVariableKind::Integer), other @ Ty::Scalar(Scalar::Int(_)))
302 | (other, Ty::Infer(InferTy::MaybeNeverTypeVar(tv))) 334 | (other @ Ty::Scalar(Scalar::Int(_)), Ty::InferenceVar(tv, TyVariableKind::Integer))
303 | (Ty::Infer(InferTy::IntVar(tv)), other @ ty_app!(TypeCtor::Int(_))) 335 | (
304 | (other @ ty_app!(TypeCtor::Int(_)), Ty::Infer(InferTy::IntVar(tv))) 336 Ty::InferenceVar(tv, TyVariableKind::Integer),
305 | (Ty::Infer(InferTy::FloatVar(tv)), other @ ty_app!(TypeCtor::Float(_))) 337 other @ Ty::Scalar(Scalar::Uint(_)),
306 | (other @ ty_app!(TypeCtor::Float(_)), Ty::Infer(InferTy::FloatVar(tv))) => { 338 )
339 | (
340 other @ Ty::Scalar(Scalar::Uint(_)),
341 Ty::InferenceVar(tv, TyVariableKind::Integer),
342 )
343 | (Ty::InferenceVar(tv, TyVariableKind::Float), other @ Ty::Scalar(Scalar::Float(_)))
344 | (other @ Ty::Scalar(Scalar::Float(_)), Ty::InferenceVar(tv, TyVariableKind::Float)) =>
345 {
307 // the type var is unknown since we tried to resolve it 346 // the type var is unknown since we tried to resolve it
308 self.var_unification_table.union_value(*tv, TypeVarValue::Known(other.clone())); 347 self.var_unification_table
348 .union_value(tv.to_inner(), TypeVarValue::Known(other.clone()));
309 true 349 true
310 } 350 }
311 351
@@ -350,7 +390,7 @@ impl InferenceTable {
350 mark::hit!(type_var_resolves_to_int_var); 390 mark::hit!(type_var_resolves_to_int_var);
351 } 391 }
352 match &*ty { 392 match &*ty {
353 Ty::Infer(tv) => { 393 Ty::InferenceVar(tv, _) => {
354 let inner = tv.to_inner(); 394 let inner = tv.to_inner();
355 match self.var_unification_table.inlined_probe_value(inner).known() { 395 match self.var_unification_table.inlined_probe_value(inner).known() {
356 Some(known_ty) => { 396 Some(known_ty) => {
@@ -373,12 +413,12 @@ impl InferenceTable {
373 /// known type. 413 /// known type.
374 fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { 414 fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
375 ty.fold(&mut |ty| match ty { 415 ty.fold(&mut |ty| match ty {
376 Ty::Infer(tv) => { 416 Ty::InferenceVar(tv, kind) => {
377 let inner = tv.to_inner(); 417 let inner = tv.to_inner();
378 if tv_stack.contains(&inner) { 418 if tv_stack.contains(&inner) {
379 mark::hit!(type_var_cycles_resolve_as_possible); 419 mark::hit!(type_var_cycles_resolve_as_possible);
380 // recursive type 420 // recursive type
381 return tv.fallback_value(); 421 return self.type_variable_table.fallback_value(tv, kind);
382 } 422 }
383 if let Some(known_ty) = 423 if let Some(known_ty) =
384 self.var_unification_table.inlined_probe_value(inner).known() 424 self.var_unification_table.inlined_probe_value(inner).known()
@@ -400,12 +440,12 @@ impl InferenceTable {
400 /// replaced by Ty::Unknown. 440 /// replaced by Ty::Unknown.
401 fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { 441 fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
402 ty.fold(&mut |ty| match ty { 442 ty.fold(&mut |ty| match ty {
403 Ty::Infer(tv) => { 443 Ty::InferenceVar(tv, kind) => {
404 let inner = tv.to_inner(); 444 let inner = tv.to_inner();
405 if tv_stack.contains(&inner) { 445 if tv_stack.contains(&inner) {
406 mark::hit!(type_var_cycles_resolve_completely); 446 mark::hit!(type_var_cycles_resolve_completely);
407 // recursive type 447 // recursive type
408 return tv.fallback_value(); 448 return self.type_variable_table.fallback_value(tv, kind);
409 } 449 }
410 if let Some(known_ty) = 450 if let Some(known_ty) =
411 self.var_unification_table.inlined_probe_value(inner).known() 451 self.var_unification_table.inlined_probe_value(inner).known()
@@ -416,7 +456,7 @@ impl InferenceTable {
416 tv_stack.pop(); 456 tv_stack.pop();
417 result 457 result
418 } else { 458 } else {
419 tv.fallback_value() 459 self.type_variable_table.fallback_value(tv, kind)
420 } 460 }
421 } 461 }
422 _ => ty, 462 _ => ty,
@@ -426,7 +466,7 @@ impl InferenceTable {
426 466
427/// The ID of a type variable. 467/// The ID of a type variable.
428#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] 468#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
429pub struct TypeVarId(pub(super) u32); 469pub(super) struct TypeVarId(pub(super) u32);
430 470
431impl UnifyKey for TypeVarId { 471impl UnifyKey for TypeVarId {
432 type Value = TypeVarValue; 472 type Value = TypeVarValue;
@@ -447,7 +487,7 @@ impl UnifyKey for TypeVarId {
447/// The value of a type variable: either we already know the type, or we don't 487/// The value of a type variable: either we already know the type, or we don't
448/// know it yet. 488/// know it yet.
449#[derive(Clone, PartialEq, Eq, Debug)] 489#[derive(Clone, PartialEq, Eq, Debug)]
450pub enum TypeVarValue { 490pub(super) enum TypeVarValue {
451 Known(Ty), 491 Known(Ty),
452 Unknown, 492 Unknown,
453} 493}
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index 50d248674..c2a20c480 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -25,32 +25,29 @@ mod test_db;
25 25
26use std::{iter, mem, ops::Deref, sync::Arc}; 26use std::{iter, mem, ops::Deref, sync::Arc};
27 27
28use base_db::{salsa, CrateId}; 28use base_db::salsa;
29use hir_def::{ 29use hir_def::{
30 builtin_type::BuiltinType, 30 builtin_type::BuiltinType, expr::ExprId, type_ref::Rawness, AdtId, AssocContainerId,
31 expr::ExprId, 31 DefWithBodyId, FunctionId, GenericDefId, HasModule, LifetimeParamId, Lookup, TraitId,
32 type_ref::{Mutability, Rawness}, 32 TypeAliasId, TypeParamId,
33 AdtId, AssocContainerId, DefWithBodyId, FunctionId, GenericDefId, HasModule, LifetimeParamId,
34 Lookup, TraitId, TypeAliasId, TypeParamId,
35}; 33};
36use itertools::Itertools; 34use itertools::Itertools;
37 35
38use crate::{ 36use crate::{
39 db::HirDatabase, 37 db::HirDatabase,
40 display::HirDisplay, 38 display::HirDisplay,
41 primitive::{FloatTy, IntTy},
42 utils::{generics, make_mut_slice, Generics}, 39 utils::{generics, make_mut_slice, Generics},
43}; 40};
44 41
45pub use autoderef::autoderef; 42pub use autoderef::autoderef;
46pub use infer::{InferTy, InferenceResult}; 43pub use infer::{InferenceResult, InferenceVar};
47pub use lower::{ 44pub use lower::{
48 associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, 45 associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode,
49 TyDefId, TyLoweringContext, ValueTyDefId, 46 TyDefId, TyLoweringContext, ValueTyDefId,
50}; 47};
51pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; 48pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment};
52 49
53pub use chalk_ir::{BoundVar, DebruijnIndex}; 50pub use chalk_ir::{BoundVar, DebruijnIndex, Mutability, Scalar, TyVariableKind};
54 51
55#[derive(Clone, PartialEq, Eq, Debug, Hash)] 52#[derive(Clone, PartialEq, Eq, Debug, Hash)]
56pub enum Lifetime { 53pub enum Lifetime {
@@ -58,211 +55,6 @@ pub enum Lifetime {
58 Static, 55 Static,
59} 56}
60 57
61/// A type constructor or type name: this might be something like the primitive
62/// type `bool`, a struct like `Vec`, or things like function pointers or
63/// tuples.
64#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
65pub enum TypeCtor {
66 /// The primitive boolean type. Written as `bool`.
67 Bool,
68
69 /// The primitive character type; holds a Unicode scalar value
70 /// (a non-surrogate code point). Written as `char`.
71 Char,
72
73 /// A primitive integer type. For example, `i32`.
74 Int(IntTy),
75
76 /// A primitive floating-point type. For example, `f64`.
77 Float(FloatTy),
78
79 /// Structures, enumerations and unions.
80 Adt(AdtId),
81
82 /// The pointee of a string slice. Written as `str`.
83 Str,
84
85 /// The pointee of an array slice. Written as `[T]`.
86 Slice,
87
88 /// An array with the given length. Written as `[T; n]`.
89 Array,
90
91 /// A raw pointer. Written as `*mut T` or `*const T`
92 RawPtr(Mutability),
93
94 /// A reference; a pointer with an associated lifetime. Written as
95 /// `&'a mut T` or `&'a T`.
96 Ref(Mutability),
97
98 /// The anonymous type of a function declaration/definition. Each
99 /// function has a unique type, which is output (for a function
100 /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`.
101 ///
102 /// This includes tuple struct / enum variant constructors as well.
103 ///
104 /// For example the type of `bar` here:
105 ///
106 /// ```
107 /// fn foo() -> i32 { 1 }
108 /// let bar = foo; // bar: fn() -> i32 {foo}
109 /// ```
110 FnDef(CallableDefId),
111
112 /// A pointer to a function. Written as `fn() -> i32`.
113 ///
114 /// For example the type of `bar` here:
115 ///
116 /// ```
117 /// fn foo() -> i32 { 1 }
118 /// let bar: fn() -> i32 = foo;
119 /// ```
120 // FIXME make this a Ty variant like in Chalk
121 FnPtr { num_args: u16, is_varargs: bool },
122
123 /// The never type `!`.
124 Never,
125
126 /// A tuple type. For example, `(i32, bool)`.
127 Tuple { cardinality: u16 },
128
129 /// Represents an associated item like `Iterator::Item`. This is used
130 /// when we have tried to normalize a projection like `T::Item` but
131 /// couldn't find a better representation. In that case, we generate
132 /// an **application type** like `(Iterator::Item)<T>`.
133 AssociatedType(TypeAliasId),
134
135 /// This represents a placeholder for an opaque type in situations where we
136 /// don't know the hidden type (i.e. currently almost always). This is
137 /// analogous to the `AssociatedType` type constructor.
138 /// It is also used as the type of async block, with one type parameter
139 /// representing the Future::Output type.
140 OpaqueType(OpaqueTyId),
141
142 /// Represents a foreign type declared in external blocks.
143 ForeignType(TypeAliasId),
144
145 /// The type of a specific closure.
146 ///
147 /// The closure signature is stored in a `FnPtr` type in the first type
148 /// parameter.
149 Closure { def: DefWithBodyId, expr: ExprId },
150}
151
152impl TypeCtor {
153 pub fn num_ty_params(self, db: &dyn HirDatabase) -> usize {
154 match self {
155 TypeCtor::Bool
156 | TypeCtor::Char
157 | TypeCtor::Int(_)
158 | TypeCtor::Float(_)
159 | TypeCtor::Str
160 | TypeCtor::Never => 0,
161 TypeCtor::Slice
162 | TypeCtor::Array
163 | TypeCtor::RawPtr(_)
164 | TypeCtor::Ref(_)
165 | TypeCtor::Closure { .. } // 1 param representing the signature of the closure
166 => 1,
167 TypeCtor::Adt(adt) => {
168 let generic_params = generics(db.upcast(), adt.into());
169 generic_params.len()
170 }
171 TypeCtor::FnDef(callable) => {
172 let generic_params = generics(db.upcast(), callable.into());
173 generic_params.len()
174 }
175 TypeCtor::AssociatedType(type_alias) => {
176 let generic_params = generics(db.upcast(), type_alias.into());
177 generic_params.len()
178 }
179 TypeCtor::ForeignType(type_alias) => {
180 let generic_params = generics(db.upcast(), type_alias.into());
181 generic_params.len()
182 }
183 TypeCtor::OpaqueType(opaque_ty_id) => {
184 match opaque_ty_id {
185 OpaqueTyId::ReturnTypeImplTrait(func, _) => {
186 let generic_params = generics(db.upcast(), func.into());
187 generic_params.len()
188 }
189 // 1 param representing Future::Output type.
190 OpaqueTyId::AsyncBlockTypeImplTrait(..) => 1,
191 }
192 }
193 TypeCtor::FnPtr { num_args, is_varargs: _ } => num_args as usize + 1,
194 TypeCtor::Tuple { cardinality } => cardinality as usize,
195 }
196 }
197
198 pub fn krate(self, db: &dyn HirDatabase) -> Option<CrateId> {
199 match self {
200 TypeCtor::Bool
201 | TypeCtor::Char
202 | TypeCtor::Int(_)
203 | TypeCtor::Float(_)
204 | TypeCtor::Str
205 | TypeCtor::Never
206 | TypeCtor::Slice
207 | TypeCtor::Array
208 | TypeCtor::RawPtr(_)
209 | TypeCtor::Ref(_)
210 | TypeCtor::FnPtr { .. }
211 | TypeCtor::Tuple { .. } => None,
212 // Closure's krate is irrelevant for coherence I would think?
213 TypeCtor::Closure { .. } => None,
214 TypeCtor::Adt(adt) => Some(adt.module(db.upcast()).krate()),
215 TypeCtor::FnDef(callable) => Some(callable.krate(db)),
216 TypeCtor::AssociatedType(type_alias) => {
217 Some(type_alias.lookup(db.upcast()).module(db.upcast()).krate())
218 }
219 TypeCtor::ForeignType(type_alias) => {
220 Some(type_alias.lookup(db.upcast()).module(db.upcast()).krate())
221 }
222 TypeCtor::OpaqueType(opaque_ty_id) => match opaque_ty_id {
223 OpaqueTyId::ReturnTypeImplTrait(func, _) => {
224 Some(func.lookup(db.upcast()).module(db.upcast()).krate())
225 }
226 OpaqueTyId::AsyncBlockTypeImplTrait(def, _) => {
227 Some(def.module(db.upcast()).krate())
228 }
229 },
230 }
231 }
232
233 pub fn as_generic_def(self) -> Option<GenericDefId> {
234 match self {
235 TypeCtor::Bool
236 | TypeCtor::Char
237 | TypeCtor::Int(_)
238 | TypeCtor::Float(_)
239 | TypeCtor::Str
240 | TypeCtor::Never
241 | TypeCtor::Slice
242 | TypeCtor::Array
243 | TypeCtor::RawPtr(_)
244 | TypeCtor::Ref(_)
245 | TypeCtor::FnPtr { .. }
246 | TypeCtor::Tuple { .. }
247 | TypeCtor::Closure { .. } => None,
248 TypeCtor::Adt(adt) => Some(adt.into()),
249 TypeCtor::FnDef(callable) => Some(callable.into()),
250 TypeCtor::AssociatedType(type_alias) => Some(type_alias.into()),
251 TypeCtor::ForeignType(type_alias) => Some(type_alias.into()),
252 TypeCtor::OpaqueType(_impl_trait_id) => None,
253 }
254 }
255}
256
257/// A nominal type with (maybe 0) type parameters. This might be a primitive
258/// type like `bool`, a struct, tuple, function pointer, reference or
259/// several other things.
260#[derive(Clone, PartialEq, Eq, Debug, Hash)]
261pub struct ApplicationTy {
262 pub ctor: TypeCtor,
263 pub parameters: Substs,
264}
265
266#[derive(Clone, PartialEq, Eq, Debug, Hash)] 58#[derive(Clone, PartialEq, Eq, Debug, Hash)]
267pub struct OpaqueTy { 59pub struct OpaqueTy {
268 pub opaque_ty_id: OpaqueTyId, 60 pub opaque_ty_id: OpaqueTyId,
@@ -305,29 +97,118 @@ impl TypeWalk for ProjectionTy {
305 } 97 }
306} 98}
307 99
308/// A type. 100#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
309/// 101pub struct FnSig {
310/// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents 102 pub variadic: bool,
311/// the same thing (but in a different way). 103}
312/// 104
313/// This should be cheap to clone.
314#[derive(Clone, PartialEq, Eq, Debug, Hash)] 105#[derive(Clone, PartialEq, Eq, Debug, Hash)]
315pub enum Ty { 106pub struct FnPointer {
316 /// A nominal type with (maybe 0) type parameters. This might be a primitive 107 pub num_args: usize,
317 /// type like `bool`, a struct, tuple, function pointer, reference or 108 pub sig: FnSig,
318 /// several other things. 109 pub substs: Substs,
319 Apply(ApplicationTy), 110}
320 111
112#[derive(Clone, PartialEq, Eq, Debug, Hash)]
113pub enum AliasTy {
321 /// A "projection" type corresponds to an (unnormalized) 114 /// A "projection" type corresponds to an (unnormalized)
322 /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the 115 /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the
323 /// trait and all its parameters are fully known. 116 /// trait and all its parameters are fully known.
324 Projection(ProjectionTy), 117 Projection(ProjectionTy),
325
326 /// An opaque type (`impl Trait`). 118 /// An opaque type (`impl Trait`).
327 /// 119 ///
328 /// This is currently only used for return type impl trait; each instance of 120 /// This is currently only used for return type impl trait; each instance of
329 /// `impl Trait` in a return type gets its own ID. 121 /// `impl Trait` in a return type gets its own ID.
330 Opaque(OpaqueTy), 122 Opaque(OpaqueTy),
123}
124
125/// A type.
126///
127/// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents
128/// the same thing (but in a different way).
129///
130/// This should be cheap to clone.
131#[derive(Clone, PartialEq, Eq, Debug, Hash)]
132pub enum Ty {
133 /// Structures, enumerations and unions.
134 Adt(AdtId, Substs),
135
136 /// Represents an associated item like `Iterator::Item`. This is used
137 /// when we have tried to normalize a projection like `T::Item` but
138 /// couldn't find a better representation. In that case, we generate
139 /// an **application type** like `(Iterator::Item)<T>`.
140 AssociatedType(TypeAliasId, Substs),
141
142 /// a scalar type like `bool` or `u32`
143 Scalar(Scalar),
144
145 /// A tuple type. For example, `(i32, bool)`.
146 Tuple(usize, Substs),
147
148 /// An array with the given length. Written as `[T; n]`.
149 Array(Substs),
150
151 /// The pointee of an array slice. Written as `[T]`.
152 Slice(Substs),
153
154 /// A raw pointer. Written as `*mut T` or `*const T`
155 Raw(Mutability, Substs),
156
157 /// A reference; a pointer with an associated lifetime. Written as
158 /// `&'a mut T` or `&'a T`.
159 Ref(Mutability, Substs),
160
161 /// This represents a placeholder for an opaque type in situations where we
162 /// don't know the hidden type (i.e. currently almost always). This is
163 /// analogous to the `AssociatedType` type constructor.
164 /// It is also used as the type of async block, with one type parameter
165 /// representing the Future::Output type.
166 OpaqueType(OpaqueTyId, Substs),
167
168 /// The anonymous type of a function declaration/definition. Each
169 /// function has a unique type, which is output (for a function
170 /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`.
171 ///
172 /// This includes tuple struct / enum variant constructors as well.
173 ///
174 /// For example the type of `bar` here:
175 ///
176 /// ```
177 /// fn foo() -> i32 { 1 }
178 /// let bar = foo; // bar: fn() -> i32 {foo}
179 /// ```
180 FnDef(CallableDefId, Substs),
181
182 /// The pointee of a string slice. Written as `str`.
183 Str,
184
185 /// The never type `!`.
186 Never,
187
188 /// The type of a specific closure.
189 ///
190 /// The closure signature is stored in a `FnPtr` type in the first type
191 /// parameter.
192 Closure(DefWithBodyId, ExprId, Substs),
193
194 /// Represents a foreign type declared in external blocks.
195 ForeignType(TypeAliasId),
196
197 /// A pointer to a function. Written as `fn() -> i32`.
198 ///
199 /// For example the type of `bar` here:
200 ///
201 /// ```
202 /// fn foo() -> i32 { 1 }
203 /// let bar: fn() -> i32 = foo;
204 /// ```
205 Function(FnPointer),
206
207 /// An "alias" type represents some form of type alias, such as:
208 /// - An associated type projection like `<T as Iterator>::Item`
209 /// - `impl Trait` types
210 /// - Named type aliases like `type Foo<X> = Vec<X>`
211 Alias(AliasTy),
331 212
332 /// A placeholder for a type parameter; for example, `T` in `fn f<T>(x: T) 213 /// A placeholder for a type parameter; for example, `T` in `fn f<T>(x: T)
333 /// {}` when we're type-checking the body of that function. In this 214 /// {}` when we're type-checking the body of that function. In this
@@ -340,10 +221,10 @@ pub enum Ty {
340 /// parameters get turned into variables; during trait resolution, inference 221 /// parameters get turned into variables; during trait resolution, inference
341 /// variables get turned into bound variables and back; and in `Dyn` the 222 /// variables get turned into bound variables and back; and in `Dyn` the
342 /// `Self` type is represented with a bound variable as well. 223 /// `Self` type is represented with a bound variable as well.
343 Bound(BoundVar), 224 BoundVar(BoundVar),
344 225
345 /// A type variable used during type checking. 226 /// A type variable used during type checking.
346 Infer(InferTy), 227 InferenceVar(InferenceVar, TyVariableKind),
347 228
348 /// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust). 229 /// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust).
349 /// 230 ///
@@ -424,7 +305,7 @@ impl Substs {
424 generic_params 305 generic_params
425 .iter() 306 .iter()
426 .enumerate() 307 .enumerate()
427 .map(|(idx, _)| Ty::Bound(BoundVar::new(debruijn, idx))) 308 .map(|(idx, _)| Ty::BoundVar(BoundVar::new(debruijn, idx)))
428 .collect(), 309 .collect(),
429 ) 310 )
430 } 311 }
@@ -440,10 +321,6 @@ impl Substs {
440 Substs::builder(generic_params.len()) 321 Substs::builder(generic_params.len())
441 } 322 }
442 323
443 pub fn build_for_type_ctor(db: &dyn HirDatabase, type_ctor: TypeCtor) -> SubstsBuilder {
444 Substs::builder(type_ctor.num_ty_params(db))
445 }
446
447 fn builder(param_count: usize) -> SubstsBuilder { 324 fn builder(param_count: usize) -> SubstsBuilder {
448 SubstsBuilder { vec: Vec::with_capacity(param_count), param_count } 325 SubstsBuilder { vec: Vec::with_capacity(param_count), param_count }
449 } 326 }
@@ -476,7 +353,7 @@ impl SubstsBuilder {
476 } 353 }
477 354
478 pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self { 355 pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self {
479 self.fill((starting_from..).map(|idx| Ty::Bound(BoundVar::new(debruijn, idx)))) 356 self.fill((starting_from..).map(|idx| Ty::BoundVar(BoundVar::new(debruijn, idx))))
480 } 357 }
481 358
482 pub fn fill_with_unknown(self) -> Self { 359 pub fn fill_with_unknown(self) -> Self {
@@ -656,41 +533,41 @@ impl TypeWalk for GenericPredicate {
656#[derive(Debug, Clone, PartialEq, Eq, Hash)] 533#[derive(Debug, Clone, PartialEq, Eq, Hash)]
657pub struct Canonical<T> { 534pub struct Canonical<T> {
658 pub value: T, 535 pub value: T,
659 pub kinds: Arc<[TyKind]>, 536 pub kinds: Arc<[TyVariableKind]>,
660} 537}
661 538
662impl<T> Canonical<T> { 539impl<T> Canonical<T> {
663 pub fn new(value: T, kinds: impl IntoIterator<Item = TyKind>) -> Self { 540 pub fn new(value: T, kinds: impl IntoIterator<Item = TyVariableKind>) -> Self {
664 Self { value, kinds: kinds.into_iter().collect() } 541 Self { value, kinds: kinds.into_iter().collect() }
665 } 542 }
666} 543}
667 544
668#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
669pub enum TyKind {
670 General,
671 Integer,
672 Float,
673}
674
675/// A function signature as seen by type inference: Several parameter types and 545/// A function signature as seen by type inference: Several parameter types and
676/// one return type. 546/// one return type.
677#[derive(Clone, PartialEq, Eq, Debug)] 547#[derive(Clone, PartialEq, Eq, Debug)]
678pub struct FnSig { 548pub struct CallableSig {
679 params_and_return: Arc<[Ty]>, 549 params_and_return: Arc<[Ty]>,
680 is_varargs: bool, 550 is_varargs: bool,
681} 551}
682 552
683/// A polymorphic function signature. 553/// A polymorphic function signature.
684pub type PolyFnSig = Binders<FnSig>; 554pub type PolyFnSig = Binders<CallableSig>;
685 555
686impl FnSig { 556impl CallableSig {
687 pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty, is_varargs: bool) -> FnSig { 557 pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty, is_varargs: bool) -> CallableSig {
688 params.push(ret); 558 params.push(ret);
689 FnSig { params_and_return: params.into(), is_varargs } 559 CallableSig { params_and_return: params.into(), is_varargs }
690 } 560 }
691 561
692 pub fn from_fn_ptr_substs(substs: &Substs, is_varargs: bool) -> FnSig { 562 pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig {
693 FnSig { params_and_return: Arc::clone(&substs.0), is_varargs } 563 CallableSig {
564 params_and_return: Arc::clone(&fn_ptr.substs.0),
565 is_varargs: fn_ptr.sig.variadic,
566 }
567 }
568
569 pub fn from_substs(substs: &Substs) -> CallableSig {
570 CallableSig { params_and_return: Arc::clone(&substs.0), is_varargs: false }
694 } 571 }
695 572
696 pub fn params(&self) -> &[Ty] { 573 pub fn params(&self) -> &[Ty] {
@@ -702,7 +579,7 @@ impl FnSig {
702 } 579 }
703} 580}
704 581
705impl TypeWalk for FnSig { 582impl TypeWalk for CallableSig {
706 fn walk(&self, f: &mut impl FnMut(&Ty)) { 583 fn walk(&self, f: &mut impl FnMut(&Ty)) {
707 for t in self.params_and_return.iter() { 584 for t in self.params_and_return.iter() {
708 t.walk(f); 585 t.walk(f);
@@ -721,49 +598,42 @@ impl TypeWalk for FnSig {
721} 598}
722 599
723impl Ty { 600impl Ty {
724 pub fn simple(ctor: TypeCtor) -> Ty {
725 Ty::Apply(ApplicationTy { ctor, parameters: Substs::empty() })
726 }
727 pub fn apply_one(ctor: TypeCtor, param: Ty) -> Ty {
728 Ty::Apply(ApplicationTy { ctor, parameters: Substs::single(param) })
729 }
730 pub fn apply(ctor: TypeCtor, parameters: Substs) -> Ty {
731 Ty::Apply(ApplicationTy { ctor, parameters })
732 }
733 pub fn unit() -> Self { 601 pub fn unit() -> Self {
734 Ty::apply(TypeCtor::Tuple { cardinality: 0 }, Substs::empty()) 602 Ty::Tuple(0, Substs::empty())
735 } 603 }
736 pub fn fn_ptr(sig: FnSig) -> Self { 604
737 Ty::apply( 605 pub fn fn_ptr(sig: CallableSig) -> Self {
738 TypeCtor::FnPtr { num_args: sig.params().len() as u16, is_varargs: sig.is_varargs }, 606 Ty::Function(FnPointer {
739 Substs(sig.params_and_return), 607 num_args: sig.params().len(),
740 ) 608 sig: FnSig { variadic: sig.is_varargs },
609 substs: Substs(sig.params_and_return),
610 })
741 } 611 }
612
742 pub fn builtin(builtin: BuiltinType) -> Self { 613 pub fn builtin(builtin: BuiltinType) -> Self {
743 Ty::simple(match builtin { 614 match builtin {
744 BuiltinType::Char => TypeCtor::Char, 615 BuiltinType::Char => Ty::Scalar(Scalar::Char),
745 BuiltinType::Bool => TypeCtor::Bool, 616 BuiltinType::Bool => Ty::Scalar(Scalar::Bool),
746 BuiltinType::Str => TypeCtor::Str, 617 BuiltinType::Str => Ty::Str,
747 BuiltinType::Int(t) => TypeCtor::Int(IntTy::from(t).into()), 618 BuiltinType::Int(t) => Ty::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))),
748 BuiltinType::Float(t) => TypeCtor::Float(FloatTy::from(t).into()), 619 BuiltinType::Uint(t) => Ty::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))),
749 }) 620 BuiltinType::Float(t) => Ty::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))),
621 }
750 } 622 }
751 623
752 pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { 624 pub fn as_reference(&self) -> Option<(&Ty, Mutability)> {
753 match self { 625 match self {
754 Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(mutability), parameters }) => { 626 Ty::Ref(mutability, parameters) => Some((parameters.as_single(), *mutability)),
755 Some((parameters.as_single(), *mutability))
756 }
757 _ => None, 627 _ => None,
758 } 628 }
759 } 629 }
760 630
761 pub fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> { 631 pub fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> {
762 match self { 632 match self {
763 Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(mutability), parameters }) => { 633 Ty::Ref(mutability, parameters) => {
764 Some((parameters.as_single(), Rawness::Ref, *mutability)) 634 Some((parameters.as_single(), Rawness::Ref, *mutability))
765 } 635 }
766 Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(mutability), parameters }) => { 636 Ty::Raw(mutability, parameters) => {
767 Some((parameters.as_single(), Rawness::RawPtr, *mutability)) 637 Some((parameters.as_single(), Rawness::RawPtr, *mutability))
768 } 638 }
769 _ => None, 639 _ => None,
@@ -773,7 +643,7 @@ impl Ty {
773 pub fn strip_references(&self) -> &Ty { 643 pub fn strip_references(&self) -> &Ty {
774 let mut t: &Ty = self; 644 let mut t: &Ty = self;
775 645
776 while let Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(_mutability), parameters }) = t { 646 while let Ty::Ref(_mutability, parameters) = t {
777 t = parameters.as_single(); 647 t = parameters.as_single();
778 } 648 }
779 649
@@ -782,30 +652,60 @@ impl Ty {
782 652
783 pub fn as_adt(&self) -> Option<(AdtId, &Substs)> { 653 pub fn as_adt(&self) -> Option<(AdtId, &Substs)> {
784 match self { 654 match self {
785 Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(adt_def), parameters }) => { 655 Ty::Adt(adt_def, parameters) => Some((*adt_def, parameters)),
786 Some((*adt_def, parameters))
787 }
788 _ => None, 656 _ => None,
789 } 657 }
790 } 658 }
791 659
792 pub fn as_tuple(&self) -> Option<&Substs> { 660 pub fn as_tuple(&self) -> Option<&Substs> {
793 match self { 661 match self {
794 Ty::Apply(ApplicationTy { ctor: TypeCtor::Tuple { .. }, parameters }) => { 662 Ty::Tuple(_, substs) => Some(substs),
795 Some(parameters) 663 _ => None,
796 } 664 }
665 }
666
667 pub fn as_generic_def(&self) -> Option<GenericDefId> {
668 match *self {
669 Ty::Adt(adt, ..) => Some(adt.into()),
670 Ty::FnDef(callable, ..) => Some(callable.into()),
671 Ty::AssociatedType(type_alias, ..) => Some(type_alias.into()),
672 Ty::ForeignType(type_alias, ..) => Some(type_alias.into()),
797 _ => None, 673 _ => None,
798 } 674 }
799 } 675 }
800 676
801 pub fn is_never(&self) -> bool { 677 pub fn is_never(&self) -> bool {
802 matches!(self, Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. })) 678 matches!(self, Ty::Never)
803 } 679 }
804 680
805 pub fn is_unknown(&self) -> bool { 681 pub fn is_unknown(&self) -> bool {
806 matches!(self, Ty::Unknown) 682 matches!(self, Ty::Unknown)
807 } 683 }
808 684
685 pub fn equals_ctor(&self, other: &Ty) -> bool {
686 match (self, other) {
687 (Ty::Adt(adt, ..), Ty::Adt(adt2, ..)) => adt == adt2,
688 (Ty::Slice(_), Ty::Slice(_)) | (Ty::Array(_), Ty::Array(_)) => true,
689 (Ty::FnDef(def_id, ..), Ty::FnDef(def_id2, ..)) => def_id == def_id2,
690 (Ty::OpaqueType(ty_id, ..), Ty::OpaqueType(ty_id2, ..)) => ty_id == ty_id2,
691 (Ty::AssociatedType(ty_id, ..), Ty::AssociatedType(ty_id2, ..))
692 | (Ty::ForeignType(ty_id, ..), Ty::ForeignType(ty_id2, ..)) => ty_id == ty_id2,
693 (Ty::Closure(def, expr, _), Ty::Closure(def2, expr2, _)) => {
694 expr == expr2 && def == def2
695 }
696 (Ty::Ref(mutability, ..), Ty::Ref(mutability2, ..))
697 | (Ty::Raw(mutability, ..), Ty::Raw(mutability2, ..)) => mutability == mutability2,
698 (
699 Ty::Function(FnPointer { num_args, sig, .. }),
700 Ty::Function(FnPointer { num_args: num_args2, sig: sig2, .. }),
701 ) => num_args == num_args2 && sig == sig2,
702 (Ty::Tuple(cardinality, _), Ty::Tuple(cardinality2, _)) => cardinality == cardinality2,
703 (Ty::Str, Ty::Str) | (Ty::Never, Ty::Never) => true,
704 (Ty::Scalar(scalar), Ty::Scalar(scalar2)) => scalar == scalar2,
705 _ => false,
706 }
707 }
708
809 /// If this is a `dyn Trait` type, this returns the `Trait` part. 709 /// If this is a `dyn Trait` type, this returns the `Trait` part.
810 pub fn dyn_trait_ref(&self) -> Option<&TraitRef> { 710 pub fn dyn_trait_ref(&self) -> Option<&TraitRef> {
811 match self { 711 match self {
@@ -824,41 +724,30 @@ impl Ty {
824 724
825 fn builtin_deref(&self) -> Option<Ty> { 725 fn builtin_deref(&self) -> Option<Ty> {
826 match self { 726 match self {
827 Ty::Apply(a_ty) => match a_ty.ctor { 727 Ty::Ref(.., parameters) => Some(Ty::clone(parameters.as_single())),
828 TypeCtor::Ref(..) => Some(Ty::clone(a_ty.parameters.as_single())), 728 Ty::Raw(.., parameters) => Some(Ty::clone(parameters.as_single())),
829 TypeCtor::RawPtr(..) => Some(Ty::clone(a_ty.parameters.as_single())),
830 _ => None,
831 },
832 _ => None, 729 _ => None,
833 } 730 }
834 } 731 }
835 732
836 pub fn as_fn_def(&self) -> Option<FunctionId> { 733 pub fn as_fn_def(&self) -> Option<FunctionId> {
837 match self { 734 match self {
838 &Ty::Apply(ApplicationTy { 735 &Ty::FnDef(CallableDefId::FunctionId(func), ..) => Some(func),
839 ctor: TypeCtor::FnDef(CallableDefId::FunctionId(func)),
840 ..
841 }) => Some(func),
842 _ => None, 736 _ => None,
843 } 737 }
844 } 738 }
845 739
846 pub fn callable_sig(&self, db: &dyn HirDatabase) -> Option<FnSig> { 740 pub fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig> {
847 match self { 741 match self {
848 Ty::Apply(a_ty) => match a_ty.ctor { 742 Ty::Function(fn_ptr) => Some(CallableSig::from_fn_ptr(fn_ptr)),
849 TypeCtor::FnPtr { is_varargs, .. } => { 743 Ty::FnDef(def, parameters) => {
850 Some(FnSig::from_fn_ptr_substs(&a_ty.parameters, is_varargs)) 744 let sig = db.callable_item_signature(*def);
851 } 745 Some(sig.subst(&parameters))
852 TypeCtor::FnDef(def) => { 746 }
853 let sig = db.callable_item_signature(def); 747 Ty::Closure(.., substs) => {
854 Some(sig.subst(&a_ty.parameters)) 748 let sig_param = &substs[0];
855 } 749 sig_param.callable_sig(db)
856 TypeCtor::Closure { .. } => { 750 }
857 let sig_param = &a_ty.parameters[0];
858 sig_param.callable_sig(db)
859 }
860 _ => None,
861 },
862 _ => None, 751 _ => None,
863 } 752 }
864 } 753 }
@@ -867,28 +756,66 @@ impl Ty {
867 /// the `Substs` for these type parameters with the given ones. (So e.g. if 756 /// the `Substs` for these type parameters with the given ones. (So e.g. if
868 /// `self` is `Option<_>` and the substs contain `u32`, we'll have 757 /// `self` is `Option<_>` and the substs contain `u32`, we'll have
869 /// `Option<u32>` afterwards.) 758 /// `Option<u32>` afterwards.)
870 pub fn apply_substs(self, substs: Substs) -> Ty { 759 pub fn apply_substs(mut self, new_substs: Substs) -> Ty {
871 match self { 760 match &mut self {
872 Ty::Apply(ApplicationTy { ctor, parameters: previous_substs }) => { 761 Ty::Adt(_, substs)
873 assert_eq!(previous_substs.len(), substs.len()); 762 | Ty::Slice(substs)
874 Ty::Apply(ApplicationTy { ctor, parameters: substs }) 763 | Ty::Array(substs)
764 | Ty::Raw(_, substs)
765 | Ty::Ref(_, substs)
766 | Ty::FnDef(_, substs)
767 | Ty::Function(FnPointer { substs, .. })
768 | Ty::Tuple(_, substs)
769 | Ty::OpaqueType(_, substs)
770 | Ty::AssociatedType(_, substs)
771 | Ty::Closure(.., substs) => {
772 assert_eq!(substs.len(), new_substs.len());
773 *substs = new_substs;
875 } 774 }
876 _ => self, 775 _ => (),
877 } 776 }
777 self
878 } 778 }
879 779
880 /// Returns the type parameters of this type if it has some (i.e. is an ADT 780 /// Returns the type parameters of this type if it has some (i.e. is an ADT
881 /// or function); so if `self` is `Option<u32>`, this returns the `u32`. 781 /// or function); so if `self` is `Option<u32>`, this returns the `u32`.
882 pub fn substs(&self) -> Option<Substs> { 782 pub fn substs(&self) -> Option<&Substs> {
883 match self { 783 match self {
884 Ty::Apply(ApplicationTy { parameters, .. }) => Some(parameters.clone()), 784 Ty::Adt(_, substs)
785 | Ty::Slice(substs)
786 | Ty::Array(substs)
787 | Ty::Raw(_, substs)
788 | Ty::Ref(_, substs)
789 | Ty::FnDef(_, substs)
790 | Ty::Function(FnPointer { substs, .. })
791 | Ty::Tuple(_, substs)
792 | Ty::OpaqueType(_, substs)
793 | Ty::AssociatedType(_, substs)
794 | Ty::Closure(.., substs) => Some(substs),
795 _ => None,
796 }
797 }
798
799 pub fn substs_mut(&mut self) -> Option<&mut Substs> {
800 match self {
801 Ty::Adt(_, substs)
802 | Ty::Slice(substs)
803 | Ty::Array(substs)
804 | Ty::Raw(_, substs)
805 | Ty::Ref(_, substs)
806 | Ty::FnDef(_, substs)
807 | Ty::Function(FnPointer { substs, .. })
808 | Ty::Tuple(_, substs)
809 | Ty::OpaqueType(_, substs)
810 | Ty::AssociatedType(_, substs)
811 | Ty::Closure(.., substs) => Some(substs),
885 _ => None, 812 _ => None,
886 } 813 }
887 } 814 }
888 815
889 pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<GenericPredicate>> { 816 pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<GenericPredicate>> {
890 match self { 817 match self {
891 Ty::Apply(ApplicationTy { ctor: TypeCtor::OpaqueType(opaque_ty_id), .. }) => { 818 Ty::OpaqueType(opaque_ty_id, ..) => {
892 match opaque_ty_id { 819 match opaque_ty_id {
893 OpaqueTyId::AsyncBlockTypeImplTrait(def, _expr) => { 820 OpaqueTyId::AsyncBlockTypeImplTrait(def, _expr) => {
894 let krate = def.module(db.upcast()).krate(); 821 let krate = def.module(db.upcast()).krate();
@@ -911,7 +838,7 @@ impl Ty {
911 OpaqueTyId::ReturnTypeImplTrait(..) => None, 838 OpaqueTyId::ReturnTypeImplTrait(..) => None,
912 } 839 }
913 } 840 }
914 Ty::Opaque(opaque_ty) => { 841 Ty::Alias(AliasTy::Opaque(opaque_ty)) => {
915 let predicates = match opaque_ty.opaque_ty_id { 842 let predicates = match opaque_ty.opaque_ty_id {
916 OpaqueTyId::ReturnTypeImplTrait(func, idx) => { 843 OpaqueTyId::ReturnTypeImplTrait(func, idx) => {
917 db.return_type_impl_traits(func).map(|it| { 844 db.return_type_impl_traits(func).map(|it| {
@@ -949,13 +876,13 @@ impl Ty {
949 876
950 pub fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId> { 877 pub fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId> {
951 match self { 878 match self {
952 Ty::Apply(ApplicationTy { ctor: TypeCtor::AssociatedType(type_alias_id), .. }) => { 879 Ty::AssociatedType(type_alias_id, ..) => {
953 match type_alias_id.lookup(db.upcast()).container { 880 match type_alias_id.lookup(db.upcast()).container {
954 AssocContainerId::TraitId(trait_id) => Some(trait_id), 881 AssocContainerId::TraitId(trait_id) => Some(trait_id),
955 _ => None, 882 _ => None,
956 } 883 }
957 } 884 }
958 Ty::Projection(projection_ty) => { 885 Ty::Alias(AliasTy::Projection(projection_ty)) => {
959 match projection_ty.associated_ty.lookup(db.upcast()).container { 886 match projection_ty.associated_ty.lookup(db.upcast()).container {
960 AssocContainerId::TraitId(trait_id) => Some(trait_id), 887 AssocContainerId::TraitId(trait_id) => Some(trait_id),
961 _ => None, 888 _ => None,
@@ -1033,7 +960,7 @@ pub trait TypeWalk {
1033 { 960 {
1034 self.walk_mut_binders( 961 self.walk_mut_binders(
1035 &mut |ty, binders| { 962 &mut |ty, binders| {
1036 if let &mut Ty::Bound(bound) = ty { 963 if let &mut Ty::BoundVar(bound) = ty {
1037 if bound.debruijn >= binders { 964 if bound.debruijn >= binders {
1038 *ty = substs.0[bound.index].clone().shift_bound_vars(binders); 965 *ty = substs.0[bound.index].clone().shift_bound_vars(binders);
1039 } 966 }
@@ -1051,8 +978,8 @@ pub trait TypeWalk {
1051 { 978 {
1052 self.fold_binders( 979 self.fold_binders(
1053 &mut |ty, binders| match ty { 980 &mut |ty, binders| match ty {
1054 Ty::Bound(bound) if bound.debruijn >= binders => { 981 Ty::BoundVar(bound) if bound.debruijn >= binders => {
1055 Ty::Bound(bound.shifted_in_from(n)) 982 Ty::BoundVar(bound.shifted_in_from(n))
1056 } 983 }
1057 ty => ty, 984 ty => ty,
1058 }, 985 },
@@ -1064,13 +991,13 @@ pub trait TypeWalk {
1064impl TypeWalk for Ty { 991impl TypeWalk for Ty {
1065 fn walk(&self, f: &mut impl FnMut(&Ty)) { 992 fn walk(&self, f: &mut impl FnMut(&Ty)) {
1066 match self { 993 match self {
1067 Ty::Apply(a_ty) => { 994 Ty::Alias(AliasTy::Projection(p_ty)) => {
1068 for t in a_ty.parameters.iter() { 995 for t in p_ty.parameters.iter() {
1069 t.walk(f); 996 t.walk(f);
1070 } 997 }
1071 } 998 }
1072 Ty::Projection(p_ty) => { 999 Ty::Alias(AliasTy::Opaque(o_ty)) => {
1073 for t in p_ty.parameters.iter() { 1000 for t in o_ty.parameters.iter() {
1074 t.walk(f); 1001 t.walk(f);
1075 } 1002 }
1076 } 1003 }
@@ -1079,12 +1006,13 @@ impl TypeWalk for Ty {
1079 p.walk(f); 1006 p.walk(f);
1080 } 1007 }
1081 } 1008 }
1082 Ty::Opaque(o_ty) => { 1009 _ => {
1083 for t in o_ty.parameters.iter() { 1010 if let Some(substs) = self.substs() {
1084 t.walk(f); 1011 for t in substs.iter() {
1012 t.walk(f);
1013 }
1085 } 1014 }
1086 } 1015 }
1087 Ty::Placeholder { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
1088 } 1016 }
1089 f(self); 1017 f(self);
1090 } 1018 }
@@ -1095,10 +1023,7 @@ impl TypeWalk for Ty {
1095 binders: DebruijnIndex, 1023 binders: DebruijnIndex,
1096 ) { 1024 ) {
1097 match self { 1025 match self {
1098 Ty::Apply(a_ty) => { 1026 Ty::Alias(AliasTy::Projection(p_ty)) => {
1099 a_ty.parameters.walk_mut_binders(f, binders);
1100 }
1101 Ty::Projection(p_ty) => {
1102 p_ty.parameters.walk_mut_binders(f, binders); 1027 p_ty.parameters.walk_mut_binders(f, binders);
1103 } 1028 }
1104 Ty::Dyn(predicates) => { 1029 Ty::Dyn(predicates) => {
@@ -1106,10 +1031,14 @@ impl TypeWalk for Ty {
1106 p.walk_mut_binders(f, binders.shifted_in()); 1031 p.walk_mut_binders(f, binders.shifted_in());
1107 } 1032 }
1108 } 1033 }
1109 Ty::Opaque(o_ty) => { 1034 Ty::Alias(AliasTy::Opaque(o_ty)) => {
1110 o_ty.parameters.walk_mut_binders(f, binders); 1035 o_ty.parameters.walk_mut_binders(f, binders);
1111 } 1036 }
1112 Ty::Placeholder { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} 1037 _ => {
1038 if let Some(substs) = self.substs_mut() {
1039 substs.walk_mut_binders(f, binders);
1040 }
1041 }
1113 } 1042 }
1114 f(self, binders); 1043 f(self, binders);
1115 } 1044 }
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index 99b0ecf3b..1b5843d48 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -8,6 +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::Mutability;
11use hir_def::{ 12use hir_def::{
12 adt::StructKind, 13 adt::StructKind,
13 builtin_type::BuiltinType, 14 builtin_type::BuiltinType,
@@ -31,9 +32,9 @@ use crate::{
31 all_super_trait_refs, associated_type_by_name_including_super_traits, generics, 32 all_super_trait_refs, associated_type_by_name_including_super_traits, generics,
32 make_mut_slice, variant_data, 33 make_mut_slice, variant_data,
33 }, 34 },
34 Binders, BoundVar, DebruijnIndex, FnSig, GenericPredicate, OpaqueTy, OpaqueTyId, PolyFnSig, 35 AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, FnPointer, FnSig, GenericPredicate,
35 ProjectionPredicate, ProjectionTy, ReturnTypeImplTrait, ReturnTypeImplTraits, Substs, 36 OpaqueTy, OpaqueTyId, PolyFnSig, ProjectionPredicate, ProjectionTy, ReturnTypeImplTrait,
36 TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, 37 ReturnTypeImplTraits, Substs, TraitEnvironment, TraitRef, Ty, TypeWalk,
37}; 38};
38 39
39#[derive(Debug)] 40#[derive(Debug)]
@@ -145,13 +146,10 @@ impl Ty {
145 pub fn from_hir_ext(ctx: &TyLoweringContext<'_>, type_ref: &TypeRef) -> (Self, Option<TypeNs>) { 146 pub fn from_hir_ext(ctx: &TyLoweringContext<'_>, type_ref: &TypeRef) -> (Self, Option<TypeNs>) {
146 let mut res = None; 147 let mut res = None;
147 let ty = match type_ref { 148 let ty = match type_ref {
148 TypeRef::Never => Ty::simple(TypeCtor::Never), 149 TypeRef::Never => Ty::Never,
149 TypeRef::Tuple(inner) => { 150 TypeRef::Tuple(inner) => {
150 let inner_tys: Arc<[Ty]> = inner.iter().map(|tr| Ty::from_hir(ctx, tr)).collect(); 151 let inner_tys: Arc<[Ty]> = inner.iter().map(|tr| Ty::from_hir(ctx, tr)).collect();
151 Ty::apply( 152 Ty::Tuple(inner_tys.len(), Substs(inner_tys))
152 TypeCtor::Tuple { cardinality: inner_tys.len() as u16 },
153 Substs(inner_tys),
154 )
155 } 153 }
156 TypeRef::Path(path) => { 154 TypeRef::Path(path) => {
157 let (ty, res_) = Ty::from_hir_path(ctx, path); 155 let (ty, res_) = Ty::from_hir_path(ctx, path);
@@ -160,30 +158,31 @@ impl Ty {
160 } 158 }
161 TypeRef::RawPtr(inner, mutability) => { 159 TypeRef::RawPtr(inner, mutability) => {
162 let inner_ty = Ty::from_hir(ctx, inner); 160 let inner_ty = Ty::from_hir(ctx, inner);
163 Ty::apply_one(TypeCtor::RawPtr(*mutability), inner_ty) 161 Ty::Raw(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty))
164 } 162 }
165 TypeRef::Array(inner) => { 163 TypeRef::Array(inner) => {
166 let inner_ty = Ty::from_hir(ctx, inner); 164 let inner_ty = Ty::from_hir(ctx, inner);
167 Ty::apply_one(TypeCtor::Array, inner_ty) 165 Ty::Array(Substs::single(inner_ty))
168 } 166 }
169 TypeRef::Slice(inner) => { 167 TypeRef::Slice(inner) => {
170 let inner_ty = Ty::from_hir(ctx, inner); 168 let inner_ty = Ty::from_hir(ctx, inner);
171 Ty::apply_one(TypeCtor::Slice, inner_ty) 169 Ty::Slice(Substs::single(inner_ty))
172 } 170 }
173 TypeRef::Reference(inner, _, mutability) => { 171 TypeRef::Reference(inner, _, mutability) => {
174 let inner_ty = Ty::from_hir(ctx, inner); 172 let inner_ty = Ty::from_hir(ctx, inner);
175 Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) 173 Ty::Ref(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty))
176 } 174 }
177 TypeRef::Placeholder => Ty::Unknown, 175 TypeRef::Placeholder => Ty::Unknown,
178 TypeRef::Fn(params, is_varargs) => { 176 TypeRef::Fn(params, is_varargs) => {
179 let sig = Substs(params.iter().map(|tr| Ty::from_hir(ctx, tr)).collect()); 177 let substs = Substs(params.iter().map(|tr| Ty::from_hir(ctx, tr)).collect());
180 Ty::apply( 178 Ty::Function(FnPointer {
181 TypeCtor::FnPtr { num_args: sig.len() as u16 - 1, is_varargs: *is_varargs }, 179 num_args: substs.len() - 1,
182 sig, 180 sig: FnSig { variadic: *is_varargs },
183 ) 181 substs,
182 })
184 } 183 }
185 TypeRef::DynTrait(bounds) => { 184 TypeRef::DynTrait(bounds) => {
186 let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); 185 let self_ty = Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0));
187 let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| { 186 let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| {
188 bounds 187 bounds
189 .iter() 188 .iter()
@@ -227,7 +226,10 @@ impl Ty {
227 let impl_trait_id = OpaqueTyId::ReturnTypeImplTrait(func, idx); 226 let impl_trait_id = OpaqueTyId::ReturnTypeImplTrait(func, idx);
228 let generics = generics(ctx.db.upcast(), func.into()); 227 let generics = generics(ctx.db.upcast(), func.into());
229 let parameters = Substs::bound_vars(&generics, ctx.in_binders); 228 let parameters = Substs::bound_vars(&generics, ctx.in_binders);
230 Ty::Opaque(OpaqueTy { opaque_ty_id: impl_trait_id, parameters }) 229 Ty::Alias(AliasTy::Opaque(OpaqueTy {
230 opaque_ty_id: impl_trait_id,
231 parameters,
232 }))
231 } 233 }
232 ImplTraitLoweringMode::Param => { 234 ImplTraitLoweringMode::Param => {
233 let idx = ctx.impl_trait_counter.get(); 235 let idx = ctx.impl_trait_counter.get();
@@ -258,7 +260,7 @@ impl Ty {
258 } else { 260 } else {
259 (0, 0, 0, 0) 261 (0, 0, 0, 0)
260 }; 262 };
261 Ty::Bound(BoundVar::new( 263 Ty::BoundVar(BoundVar::new(
262 ctx.in_binders, 264 ctx.in_binders,
263 idx as usize + parent_params + self_params + list_params, 265 idx as usize + parent_params + self_params + list_params,
264 )) 266 ))
@@ -330,7 +332,7 @@ impl Ty {
330 TypeNs::TraitId(trait_) => { 332 TypeNs::TraitId(trait_) => {
331 // if this is a bare dyn Trait, we'll directly put the required ^0 for the self type in there 333 // if this is a bare dyn Trait, we'll directly put the required ^0 for the self type in there
332 let self_ty = if remaining_segments.len() == 0 { 334 let self_ty = if remaining_segments.len() == 0 {
333 Some(Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0))) 335 Some(Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)))
334 } else { 336 } else {
335 None 337 None
336 }; 338 };
@@ -346,10 +348,10 @@ impl Ty {
346 match found { 348 match found {
347 Some((super_trait_ref, associated_ty)) => { 349 Some((super_trait_ref, associated_ty)) => {
348 // FIXME handle type parameters on the segment 350 // FIXME handle type parameters on the segment
349 Ty::Projection(ProjectionTy { 351 Ty::Alias(AliasTy::Projection(ProjectionTy {
350 associated_ty, 352 associated_ty,
351 parameters: super_trait_ref.substs, 353 parameters: super_trait_ref.substs,
352 }) 354 }))
353 } 355 }
354 None => { 356 None => {
355 // FIXME: report error (associated type not found) 357 // FIXME: report error (associated type not found)
@@ -373,7 +375,7 @@ impl Ty {
373 TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id), 375 TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id),
374 TypeParamLoweringMode::Variable => { 376 TypeParamLoweringMode::Variable => {
375 let idx = generics.param_idx(param_id).expect("matching generics"); 377 let idx = generics.param_idx(param_id).expect("matching generics");
376 Ty::Bound(BoundVar::new(ctx.in_binders, idx)) 378 Ty::BoundVar(BoundVar::new(ctx.in_binders, idx))
377 } 379 }
378 } 380 }
379 } 381 }
@@ -414,7 +416,6 @@ impl Ty {
414 // FIXME: report error 416 // FIXME: report error
415 TypeNs::EnumVariantId(_) => return (Ty::Unknown, None), 417 TypeNs::EnumVariantId(_) => return (Ty::Unknown, None),
416 }; 418 };
417
418 Ty::from_type_relative_path(ctx, ty, Some(resolution), remaining_segments) 419 Ty::from_type_relative_path(ctx, ty, Some(resolution), remaining_segments)
419 } 420 }
420 421
@@ -472,10 +473,10 @@ impl Ty {
472 // associated_type_shorthand_candidates does not do that 473 // associated_type_shorthand_candidates does not do that
473 let substs = substs.shift_bound_vars(ctx.in_binders); 474 let substs = substs.shift_bound_vars(ctx.in_binders);
474 // FIXME handle type parameters on the segment 475 // FIXME handle type parameters on the segment
475 return Some(Ty::Projection(ProjectionTy { 476 return Some(Ty::Alias(AliasTy::Projection(ProjectionTy {
476 associated_ty, 477 associated_ty,
477 parameters: substs, 478 parameters: substs,
478 })); 479 })));
479 } 480 }
480 481
481 None 482 None
@@ -676,7 +677,7 @@ impl GenericPredicate {
676 TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id), 677 TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id),
677 TypeParamLoweringMode::Variable => { 678 TypeParamLoweringMode::Variable => {
678 let idx = generics.param_idx(param_id).expect("matching generics"); 679 let idx = generics.param_idx(param_id).expect("matching generics");
679 Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, idx)) 680 Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, idx))
680 } 681 }
681 } 682 }
682 } 683 }
@@ -750,7 +751,7 @@ fn assoc_type_bindings_from_type_bound<'a>(
750 preds.extend(GenericPredicate::from_type_bound( 751 preds.extend(GenericPredicate::from_type_bound(
751 ctx, 752 ctx,
752 bound, 753 bound,
753 Ty::Projection(projection_ty.clone()), 754 Ty::Alias(AliasTy::Projection(projection_ty.clone())),
754 )); 755 ));
755 } 756 }
756 preds 757 preds
@@ -760,7 +761,7 @@ fn assoc_type_bindings_from_type_bound<'a>(
760impl ReturnTypeImplTrait { 761impl ReturnTypeImplTrait {
761 fn from_hir(ctx: &TyLoweringContext, bounds: &[TypeBound]) -> Self { 762 fn from_hir(ctx: &TyLoweringContext, bounds: &[TypeBound]) -> Self {
762 mark::hit!(lower_rpit); 763 mark::hit!(lower_rpit);
763 let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); 764 let self_ty = Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0));
764 let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| { 765 let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| {
765 bounds 766 bounds
766 .iter() 767 .iter()
@@ -984,7 +985,7 @@ pub(crate) fn generic_defaults_query(
984 // Each default can only refer to previous parameters. 985 // Each default can only refer to previous parameters.
985 ty.walk_mut_binders( 986 ty.walk_mut_binders(
986 &mut |ty, binders| match ty { 987 &mut |ty, binders| match ty {
987 Ty::Bound(BoundVar { debruijn, index }) if *debruijn == binders => { 988 Ty::BoundVar(BoundVar { debruijn, index }) if *debruijn == binders => {
988 if *index >= idx { 989 if *index >= idx {
989 // type variable default referring to parameter coming 990 // type variable default referring to parameter coming
990 // after it. This is forbidden (FIXME: report 991 // after it. This is forbidden (FIXME: report
@@ -1017,7 +1018,7 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
1017 let ret = Ty::from_hir(&ctx_ret, &data.ret_type); 1018 let ret = Ty::from_hir(&ctx_ret, &data.ret_type);
1018 let generics = generics(db.upcast(), def.into()); 1019 let generics = generics(db.upcast(), def.into());
1019 let num_binders = generics.len(); 1020 let num_binders = generics.len();
1020 Binders::new(num_binders, FnSig::from_params_and_return(params, ret, data.is_varargs)) 1021 Binders::new(num_binders, CallableSig::from_params_and_return(params, ret, data.is_varargs))
1021} 1022}
1022 1023
1023/// Build the declared type of a function. This should not need to look at the 1024/// Build the declared type of a function. This should not need to look at the
@@ -1025,7 +1026,7 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
1025fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> Binders<Ty> { 1026fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> Binders<Ty> {
1026 let generics = generics(db.upcast(), def.into()); 1027 let generics = generics(db.upcast(), def.into());
1027 let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); 1028 let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST);
1028 Binders::new(substs.len(), Ty::apply(TypeCtor::FnDef(def.into()), substs)) 1029 Binders::new(substs.len(), Ty::FnDef(def.into(), substs))
1029} 1030}
1030 1031
1031/// Build the declared type of a const. 1032/// Build the declared type of a const.
@@ -1057,7 +1058,7 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS
1057 let params = 1058 let params =
1058 fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>(); 1059 fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>();
1059 let ret = type_for_adt(db, def.into()); 1060 let ret = type_for_adt(db, def.into());
1060 Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value, false)) 1061 Binders::new(ret.num_binders, CallableSig::from_params_and_return(params, ret.value, false))
1061} 1062}
1062 1063
1063/// Build the type of a tuple struct constructor. 1064/// Build the type of a tuple struct constructor.
@@ -1068,7 +1069,7 @@ fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Binders<T
1068 } 1069 }
1069 let generics = generics(db.upcast(), def.into()); 1070 let generics = generics(db.upcast(), def.into());
1070 let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); 1071 let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST);
1071 Binders::new(substs.len(), Ty::apply(TypeCtor::FnDef(def.into()), substs)) 1072 Binders::new(substs.len(), Ty::FnDef(def.into(), substs))
1072} 1073}
1073 1074
1074fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -> PolyFnSig { 1075fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -> PolyFnSig {
@@ -1081,7 +1082,7 @@ fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId)
1081 let params = 1082 let params =
1082 fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>(); 1083 fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>();
1083 let ret = type_for_adt(db, def.parent.into()); 1084 let ret = type_for_adt(db, def.parent.into());
1084 Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value, false)) 1085 Binders::new(ret.num_binders, CallableSig::from_params_and_return(params, ret.value, false))
1085} 1086}
1086 1087
1087/// Build the type of a tuple enum variant constructor. 1088/// Build the type of a tuple enum variant constructor.
@@ -1093,13 +1094,13 @@ fn type_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -
1093 } 1094 }
1094 let generics = generics(db.upcast(), def.parent.into()); 1095 let generics = generics(db.upcast(), def.parent.into());
1095 let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); 1096 let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST);
1096 Binders::new(substs.len(), Ty::apply(TypeCtor::FnDef(def.into()), substs)) 1097 Binders::new(substs.len(), Ty::FnDef(def.into(), substs))
1097} 1098}
1098 1099
1099fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> { 1100fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> {
1100 let generics = generics(db.upcast(), adt.into()); 1101 let generics = generics(db.upcast(), adt.into());
1101 let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); 1102 let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST);
1102 Binders::new(substs.len(), Ty::apply(TypeCtor::Adt(adt), substs)) 1103 Binders::new(substs.len(), Ty::Adt(adt, substs))
1103} 1104}
1104 1105
1105fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> { 1106fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> {
@@ -1107,10 +1108,10 @@ fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> {
1107 let resolver = t.resolver(db.upcast()); 1108 let resolver = t.resolver(db.upcast());
1108 let ctx = 1109 let ctx =
1109 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); 1110 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
1110 let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST);
1111 if db.type_alias_data(t).is_extern { 1111 if db.type_alias_data(t).is_extern {
1112 Binders::new(substs.len(), Ty::apply(TypeCtor::ForeignType(t), substs)) 1112 Binders::new(0, Ty::ForeignType(t))
1113 } else { 1113 } else {
1114 let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST);
1114 let type_ref = &db.type_alias_data(t).type_ref; 1115 let type_ref = &db.type_alias_data(t).type_ref;
1115 let inner = Ty::from_hir(&ctx, type_ref.as_ref().unwrap_or(&TypeRef::Error)); 1116 let inner = Ty::from_hir(&ctx, type_ref.as_ref().unwrap_or(&TypeRef::Error));
1116 Binders::new(substs.len(), inner) 1117 Binders::new(substs.len(), inner)
@@ -1259,3 +1260,10 @@ pub(crate) fn return_type_impl_traits(
1259 Some(Arc::new(Binders::new(num_binders, return_type_impl_traits))) 1260 Some(Arc::new(Binders::new(num_binders, return_type_impl_traits)))
1260 } 1261 }
1261} 1262}
1263
1264pub(crate) fn lower_to_chalk_mutability(m: hir_def::type_ref::Mutability) -> Mutability {
1265 match m {
1266 hir_def::type_ref::Mutability::Shared => Mutability::Not,
1267 hir_def::type_ref::Mutability::Mut => Mutability::Mut,
1268 }
1269}
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index b3d1fe9a4..f301a8477 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -6,12 +6,10 @@ use std::{iter, sync::Arc};
6 6
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use base_db::CrateId; 8use base_db::CrateId;
9use chalk_ir::Mutability;
9use hir_def::{ 10use hir_def::{
10 builtin_type::{IntBitness, Signedness}, 11 lang_item::LangItemTarget, AdtId, AssocContainerId, AssocItemId, FunctionId, GenericDefId,
11 lang_item::LangItemTarget, 12 HasModule, ImplId, Lookup, ModuleId, TraitId, TypeAliasId,
12 type_ref::Mutability,
13 AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule, ImplId, Lookup, ModuleId,
14 TraitId,
15}; 13};
16use hir_expand::name::Name; 14use hir_expand::name::Name;
17use rustc_hash::{FxHashMap, FxHashSet}; 15use rustc_hash::{FxHashMap, FxHashSet};
@@ -19,17 +17,26 @@ use rustc_hash::{FxHashMap, FxHashSet};
19use crate::{ 17use crate::{
20 autoderef, 18 autoderef,
21 db::HirDatabase, 19 db::HirDatabase,
22 primitive::{FloatBitness, FloatTy, IntTy}, 20 primitive::{self, FloatTy, IntTy, UintTy},
23 utils::all_super_traits, 21 utils::all_super_traits,
24 ApplicationTy, Canonical, DebruijnIndex, InEnvironment, Substs, TraitEnvironment, TraitRef, Ty, 22 Canonical, DebruijnIndex, FnPointer, FnSig, InEnvironment, Scalar, Substs, TraitEnvironment,
25 TyKind, TypeCtor, TypeWalk, 23 TraitRef, Ty, TypeWalk,
26}; 24};
27 25
28/// This is used as a key for indexing impls. 26/// This is used as a key for indexing impls.
29#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 27#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
30pub enum TyFingerprint { 28pub enum TyFingerprint {
31 Apply(TypeCtor), 29 Str,
30 Slice,
31 Array,
32 Never,
33 RawPtr(Mutability),
34 Scalar(Scalar),
35 Adt(AdtId),
32 Dyn(TraitId), 36 Dyn(TraitId),
37 Tuple(usize),
38 ForeignType(TypeAliasId),
39 FnPtr(usize, FnSig),
33} 40}
34 41
35impl TyFingerprint { 42impl TyFingerprint {
@@ -37,68 +44,42 @@ impl TyFingerprint {
37 /// have impls: if we have some `struct S`, we can have an `impl S`, but not 44 /// have impls: if we have some `struct S`, we can have an `impl S`, but not
38 /// `impl &S`. Hence, this will return `None` for reference types and such. 45 /// `impl &S`. Hence, this will return `None` for reference types and such.
39 pub(crate) fn for_impl(ty: &Ty) -> Option<TyFingerprint> { 46 pub(crate) fn for_impl(ty: &Ty) -> Option<TyFingerprint> {
40 match ty { 47 let fp = match ty {
41 Ty::Apply(a_ty) => Some(TyFingerprint::Apply(a_ty.ctor)), 48 &Ty::Str => TyFingerprint::Str,
42 Ty::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_)), 49 &Ty::Never => TyFingerprint::Never,
43 _ => None, 50 &Ty::Slice(..) => TyFingerprint::Slice,
44 } 51 &Ty::Array(..) => TyFingerprint::Array,
52 &Ty::Scalar(scalar) => TyFingerprint::Scalar(scalar),
53 &Ty::Adt(adt, _) => TyFingerprint::Adt(adt),
54 &Ty::Tuple(cardinality, _) => TyFingerprint::Tuple(cardinality),
55 &Ty::Raw(mutability, ..) => TyFingerprint::RawPtr(mutability),
56 &Ty::ForeignType(alias_id, ..) => TyFingerprint::ForeignType(alias_id),
57 &Ty::Function(FnPointer { num_args, sig, .. }) => TyFingerprint::FnPtr(num_args, sig),
58 Ty::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_))?,
59 _ => return None,
60 };
61 Some(fp)
45 } 62 }
46} 63}
47 64
48pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [ 65pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [
49 TyFingerprint::Apply(TypeCtor::Int(IntTy { 66 TyFingerprint::Scalar(Scalar::Int(IntTy::I8)),
50 signedness: Signedness::Unsigned, 67 TyFingerprint::Scalar(Scalar::Int(IntTy::I16)),
51 bitness: IntBitness::X8, 68 TyFingerprint::Scalar(Scalar::Int(IntTy::I32)),
52 })), 69 TyFingerprint::Scalar(Scalar::Int(IntTy::I64)),
53 TyFingerprint::Apply(TypeCtor::Int(IntTy { 70 TyFingerprint::Scalar(Scalar::Int(IntTy::I128)),
54 signedness: Signedness::Unsigned, 71 TyFingerprint::Scalar(Scalar::Int(IntTy::Isize)),
55 bitness: IntBitness::X16, 72 TyFingerprint::Scalar(Scalar::Uint(UintTy::U8)),
56 })), 73 TyFingerprint::Scalar(Scalar::Uint(UintTy::U16)),
57 TyFingerprint::Apply(TypeCtor::Int(IntTy { 74 TyFingerprint::Scalar(Scalar::Uint(UintTy::U32)),
58 signedness: Signedness::Unsigned, 75 TyFingerprint::Scalar(Scalar::Uint(UintTy::U64)),
59 bitness: IntBitness::X32, 76 TyFingerprint::Scalar(Scalar::Uint(UintTy::U128)),
60 })), 77 TyFingerprint::Scalar(Scalar::Uint(UintTy::Usize)),
61 TyFingerprint::Apply(TypeCtor::Int(IntTy {
62 signedness: Signedness::Unsigned,
63 bitness: IntBitness::X64,
64 })),
65 TyFingerprint::Apply(TypeCtor::Int(IntTy {
66 signedness: Signedness::Unsigned,
67 bitness: IntBitness::X128,
68 })),
69 TyFingerprint::Apply(TypeCtor::Int(IntTy {
70 signedness: Signedness::Unsigned,
71 bitness: IntBitness::Xsize,
72 })),
73 TyFingerprint::Apply(TypeCtor::Int(IntTy {
74 signedness: Signedness::Signed,
75 bitness: IntBitness::X8,
76 })),
77 TyFingerprint::Apply(TypeCtor::Int(IntTy {
78 signedness: Signedness::Signed,
79 bitness: IntBitness::X16,
80 })),
81 TyFingerprint::Apply(TypeCtor::Int(IntTy {
82 signedness: Signedness::Signed,
83 bitness: IntBitness::X32,
84 })),
85 TyFingerprint::Apply(TypeCtor::Int(IntTy {
86 signedness: Signedness::Signed,
87 bitness: IntBitness::X64,
88 })),
89 TyFingerprint::Apply(TypeCtor::Int(IntTy {
90 signedness: Signedness::Signed,
91 bitness: IntBitness::X128,
92 })),
93 TyFingerprint::Apply(TypeCtor::Int(IntTy {
94 signedness: Signedness::Signed,
95 bitness: IntBitness::Xsize,
96 })),
97]; 78];
98 79
99pub(crate) const ALL_FLOAT_FPS: [TyFingerprint; 2] = [ 80pub(crate) const ALL_FLOAT_FPS: [TyFingerprint; 2] = [
100 TyFingerprint::Apply(TypeCtor::Float(FloatTy { bitness: FloatBitness::X32 })), 81 TyFingerprint::Scalar(Scalar::Float(FloatTy::F32)),
101 TyFingerprint::Apply(TypeCtor::Float(FloatTy { bitness: FloatBitness::X64 })), 82 TyFingerprint::Scalar(Scalar::Float(FloatTy::F64)),
102]; 83];
103 84
104/// Trait impls defined or available in some crate. 85/// Trait impls defined or available in some crate.
@@ -250,27 +231,29 @@ impl Ty {
250 let mod_to_crate_ids = |module: ModuleId| Some(std::iter::once(module.krate()).collect()); 231 let mod_to_crate_ids = |module: ModuleId| Some(std::iter::once(module.krate()).collect());
251 232
252 let lang_item_targets = match self { 233 let lang_item_targets = match self {
253 Ty::Apply(a_ty) => match a_ty.ctor { 234 Ty::Adt(def_id, _) => {
254 TypeCtor::Adt(def_id) => { 235 return mod_to_crate_ids(def_id.module(db.upcast()));
255 return mod_to_crate_ids(def_id.module(db.upcast())); 236 }
256 } 237 Ty::ForeignType(type_alias_id) => {
257 TypeCtor::ForeignType(type_alias_id) => { 238 return mod_to_crate_ids(type_alias_id.lookup(db.upcast()).module(db.upcast()));
258 return mod_to_crate_ids(type_alias_id.lookup(db.upcast()).module(db.upcast())); 239 }
259 } 240 Ty::Scalar(Scalar::Bool) => lang_item_crate!("bool"),
260 TypeCtor::Bool => lang_item_crate!("bool"), 241 Ty::Scalar(Scalar::Char) => lang_item_crate!("char"),
261 TypeCtor::Char => lang_item_crate!("char"), 242 Ty::Scalar(Scalar::Float(f)) => match f {
262 TypeCtor::Float(f) => match f.bitness { 243 // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime)
263 // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime) 244 FloatTy::F32 => lang_item_crate!("f32", "f32_runtime"),
264 FloatBitness::X32 => lang_item_crate!("f32", "f32_runtime"), 245 FloatTy::F64 => lang_item_crate!("f64", "f64_runtime"),
265 FloatBitness::X64 => lang_item_crate!("f64", "f64_runtime"),
266 },
267 TypeCtor::Int(i) => lang_item_crate!(i.ty_to_string()),
268 TypeCtor::Str => lang_item_crate!("str_alloc", "str"),
269 TypeCtor::Slice => lang_item_crate!("slice_alloc", "slice"),
270 TypeCtor::RawPtr(Mutability::Shared) => lang_item_crate!("const_ptr"),
271 TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!("mut_ptr"),
272 _ => return None,
273 }, 246 },
247 &Ty::Scalar(Scalar::Int(t)) => {
248 lang_item_crate!(primitive::int_ty_to_string(t))
249 }
250 &Ty::Scalar(Scalar::Uint(t)) => {
251 lang_item_crate!(primitive::uint_ty_to_string(t))
252 }
253 Ty::Str => lang_item_crate!("str_alloc", "str"),
254 Ty::Slice(_) => lang_item_crate!("slice_alloc", "slice"),
255 Ty::Raw(Mutability::Not, _) => lang_item_crate!("const_ptr"),
256 Ty::Raw(Mutability::Mut, _) => lang_item_crate!("mut_ptr"),
274 Ty::Dyn(_) => { 257 Ty::Dyn(_) => {
275 return self.dyn_trait().and_then(|trait_| { 258 return self.dyn_trait().and_then(|trait_| {
276 mod_to_crate_ids(GenericDefId::TraitId(trait_).module(db.upcast())) 259 mod_to_crate_ids(GenericDefId::TraitId(trait_).module(db.upcast()))
@@ -447,7 +430,7 @@ fn iterate_method_candidates_with_autoref(
447 } 430 }
448 let refed = Canonical { 431 let refed = Canonical {
449 kinds: deref_chain[0].kinds.clone(), 432 kinds: deref_chain[0].kinds.clone(),
450 value: Ty::apply_one(TypeCtor::Ref(Mutability::Shared), deref_chain[0].value.clone()), 433 value: Ty::Ref(Mutability::Not, Substs::single(deref_chain[0].value.clone())),
451 }; 434 };
452 if iterate_method_candidates_by_receiver( 435 if iterate_method_candidates_by_receiver(
453 &refed, 436 &refed,
@@ -463,7 +446,7 @@ fn iterate_method_candidates_with_autoref(
463 } 446 }
464 let ref_muted = Canonical { 447 let ref_muted = Canonical {
465 kinds: deref_chain[0].kinds.clone(), 448 kinds: deref_chain[0].kinds.clone(),
466 value: Ty::apply_one(TypeCtor::Ref(Mutability::Mut), deref_chain[0].value.clone()), 449 value: Ty::Ref(Mutability::Mut, Substs::single(deref_chain[0].value.clone())),
467 }; 450 };
468 if iterate_method_candidates_by_receiver( 451 if iterate_method_candidates_by_receiver(
469 &ref_muted, 452 &ref_muted,
@@ -685,7 +668,7 @@ pub(crate) fn inherent_impl_substs(
685 .build(); 668 .build();
686 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); 669 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars);
687 let mut kinds = self_ty.kinds.to_vec(); 670 let mut kinds = self_ty.kinds.to_vec();
688 kinds.extend(iter::repeat(TyKind::General).take(vars.len())); 671 kinds.extend(iter::repeat(chalk_ir::TyVariableKind::General).take(vars.len()));
689 let tys = Canonical { kinds: kinds.into(), value: (self_ty_with_vars, self_ty.value.clone()) }; 672 let tys = Canonical { kinds: kinds.into(), value: (self_ty_with_vars, self_ty.value.clone()) };
690 let substs = super::infer::unify(&tys); 673 let substs = super::infer::unify(&tys);
691 // We only want the substs for the vars we added, not the ones from self_ty. 674 // We only want the substs for the vars we added, not the ones from self_ty.
@@ -701,7 +684,7 @@ pub(crate) fn inherent_impl_substs(
701fn fallback_bound_vars(s: Substs, num_vars_to_keep: usize) -> Substs { 684fn fallback_bound_vars(s: Substs, num_vars_to_keep: usize) -> Substs {
702 s.fold_binders( 685 s.fold_binders(
703 &mut |ty, binders| { 686 &mut |ty, binders| {
704 if let Ty::Bound(bound) = &ty { 687 if let Ty::BoundVar(bound) = &ty {
705 if bound.index >= num_vars_to_keep && bound.debruijn >= binders { 688 if bound.index >= num_vars_to_keep && bound.debruijn >= binders {
706 Ty::Unknown 689 Ty::Unknown
707 } else { 690 } else {
@@ -777,7 +760,7 @@ fn generic_implements_goal(
777 .push(self_ty.value) 760 .push(self_ty.value)
778 .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len()) 761 .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len())
779 .build(); 762 .build();
780 kinds.extend(iter::repeat(TyKind::General).take(substs.len() - 1)); 763 kinds.extend(iter::repeat(chalk_ir::TyVariableKind::General).take(substs.len() - 1));
781 let trait_ref = TraitRef { trait_, substs }; 764 let trait_ref = TraitRef { trait_, substs };
782 let obligation = super::Obligation::Trait(trait_ref); 765 let obligation = super::Obligation::Trait(trait_ref);
783 Canonical { kinds: kinds.into(), value: InEnvironment::new(env, obligation) } 766 Canonical { kinds: kinds.into(), value: InEnvironment::new(env, obligation) }
@@ -790,11 +773,9 @@ fn autoderef_method_receiver(
790) -> Vec<Canonical<Ty>> { 773) -> Vec<Canonical<Ty>> {
791 let mut deref_chain: Vec<_> = autoderef::autoderef(db, Some(krate), ty).collect(); 774 let mut deref_chain: Vec<_> = autoderef::autoderef(db, Some(krate), ty).collect();
792 // As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!) 775 // As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!)
793 if let Some(Ty::Apply(ApplicationTy { ctor: TypeCtor::Array, parameters })) = 776 if let Some(Ty::Array(parameters)) = deref_chain.last().map(|ty| &ty.value) {
794 deref_chain.last().map(|ty| &ty.value)
795 {
796 let kinds = deref_chain.last().unwrap().kinds.clone(); 777 let kinds = deref_chain.last().unwrap().kinds.clone();
797 let unsized_ty = Ty::apply(TypeCtor::Slice, parameters.clone()); 778 let unsized_ty = Ty::Slice(parameters.clone());
798 deref_chain.push(Canonical { value: unsized_ty, kinds }) 779 deref_chain.push(Canonical { value: unsized_ty, kinds })
799 } 780 }
800 deref_chain 781 deref_chain
diff --git a/crates/hir_ty/src/op.rs b/crates/hir_ty/src/op.rs
index 0870874fc..bb9b8bbfc 100644
--- a/crates/hir_ty/src/op.rs
+++ b/crates/hir_ty/src/op.rs
@@ -1,27 +1,27 @@
1//! Helper functions for binary operator type inference. 1//! Helper functions for binary operator type inference.
2use chalk_ir::TyVariableKind;
2use hir_def::expr::{ArithOp, BinaryOp, CmpOp}; 3use hir_def::expr::{ArithOp, BinaryOp, CmpOp};
3 4
4use super::{InferTy, Ty, TypeCtor}; 5use crate::{Scalar, Ty};
5use crate::ApplicationTy;
6 6
7pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty { 7pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty {
8 match op { 8 match op {
9 BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => Ty::simple(TypeCtor::Bool), 9 BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => Ty::Scalar(Scalar::Bool),
10 BinaryOp::Assignment { .. } => Ty::unit(), 10 BinaryOp::Assignment { .. } => Ty::unit(),
11 BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => match lhs_ty { 11 BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => match lhs_ty {
12 Ty::Apply(ApplicationTy { ctor, .. }) => match ctor { 12 Ty::Scalar(Scalar::Int(_))
13 TypeCtor::Int(..) | TypeCtor::Float(..) => lhs_ty, 13 | Ty::Scalar(Scalar::Uint(_))
14 _ => Ty::Unknown, 14 | Ty::Scalar(Scalar::Float(_)) => lhs_ty,
15 }, 15 Ty::InferenceVar(_, TyVariableKind::Integer)
16 Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => lhs_ty, 16 | Ty::InferenceVar(_, TyVariableKind::Float) => lhs_ty,
17 _ => Ty::Unknown, 17 _ => Ty::Unknown,
18 }, 18 },
19 BinaryOp::ArithOp(_) => match rhs_ty { 19 BinaryOp::ArithOp(_) => match rhs_ty {
20 Ty::Apply(ApplicationTy { ctor, .. }) => match ctor { 20 Ty::Scalar(Scalar::Int(_))
21 TypeCtor::Int(..) | TypeCtor::Float(..) => rhs_ty, 21 | Ty::Scalar(Scalar::Uint(_))
22 _ => Ty::Unknown, 22 | Ty::Scalar(Scalar::Float(_)) => rhs_ty,
23 }, 23 Ty::InferenceVar(_, TyVariableKind::Integer)
24 Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => rhs_ty, 24 | Ty::InferenceVar(_, TyVariableKind::Float) => rhs_ty,
25 _ => Ty::Unknown, 25 _ => Ty::Unknown,
26 }, 26 },
27 } 27 }
@@ -29,29 +29,23 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty {
29 29
30pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { 30pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty {
31 match op { 31 match op {
32 BinaryOp::LogicOp(..) => Ty::simple(TypeCtor::Bool), 32 BinaryOp::LogicOp(..) => Ty::Scalar(Scalar::Bool),
33 BinaryOp::Assignment { op: None } => lhs_ty, 33 BinaryOp::Assignment { op: None } => lhs_ty,
34 BinaryOp::CmpOp(CmpOp::Eq { .. }) => match lhs_ty { 34 BinaryOp::CmpOp(CmpOp::Eq { .. }) => match lhs_ty {
35 Ty::Apply(ApplicationTy { ctor, .. }) => match ctor { 35 Ty::Scalar(_) | Ty::Str => lhs_ty,
36 TypeCtor::Int(..) 36 Ty::InferenceVar(_, TyVariableKind::Integer)
37 | TypeCtor::Float(..) 37 | Ty::InferenceVar(_, TyVariableKind::Float) => lhs_ty,
38 | TypeCtor::Str
39 | TypeCtor::Char
40 | TypeCtor::Bool => lhs_ty,
41 _ => Ty::Unknown,
42 },
43 Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => lhs_ty,
44 _ => Ty::Unknown, 38 _ => Ty::Unknown,
45 }, 39 },
46 BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => Ty::Unknown, 40 BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => Ty::Unknown,
47 BinaryOp::CmpOp(CmpOp::Ord { .. }) 41 BinaryOp::CmpOp(CmpOp::Ord { .. })
48 | BinaryOp::Assignment { op: Some(_) } 42 | BinaryOp::Assignment { op: Some(_) }
49 | BinaryOp::ArithOp(_) => match lhs_ty { 43 | BinaryOp::ArithOp(_) => match lhs_ty {
50 Ty::Apply(ApplicationTy { ctor, .. }) => match ctor { 44 Ty::Scalar(Scalar::Int(_))
51 TypeCtor::Int(..) | TypeCtor::Float(..) => lhs_ty, 45 | Ty::Scalar(Scalar::Uint(_))
52 _ => Ty::Unknown, 46 | Ty::Scalar(Scalar::Float(_)) => lhs_ty,
53 }, 47 Ty::InferenceVar(_, TyVariableKind::Integer)
54 Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => lhs_ty, 48 | Ty::InferenceVar(_, TyVariableKind::Float) => lhs_ty,
55 _ => Ty::Unknown, 49 _ => Ty::Unknown,
56 }, 50 },
57 } 51 }
diff --git a/crates/hir_ty/src/primitive.rs b/crates/hir_ty/src/primitive.rs
index 37966b709..2449addfb 100644
--- a/crates/hir_ty/src/primitive.rs
+++ b/crates/hir_ty/src/primitive.rs
@@ -3,137 +3,63 @@
3//! * during type inference, they can be uncertain (ie, `let x = 92;`) 3//! * during type inference, they can be uncertain (ie, `let x = 92;`)
4//! * they don't belong to any particular crate. 4//! * they don't belong to any particular crate.
5 5
6use std::fmt; 6pub use chalk_ir::{FloatTy, IntTy, UintTy};
7 7pub use hir_def::builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint};
8pub use hir_def::builtin_type::{BuiltinFloat, BuiltinInt, FloatBitness, IntBitness, Signedness}; 8
9 9pub fn int_ty_to_string(ty: IntTy) -> &'static str {
10#[derive(Copy, Clone, Eq, PartialEq, Hash)] 10 match ty {
11pub struct IntTy { 11 IntTy::Isize => "isize",
12 pub signedness: Signedness, 12 IntTy::I8 => "i8",
13 pub bitness: IntBitness, 13 IntTy::I16 => "i16",
14} 14 IntTy::I32 => "i32",
15 15 IntTy::I64 => "i64",
16impl fmt::Debug for IntTy { 16 IntTy::I128 => "i128",
17 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
18 fmt::Display::fmt(self, f)
19 }
20}
21
22impl fmt::Display for IntTy {
23 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
24 write!(f, "{}", self.ty_to_string())
25 }
26}
27
28impl IntTy {
29 pub fn isize() -> IntTy {
30 IntTy { signedness: Signedness::Signed, bitness: IntBitness::Xsize }
31 }
32
33 pub fn i8() -> IntTy {
34 IntTy { signedness: Signedness::Signed, bitness: IntBitness::X8 }
35 }
36
37 pub fn i16() -> IntTy {
38 IntTy { signedness: Signedness::Signed, bitness: IntBitness::X16 }
39 }
40
41 pub fn i32() -> IntTy {
42 IntTy { signedness: Signedness::Signed, bitness: IntBitness::X32 }
43 }
44
45 pub fn i64() -> IntTy {
46 IntTy { signedness: Signedness::Signed, bitness: IntBitness::X64 }
47 }
48
49 pub fn i128() -> IntTy {
50 IntTy { signedness: Signedness::Signed, bitness: IntBitness::X128 }
51 } 17 }
52
53 pub fn usize() -> IntTy {
54 IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::Xsize }
55 }
56
57 pub fn u8() -> IntTy {
58 IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X8 }
59 }
60
61 pub fn u16() -> IntTy {
62 IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X16 }
63 }
64
65 pub fn u32() -> IntTy {
66 IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X32 }
67 }
68
69 pub fn u64() -> IntTy {
70 IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X64 }
71 }
72
73 pub fn u128() -> IntTy {
74 IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X128 }
75 }
76
77 pub fn ty_to_string(self) -> &'static str {
78 match (self.signedness, self.bitness) {
79 (Signedness::Signed, IntBitness::Xsize) => "isize",
80 (Signedness::Signed, IntBitness::X8) => "i8",
81 (Signedness::Signed, IntBitness::X16) => "i16",
82 (Signedness::Signed, IntBitness::X32) => "i32",
83 (Signedness::Signed, IntBitness::X64) => "i64",
84 (Signedness::Signed, IntBitness::X128) => "i128",
85 (Signedness::Unsigned, IntBitness::Xsize) => "usize",
86 (Signedness::Unsigned, IntBitness::X8) => "u8",
87 (Signedness::Unsigned, IntBitness::X16) => "u16",
88 (Signedness::Unsigned, IntBitness::X32) => "u32",
89 (Signedness::Unsigned, IntBitness::X64) => "u64",
90 (Signedness::Unsigned, IntBitness::X128) => "u128",
91 }
92 }
93}
94
95#[derive(Copy, Clone, PartialEq, Eq, Hash)]
96pub struct FloatTy {
97 pub bitness: FloatBitness,
98} 18}
99 19
100impl fmt::Debug for FloatTy { 20pub fn uint_ty_to_string(ty: UintTy) -> &'static str {
101 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 21 match ty {
102 fmt::Display::fmt(self, f) 22 UintTy::Usize => "usize",
23 UintTy::U8 => "u8",
24 UintTy::U16 => "u16",
25 UintTy::U32 => "u32",
26 UintTy::U64 => "u64",
27 UintTy::U128 => "u128",
103 } 28 }
104} 29}
105 30
106impl fmt::Display for FloatTy { 31pub fn float_ty_to_string(ty: FloatTy) -> &'static str {
107 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 32 match ty {
108 write!(f, "{}", self.ty_to_string()) 33 FloatTy::F32 => "f32",
34 FloatTy::F64 => "f64",
109 } 35 }
110} 36}
111 37
112impl FloatTy { 38pub(super) fn int_ty_from_builtin(t: BuiltinInt) -> IntTy {
113 pub fn f32() -> FloatTy { 39 match t {
114 FloatTy { bitness: FloatBitness::X32 } 40 BuiltinInt::Isize => IntTy::Isize,
115 } 41 BuiltinInt::I8 => IntTy::I8,
116 42 BuiltinInt::I16 => IntTy::I16,
117 pub fn f64() -> FloatTy { 43 BuiltinInt::I32 => IntTy::I32,
118 FloatTy { bitness: FloatBitness::X64 } 44 BuiltinInt::I64 => IntTy::I64,
119 } 45 BuiltinInt::I128 => IntTy::I128,
120
121 pub fn ty_to_string(self) -> &'static str {
122 match self.bitness {
123 FloatBitness::X32 => "f32",
124 FloatBitness::X64 => "f64",
125 }
126 } 46 }
127} 47}
128 48
129impl From<BuiltinInt> for IntTy { 49pub(super) fn uint_ty_from_builtin(t: BuiltinUint) -> UintTy {
130 fn from(t: BuiltinInt) -> Self { 50 match t {
131 IntTy { signedness: t.signedness, bitness: t.bitness } 51 BuiltinUint::Usize => UintTy::Usize,
52 BuiltinUint::U8 => UintTy::U8,
53 BuiltinUint::U16 => UintTy::U16,
54 BuiltinUint::U32 => UintTy::U32,
55 BuiltinUint::U64 => UintTy::U64,
56 BuiltinUint::U128 => UintTy::U128,
132 } 57 }
133} 58}
134 59
135impl From<BuiltinFloat> for FloatTy { 60pub(super) fn float_ty_from_builtin(t: BuiltinFloat) -> FloatTy {
136 fn from(t: BuiltinFloat) -> Self { 61 match t {
137 FloatTy { bitness: t.bitness } 62 BuiltinFloat::F32 => FloatTy::F32,
63 BuiltinFloat::F64 => FloatTy::F64,
138 } 64 }
139} 65}
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs
index 12ec4657b..2947857a5 100644
--- a/crates/hir_ty/src/tests/simple.rs
+++ b/crates/hir_ty/src/tests/simple.rs
@@ -2491,3 +2491,58 @@ fn inner_use_enum_rename() {
2491 "#]], 2491 "#]],
2492 ) 2492 )
2493} 2493}
2494
2495#[test]
2496fn box_into_vec() {
2497 check_infer(
2498 r#"
2499#[lang = "sized"]
2500pub trait Sized {}
2501
2502#[lang = "unsize"]
2503pub trait Unsize<T: ?Sized> {}
2504
2505#[lang = "coerce_unsized"]
2506pub trait CoerceUnsized<T> {}
2507
2508pub unsafe trait Allocator {}
2509
2510pub struct Global;
2511unsafe impl Allocator for Global {}
2512
2513#[lang = "owned_box"]
2514#[fundamental]
2515pub struct Box<T: ?Sized, A: Allocator = Global>;
2516
2517impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Box<U, A>> for Box<T, A> {}
2518
2519pub struct Vec<T, A: Allocator = Global> {}
2520
2521#[lang = "slice"]
2522impl<T> [T] {}
2523
2524#[lang = "slice_alloc"]
2525impl<T> [T] {
2526 pub fn into_vec<A: Allocator>(self: Box<Self, A>) -> Vec<T, A> {
2527 unimplemented!()
2528 }
2529}
2530
2531fn test() {
2532 let vec = <[_]>::into_vec(box [1i32]);
2533}
2534"#,
2535 expect![[r#"
2536 569..573 'self': Box<[T], A>
2537 602..634 '{ ... }': Vec<T, A>
2538 612..628 'unimpl...ted!()': Vec<T, A>
2539 648..694 '{ ...2]); }': ()
2540 658..661 'vec': Vec<i32, Global>
2541 664..679 '<[_]>::into_vec': fn into_vec<i32, Global>(Box<[i32], Global>) -> Vec<i32, Global>
2542 664..691 '<[_]>:...1i32])': Vec<i32, Global>
2543 680..690 'box [1i32]': Box<[i32; _], Global>
2544 684..690 '[1i32]': [i32; _]
2545 685..689 '1i32': i32
2546 "#]],
2547 )
2548}
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs
index dfa51896b..e4cdb6d53 100644
--- a/crates/hir_ty/src/traits.rs
+++ b/crates/hir_ty/src/traits.rs
@@ -129,7 +129,7 @@ pub(crate) fn trait_solve_query(
129 log::info!("trait_solve_query({})", goal.value.value.display(db)); 129 log::info!("trait_solve_query({})", goal.value.value.display(db));
130 130
131 if let Obligation::Projection(pred) = &goal.value.value { 131 if let Obligation::Projection(pred) = &goal.value.value {
132 if let Ty::Bound(_) = &pred.projection_ty.parameters[0] { 132 if let Ty::BoundVar(_) = &pred.projection_ty.parameters[0] {
133 // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible 133 // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible
134 return Some(Solution::Ambig(Guidance::Unknown)); 134 return Some(Solution::Ambig(Guidance::Unknown));
135 } 135 }
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs
index d74c83737..e513fa8f4 100644
--- a/crates/hir_ty/src/traits/chalk.rs
+++ b/crates/hir_ty/src/traits/chalk.rs
@@ -19,8 +19,8 @@ use crate::{
19 display::HirDisplay, 19 display::HirDisplay,
20 method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, 20 method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
21 utils::generics, 21 utils::generics,
22 BoundVar, CallableDefId, DebruijnIndex, FnSig, GenericPredicate, ProjectionPredicate, 22 BoundVar, CallableDefId, CallableSig, DebruijnIndex, GenericPredicate, ProjectionPredicate,
23 ProjectionTy, Substs, TraitRef, Ty, TypeCtor, 23 ProjectionTy, Substs, TraitRef, Ty,
24}; 24};
25use mapping::{ 25use mapping::{
26 convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsAssocType, 26 convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsAssocType,
@@ -90,7 +90,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
90 ty: &Ty, 90 ty: &Ty,
91 binders: &CanonicalVarKinds<Interner>, 91 binders: &CanonicalVarKinds<Interner>,
92 ) -> Option<chalk_ir::TyVariableKind> { 92 ) -> Option<chalk_ir::TyVariableKind> {
93 if let Ty::Bound(bv) = ty { 93 if let Ty::BoundVar(bv) = ty {
94 let binders = binders.as_slice(&Interner); 94 let binders = binders.as_slice(&Interner);
95 if bv.debruijn == DebruijnIndex::INNERMOST { 95 if bv.debruijn == DebruijnIndex::INNERMOST {
96 if let chalk_ir::VariableKind::Ty(tk) = binders[bv.index].kind { 96 if let chalk_ir::VariableKind::Ty(tk) = binders[bv.index].kind {
@@ -220,18 +220,18 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
220 let impl_bound = GenericPredicate::Implemented(TraitRef { 220 let impl_bound = GenericPredicate::Implemented(TraitRef {
221 trait_: future_trait, 221 trait_: future_trait,
222 // Self type as the first parameter. 222 // Self type as the first parameter.
223 substs: Substs::single(Ty::Bound(BoundVar { 223 substs: Substs::single(Ty::BoundVar(BoundVar {
224 debruijn: DebruijnIndex::INNERMOST, 224 debruijn: DebruijnIndex::INNERMOST,
225 index: 0, 225 index: 0,
226 })), 226 })),
227 }); 227 });
228 let proj_bound = GenericPredicate::Projection(ProjectionPredicate { 228 let proj_bound = GenericPredicate::Projection(ProjectionPredicate {
229 // The parameter of the opaque type. 229 // The parameter of the opaque type.
230 ty: Ty::Bound(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 }), 230 ty: Ty::BoundVar(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 }),
231 projection_ty: ProjectionTy { 231 projection_ty: ProjectionTy {
232 associated_ty: future_output, 232 associated_ty: future_output,
233 // Self type as the first parameter. 233 // Self type as the first parameter.
234 parameters: Substs::single(Ty::Bound(BoundVar::new( 234 parameters: Substs::single(Ty::BoundVar(BoundVar::new(
235 DebruijnIndex::INNERMOST, 235 DebruijnIndex::INNERMOST,
236 0, 236 0,
237 ))), 237 ))),
@@ -286,9 +286,8 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
286 ) -> chalk_ir::Binders<rust_ir::FnDefInputsAndOutputDatum<Interner>> { 286 ) -> chalk_ir::Binders<rust_ir::FnDefInputsAndOutputDatum<Interner>> {
287 let sig_ty: Ty = 287 let sig_ty: Ty =
288 from_chalk(self.db, substs.at(&Interner, 0).assert_ty_ref(&Interner).clone()); 288 from_chalk(self.db, substs.at(&Interner, 0).assert_ty_ref(&Interner).clone());
289 let sig = FnSig::from_fn_ptr_substs( 289 let sig = CallableSig::from_substs(
290 &sig_ty.substs().expect("first closure param should be fn ptr"), 290 &sig_ty.substs().expect("first closure param should be fn ptr"),
291 false,
292 ); 291 );
293 let io = rust_ir::FnDefInputsAndOutputDatum { 292 let io = rust_ir::FnDefInputsAndOutputDatum {
294 argument_types: sig.params().iter().map(|ty| ty.clone().to_chalk(self.db)).collect(), 293 argument_types: sig.params().iter().map(|ty| ty.clone().to_chalk(self.db)).collect(),
@@ -393,7 +392,7 @@ pub(crate) fn associated_ty_data_query(
393 let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db.upcast()); 392 let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db.upcast());
394 let ctx = crate::TyLoweringContext::new(db, &resolver) 393 let ctx = crate::TyLoweringContext::new(db, &resolver)
395 .with_type_param_mode(crate::lower::TypeParamLoweringMode::Variable); 394 .with_type_param_mode(crate::lower::TypeParamLoweringMode::Variable);
396 let self_ty = Ty::Bound(crate::BoundVar::new(crate::DebruijnIndex::INNERMOST, 0)); 395 let self_ty = Ty::BoundVar(crate::BoundVar::new(crate::DebruijnIndex::INNERMOST, 0));
397 let bounds = type_alias_data 396 let bounds = type_alias_data
398 .bounds 397 .bounds
399 .iter() 398 .iter()
@@ -489,10 +488,11 @@ pub(crate) fn struct_datum_query(
489 struct_id: AdtId, 488 struct_id: AdtId,
490) -> Arc<StructDatum> { 489) -> Arc<StructDatum> {
491 debug!("struct_datum {:?}", struct_id); 490 debug!("struct_datum {:?}", struct_id);
492 let type_ctor = TypeCtor::Adt(from_chalk(db, struct_id)); 491 let adt_id = from_chalk(db, struct_id);
492 let type_ctor = Ty::Adt(adt_id, Substs::empty());
493 debug!("struct {:?} = {:?}", struct_id, type_ctor); 493 debug!("struct {:?} = {:?}", struct_id, type_ctor);
494 let num_params = type_ctor.num_ty_params(db); 494 let num_params = generics(db.upcast(), adt_id.into()).len();
495 let upstream = type_ctor.krate(db) != Some(krate); 495 let upstream = adt_id.module(db.upcast()).krate() != krate;
496 let where_clauses = type_ctor 496 let where_clauses = type_ctor
497 .as_generic_def() 497 .as_generic_def()
498 .map(|generic_def| { 498 .map(|generic_def| {
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs
index 8700d664e..db1760e6c 100644
--- a/crates/hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/hir_ty/src/traits/chalk/mapping.rs
@@ -4,20 +4,20 @@
4//! conversions. 4//! conversions.
5 5
6use chalk_ir::{ 6use chalk_ir::{
7 cast::Cast, fold::shift::Shift, interner::HasInterner, LifetimeData, PlaceholderIndex, Scalar, 7 cast::Cast, fold::shift::Shift, interner::HasInterner, LifetimeData, PlaceholderIndex,
8 UniverseIndex, 8 UniverseIndex,
9}; 9};
10use chalk_solve::rust_ir; 10use chalk_solve::rust_ir;
11 11
12use base_db::salsa::InternKey; 12use base_db::salsa::InternKey;
13use hir_def::{type_ref::Mutability, AssocContainerId, GenericDefId, Lookup, TypeAliasId}; 13use hir_def::{AssocContainerId, GenericDefId, Lookup, TypeAliasId};
14 14
15use crate::{ 15use crate::{
16 db::HirDatabase, 16 db::HirDatabase,
17 primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness}, 17 primitive::UintTy,
18 traits::{Canonical, Obligation}, 18 traits::{Canonical, Obligation},
19 ApplicationTy, CallableDefId, GenericPredicate, InEnvironment, OpaqueTy, OpaqueTyId, 19 AliasTy, CallableDefId, FnPointer, FnSig, GenericPredicate, InEnvironment, OpaqueTy,
20 ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TyKind, TypeCtor, 20 OpaqueTyId, ProjectionPredicate, ProjectionTy, Scalar, Substs, TraitEnvironment, TraitRef, Ty,
21}; 21};
22 22
23use super::interner::*; 23use super::interner::*;
@@ -27,88 +27,68 @@ impl ToChalk for Ty {
27 type Chalk = chalk_ir::Ty<Interner>; 27 type Chalk = chalk_ir::Ty<Interner>;
28 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> { 28 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> {
29 match self { 29 match self {
30 Ty::Apply(apply_ty) => match apply_ty.ctor { 30 Ty::Ref(m, parameters) => ref_to_chalk(db, m, parameters),
31 TypeCtor::Ref(m) => ref_to_chalk(db, m, apply_ty.parameters), 31 Ty::Array(parameters) => array_to_chalk(db, parameters),
32 TypeCtor::Array => array_to_chalk(db, apply_ty.parameters), 32 Ty::Function(FnPointer { sig: FnSig { variadic }, substs, .. }) => {
33 TypeCtor::FnPtr { num_args: _, is_varargs } => { 33 let substitution = chalk_ir::FnSubst(substs.to_chalk(db).shifted_in(&Interner));
34 let substitution = 34 chalk_ir::TyKind::Function(chalk_ir::FnPointer {
35 chalk_ir::FnSubst(apply_ty.parameters.to_chalk(db).shifted_in(&Interner)); 35 num_binders: 0,
36 chalk_ir::TyKind::Function(chalk_ir::FnPointer { 36 sig: chalk_ir::FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic },
37 num_binders: 0, 37 substitution,
38 sig: chalk_ir::FnSig { 38 })
39 abi: (), 39 .intern(&Interner)
40 safety: chalk_ir::Safety::Safe, 40 }
41 variadic: is_varargs, 41 Ty::AssociatedType(type_alias, substs) => {
42 }, 42 let assoc_type = TypeAliasAsAssocType(type_alias);
43 substitution, 43 let assoc_type_id = assoc_type.to_chalk(db);
44 }) 44 let substitution = substs.to_chalk(db);
45 .intern(&Interner) 45 chalk_ir::TyKind::AssociatedType(assoc_type_id, substitution).intern(&Interner)
46 } 46 }
47 TypeCtor::AssociatedType(type_alias) => {
48 let assoc_type = TypeAliasAsAssocType(type_alias);
49 let assoc_type_id = assoc_type.to_chalk(db);
50 let substitution = apply_ty.parameters.to_chalk(db);
51 chalk_ir::TyKind::AssociatedType(assoc_type_id, substitution).intern(&Interner)
52 }
53 47
54 TypeCtor::OpaqueType(impl_trait_id) => { 48 Ty::OpaqueType(impl_trait_id, substs) => {
55 let id = impl_trait_id.to_chalk(db); 49 let id = impl_trait_id.to_chalk(db);
56 let substitution = apply_ty.parameters.to_chalk(db); 50 let substitution = substs.to_chalk(db);
57 chalk_ir::TyKind::OpaqueType(id, substitution).intern(&Interner) 51 chalk_ir::TyKind::OpaqueType(id, substitution).intern(&Interner)
58 } 52 }
59 53
60 TypeCtor::ForeignType(type_alias) => { 54 Ty::ForeignType(type_alias) => {
61 let foreign_type = TypeAliasAsForeignType(type_alias); 55 let foreign_type = TypeAliasAsForeignType(type_alias);
62 let foreign_type_id = foreign_type.to_chalk(db); 56 let foreign_type_id = foreign_type.to_chalk(db);
63 chalk_ir::TyKind::Foreign(foreign_type_id).intern(&Interner) 57 chalk_ir::TyKind::Foreign(foreign_type_id).intern(&Interner)
64 } 58 }
65 59
66 TypeCtor::Bool => chalk_ir::TyKind::Scalar(Scalar::Bool).intern(&Interner), 60 Ty::Scalar(scalar) => chalk_ir::TyKind::Scalar(scalar).intern(&Interner),
67 TypeCtor::Char => chalk_ir::TyKind::Scalar(Scalar::Char).intern(&Interner),
68 TypeCtor::Int(int_ty) => {
69 chalk_ir::TyKind::Scalar(int_ty_to_chalk(int_ty)).intern(&Interner)
70 }
71 TypeCtor::Float(FloatTy { bitness: FloatBitness::X32 }) => {
72 chalk_ir::TyKind::Scalar(Scalar::Float(chalk_ir::FloatTy::F32))
73 .intern(&Interner)
74 }
75 TypeCtor::Float(FloatTy { bitness: FloatBitness::X64 }) => {
76 chalk_ir::TyKind::Scalar(Scalar::Float(chalk_ir::FloatTy::F64))
77 .intern(&Interner)
78 }
79 61
80 TypeCtor::Tuple { cardinality } => { 62 Ty::Tuple(cardinality, substs) => {
81 let substitution = apply_ty.parameters.to_chalk(db); 63 let substitution = substs.to_chalk(db);
82 chalk_ir::TyKind::Tuple(cardinality.into(), substitution).intern(&Interner) 64 chalk_ir::TyKind::Tuple(cardinality.into(), substitution).intern(&Interner)
83 } 65 }
84 TypeCtor::RawPtr(mutability) => { 66 Ty::Raw(mutability, substs) => {
85 let ty = apply_ty.parameters[0].clone().to_chalk(db); 67 let ty = substs[0].clone().to_chalk(db);
86 chalk_ir::TyKind::Raw(mutability.to_chalk(db), ty).intern(&Interner) 68 chalk_ir::TyKind::Raw(mutability, ty).intern(&Interner)
87 } 69 }
88 TypeCtor::Slice => { 70 Ty::Slice(substs) => {
89 chalk_ir::TyKind::Slice(apply_ty.parameters[0].clone().to_chalk(db)) 71 chalk_ir::TyKind::Slice(substs[0].clone().to_chalk(db)).intern(&Interner)
90 .intern(&Interner) 72 }
91 } 73 Ty::Str => chalk_ir::TyKind::Str.intern(&Interner),
92 TypeCtor::Str => chalk_ir::TyKind::Str.intern(&Interner), 74 Ty::FnDef(callable_def, substs) => {
93 TypeCtor::FnDef(callable_def) => { 75 let id = callable_def.to_chalk(db);
94 let id = callable_def.to_chalk(db); 76 let substitution = substs.to_chalk(db);
95 let substitution = apply_ty.parameters.to_chalk(db); 77 chalk_ir::TyKind::FnDef(id, substitution).intern(&Interner)
96 chalk_ir::TyKind::FnDef(id, substitution).intern(&Interner) 78 }
97 } 79 Ty::Never => chalk_ir::TyKind::Never.intern(&Interner),
98 TypeCtor::Never => chalk_ir::TyKind::Never.intern(&Interner),
99 80
100 TypeCtor::Closure { def, expr } => { 81 Ty::Closure(def, expr, substs) => {
101 let closure_id = db.intern_closure((def, expr)); 82 let closure_id = db.intern_closure((def, expr));
102 let substitution = apply_ty.parameters.to_chalk(db); 83 let substitution = substs.to_chalk(db);
103 chalk_ir::TyKind::Closure(closure_id.into(), substitution).intern(&Interner) 84 chalk_ir::TyKind::Closure(closure_id.into(), substitution).intern(&Interner)
104 } 85 }
105 86
106 TypeCtor::Adt(adt_id) => { 87 Ty::Adt(adt_id, substs) => {
107 let substitution = apply_ty.parameters.to_chalk(db); 88 let substitution = substs.to_chalk(db);
108 chalk_ir::TyKind::Adt(chalk_ir::AdtId(adt_id), substitution).intern(&Interner) 89 chalk_ir::TyKind::Adt(chalk_ir::AdtId(adt_id), substitution).intern(&Interner)
109 } 90 }
110 }, 91 Ty::Alias(AliasTy::Projection(proj_ty)) => {
111 Ty::Projection(proj_ty) => {
112 let associated_ty_id = TypeAliasAsAssocType(proj_ty.associated_ty).to_chalk(db); 92 let associated_ty_id = TypeAliasAsAssocType(proj_ty.associated_ty).to_chalk(db);
113 let substitution = proj_ty.parameters.to_chalk(db); 93 let substitution = proj_ty.parameters.to_chalk(db);
114 chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy { 94 chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
@@ -126,8 +106,8 @@ impl ToChalk for Ty {
126 } 106 }
127 .to_ty::<Interner>(&Interner) 107 .to_ty::<Interner>(&Interner)
128 } 108 }
129 Ty::Bound(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner), 109 Ty::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner),
130 Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), 110 Ty::InferenceVar(..) => panic!("uncanonicalized infer ty"),
131 Ty::Dyn(predicates) => { 111 Ty::Dyn(predicates) => {
132 let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter( 112 let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter(
133 &Interner, 113 &Interner,
@@ -139,7 +119,7 @@ impl ToChalk for Ty {
139 }; 119 };
140 chalk_ir::TyKind::Dyn(bounded_ty).intern(&Interner) 120 chalk_ir::TyKind::Dyn(bounded_ty).intern(&Interner)
141 } 121 }
142 Ty::Opaque(opaque_ty) => { 122 Ty::Alias(AliasTy::Opaque(opaque_ty)) => {
143 let opaque_ty_id = opaque_ty.opaque_ty_id.to_chalk(db); 123 let opaque_ty_id = opaque_ty.opaque_ty_id.to_chalk(db);
144 let substitution = opaque_ty.parameters.to_chalk(db); 124 let substitution = opaque_ty.parameters.to_chalk(db);
145 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy { 125 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy {
@@ -154,9 +134,7 @@ impl ToChalk for Ty {
154 fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self { 134 fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self {
155 match chalk.data(&Interner).kind.clone() { 135 match chalk.data(&Interner).kind.clone() {
156 chalk_ir::TyKind::Error => Ty::Unknown, 136 chalk_ir::TyKind::Error => Ty::Unknown,
157 chalk_ir::TyKind::Array(ty, _size) => { 137 chalk_ir::TyKind::Array(ty, _size) => Ty::Array(Substs::single(from_chalk(db, ty))),
158 Ty::apply(TypeCtor::Array, Substs::single(from_chalk(db, ty)))
159 }
160 chalk_ir::TyKind::Placeholder(idx) => { 138 chalk_ir::TyKind::Placeholder(idx) => {
161 assert_eq!(idx.ui, UniverseIndex::ROOT); 139 assert_eq!(idx.ui, UniverseIndex::ROOT);
162 let interned_id = crate::db::GlobalTypeParamId::from_intern_id( 140 let interned_id = crate::db::GlobalTypeParamId::from_intern_id(
@@ -168,12 +146,12 @@ impl ToChalk for Ty {
168 let associated_ty = 146 let associated_ty =
169 from_chalk::<TypeAliasAsAssocType, _>(db, proj.associated_ty_id).0; 147 from_chalk::<TypeAliasAsAssocType, _>(db, proj.associated_ty_id).0;
170 let parameters = from_chalk(db, proj.substitution); 148 let parameters = from_chalk(db, proj.substitution);
171 Ty::Projection(ProjectionTy { associated_ty, parameters }) 149 Ty::Alias(AliasTy::Projection(ProjectionTy { associated_ty, parameters }))
172 } 150 }
173 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(opaque_ty)) => { 151 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(opaque_ty)) => {
174 let impl_trait_id = from_chalk(db, opaque_ty.opaque_ty_id); 152 let impl_trait_id = from_chalk(db, opaque_ty.opaque_ty_id);
175 let parameters = from_chalk(db, opaque_ty.substitution); 153 let parameters = from_chalk(db, opaque_ty.substitution);
176 Ty::Opaque(OpaqueTy { opaque_ty_id: impl_trait_id, parameters }) 154 Ty::Alias(AliasTy::Opaque(OpaqueTy { opaque_ty_id: impl_trait_id, parameters }))
177 } 155 }
178 chalk_ir::TyKind::Function(chalk_ir::FnPointer { 156 chalk_ir::TyKind::Function(chalk_ir::FnPointer {
179 num_binders, 157 num_binders,
@@ -182,19 +160,17 @@ impl ToChalk for Ty {
182 .. 160 ..
183 }) => { 161 }) => {
184 assert_eq!(num_binders, 0); 162 assert_eq!(num_binders, 0);
185 let parameters: Substs = from_chalk( 163 let substs: Substs = from_chalk(
186 db, 164 db,
187 substitution.0.shifted_out(&Interner).expect("fn ptr should have no binders"), 165 substitution.0.shifted_out(&Interner).expect("fn ptr should have no binders"),
188 ); 166 );
189 Ty::Apply(ApplicationTy { 167 Ty::Function(FnPointer {
190 ctor: TypeCtor::FnPtr { 168 num_args: (substs.len() - 1),
191 num_args: (parameters.len() - 1) as u16, 169 sig: FnSig { variadic },
192 is_varargs: variadic, 170 substs,
193 },
194 parameters,
195 }) 171 })
196 } 172 }
197 chalk_ir::TyKind::BoundVar(idx) => Ty::Bound(idx), 173 chalk_ir::TyKind::BoundVar(idx) => Ty::BoundVar(idx),
198 chalk_ir::TyKind::InferenceVar(_iv, _kind) => Ty::Unknown, 174 chalk_ir::TyKind::InferenceVar(_iv, _kind) => Ty::Unknown,
199 chalk_ir::TyKind::Dyn(where_clauses) => { 175 chalk_ir::TyKind::Dyn(where_clauses) => {
200 assert_eq!(where_clauses.bounds.binders.len(&Interner), 1); 176 assert_eq!(where_clauses.bounds.binders.len(&Interner), 1);
@@ -207,93 +183,66 @@ impl ToChalk for Ty {
207 Ty::Dyn(predicates) 183 Ty::Dyn(predicates)
208 } 184 }
209 185
210 chalk_ir::TyKind::Adt(struct_id, subst) => { 186 chalk_ir::TyKind::Adt(struct_id, subst) => Ty::Adt(struct_id.0, from_chalk(db, subst)),
211 apply_ty_from_chalk(db, TypeCtor::Adt(struct_id.0), subst) 187 chalk_ir::TyKind::AssociatedType(type_id, subst) => Ty::AssociatedType(
212 } 188 from_chalk::<TypeAliasAsAssocType, _>(db, type_id).0,
213 chalk_ir::TyKind::AssociatedType(type_id, subst) => apply_ty_from_chalk( 189 from_chalk(db, subst),
214 db,
215 TypeCtor::AssociatedType(from_chalk::<TypeAliasAsAssocType, _>(db, type_id).0),
216 subst,
217 ), 190 ),
191
218 chalk_ir::TyKind::OpaqueType(opaque_type_id, subst) => { 192 chalk_ir::TyKind::OpaqueType(opaque_type_id, subst) => {
219 apply_ty_from_chalk(db, TypeCtor::OpaqueType(from_chalk(db, opaque_type_id)), subst) 193 Ty::OpaqueType(from_chalk(db, opaque_type_id), from_chalk(db, subst))
220 } 194 }
221 195
222 chalk_ir::TyKind::Scalar(Scalar::Bool) => Ty::simple(TypeCtor::Bool), 196 chalk_ir::TyKind::Scalar(scalar) => Ty::Scalar(scalar),
223 chalk_ir::TyKind::Scalar(Scalar::Char) => Ty::simple(TypeCtor::Char),
224 chalk_ir::TyKind::Scalar(Scalar::Int(int_ty)) => Ty::simple(TypeCtor::Int(IntTy {
225 signedness: Signedness::Signed,
226 bitness: bitness_from_chalk_int(int_ty),
227 })),
228 chalk_ir::TyKind::Scalar(Scalar::Uint(uint_ty)) => Ty::simple(TypeCtor::Int(IntTy {
229 signedness: Signedness::Unsigned,
230 bitness: bitness_from_chalk_uint(uint_ty),
231 })),
232 chalk_ir::TyKind::Scalar(Scalar::Float(chalk_ir::FloatTy::F32)) => {
233 Ty::simple(TypeCtor::Float(FloatTy { bitness: FloatBitness::X32 }))
234 }
235 chalk_ir::TyKind::Scalar(Scalar::Float(chalk_ir::FloatTy::F64)) => {
236 Ty::simple(TypeCtor::Float(FloatTy { bitness: FloatBitness::X64 }))
237 }
238 chalk_ir::TyKind::Tuple(cardinality, subst) => { 197 chalk_ir::TyKind::Tuple(cardinality, subst) => {
239 apply_ty_from_chalk(db, TypeCtor::Tuple { cardinality: cardinality as u16 }, subst) 198 Ty::Tuple(cardinality, from_chalk(db, subst))
240 } 199 }
241 chalk_ir::TyKind::Raw(mutability, ty) => { 200 chalk_ir::TyKind::Raw(mutability, ty) => {
242 Ty::apply_one(TypeCtor::RawPtr(from_chalk(db, mutability)), from_chalk(db, ty)) 201 Ty::Raw(mutability, Substs::single(from_chalk(db, ty)))
243 } 202 }
244 chalk_ir::TyKind::Slice(ty) => Ty::apply_one(TypeCtor::Slice, from_chalk(db, ty)), 203 chalk_ir::TyKind::Slice(ty) => Ty::Slice(Substs::single(from_chalk(db, ty))),
245 chalk_ir::TyKind::Ref(mutability, _lifetime, ty) => { 204 chalk_ir::TyKind::Ref(mutability, _lifetime, ty) => {
246 Ty::apply_one(TypeCtor::Ref(from_chalk(db, mutability)), from_chalk(db, ty)) 205 Ty::Ref(mutability, Substs::single(from_chalk(db, ty)))
247 } 206 }
248 chalk_ir::TyKind::Str => Ty::simple(TypeCtor::Str), 207 chalk_ir::TyKind::Str => Ty::Str,
249 chalk_ir::TyKind::Never => Ty::simple(TypeCtor::Never), 208 chalk_ir::TyKind::Never => Ty::Never,
250 209
251 chalk_ir::TyKind::FnDef(fn_def_id, subst) => { 210 chalk_ir::TyKind::FnDef(fn_def_id, subst) => {
252 let callable_def = from_chalk(db, fn_def_id); 211 Ty::FnDef(from_chalk(db, fn_def_id), from_chalk(db, subst))
253 apply_ty_from_chalk(db, TypeCtor::FnDef(callable_def), subst)
254 } 212 }
255 213
256 chalk_ir::TyKind::Closure(id, subst) => { 214 chalk_ir::TyKind::Closure(id, subst) => {
257 let id: crate::db::ClosureId = id.into(); 215 let id: crate::db::ClosureId = id.into();
258 let (def, expr) = db.lookup_intern_closure(id); 216 let (def, expr) = db.lookup_intern_closure(id);
259 apply_ty_from_chalk(db, TypeCtor::Closure { def, expr }, subst) 217 Ty::Closure(def, expr, from_chalk(db, subst))
260 } 218 }
261 219
262 chalk_ir::TyKind::Foreign(foreign_def_id) => Ty::simple(TypeCtor::ForeignType( 220 chalk_ir::TyKind::Foreign(foreign_def_id) => {
263 from_chalk::<TypeAliasAsForeignType, _>(db, foreign_def_id).0, 221 Ty::ForeignType(from_chalk::<TypeAliasAsForeignType, _>(db, foreign_def_id).0)
264 )), 222 }
265 chalk_ir::TyKind::Generator(_, _) => unimplemented!(), // FIXME 223 chalk_ir::TyKind::Generator(_, _) => unimplemented!(), // FIXME
266 chalk_ir::TyKind::GeneratorWitness(_, _) => unimplemented!(), // FIXME 224 chalk_ir::TyKind::GeneratorWitness(_, _) => unimplemented!(), // FIXME
267 } 225 }
268 } 226 }
269} 227}
270 228
271fn apply_ty_from_chalk(
272 db: &dyn HirDatabase,
273 ctor: TypeCtor,
274 subst: chalk_ir::Substitution<Interner>,
275) -> Ty {
276 Ty::Apply(ApplicationTy { ctor, parameters: from_chalk(db, subst) })
277}
278
279/// We currently don't model lifetimes, but Chalk does. So, we have to insert a 229/// We currently don't model lifetimes, but Chalk does. So, we have to insert a
280/// fake lifetime here, because Chalks built-in logic may expect it to be there. 230/// fake lifetime here, because Chalks built-in logic may expect it to be there.
281fn ref_to_chalk( 231fn ref_to_chalk(
282 db: &dyn HirDatabase, 232 db: &dyn HirDatabase,
283 mutability: Mutability, 233 mutability: chalk_ir::Mutability,
284 subst: Substs, 234 subst: Substs,
285) -> chalk_ir::Ty<Interner> { 235) -> chalk_ir::Ty<Interner> {
286 let arg = subst[0].clone().to_chalk(db); 236 let arg = subst[0].clone().to_chalk(db);
287 let lifetime = LifetimeData::Static.intern(&Interner); 237 let lifetime = LifetimeData::Static.intern(&Interner);
288 chalk_ir::TyKind::Ref(mutability.to_chalk(db), lifetime, arg).intern(&Interner) 238 chalk_ir::TyKind::Ref(mutability, lifetime, arg).intern(&Interner)
289} 239}
290 240
291/// We currently don't model constants, but Chalk does. So, we have to insert a 241/// We currently don't model constants, but Chalk does. So, we have to insert a
292/// fake constant here, because Chalks built-in logic may expect it to be there. 242/// fake constant here, because Chalks built-in logic may expect it to be there.
293fn array_to_chalk(db: &dyn HirDatabase, subst: Substs) -> chalk_ir::Ty<Interner> { 243fn array_to_chalk(db: &dyn HirDatabase, subst: Substs) -> chalk_ir::Ty<Interner> {
294 let arg = subst[0].clone().to_chalk(db); 244 let arg = subst[0].clone().to_chalk(db);
295 let usize_ty = 245 let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner);
296 chalk_ir::TyKind::Scalar(Scalar::Uint(chalk_ir::UintTy::Usize)).intern(&Interner);
297 let const_ = chalk_ir::ConstData { 246 let const_ = chalk_ir::ConstData {
298 ty: usize_ty, 247 ty: usize_ty,
299 value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { interned: () }), 248 value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { interned: () }),
@@ -364,71 +313,6 @@ impl ToChalk for OpaqueTyId {
364 } 313 }
365} 314}
366 315
367fn bitness_from_chalk_uint(uint_ty: chalk_ir::UintTy) -> IntBitness {
368 use chalk_ir::UintTy;
369
370 match uint_ty {
371 UintTy::Usize => IntBitness::Xsize,
372 UintTy::U8 => IntBitness::X8,
373 UintTy::U16 => IntBitness::X16,
374 UintTy::U32 => IntBitness::X32,
375 UintTy::U64 => IntBitness::X64,
376 UintTy::U128 => IntBitness::X128,
377 }
378}
379
380fn bitness_from_chalk_int(int_ty: chalk_ir::IntTy) -> IntBitness {
381 use chalk_ir::IntTy;
382
383 match int_ty {
384 IntTy::Isize => IntBitness::Xsize,
385 IntTy::I8 => IntBitness::X8,
386 IntTy::I16 => IntBitness::X16,
387 IntTy::I32 => IntBitness::X32,
388 IntTy::I64 => IntBitness::X64,
389 IntTy::I128 => IntBitness::X128,
390 }
391}
392
393fn int_ty_to_chalk(int_ty: IntTy) -> Scalar {
394 use chalk_ir::{IntTy, UintTy};
395
396 match int_ty.signedness {
397 Signedness::Signed => Scalar::Int(match int_ty.bitness {
398 IntBitness::Xsize => IntTy::Isize,
399 IntBitness::X8 => IntTy::I8,
400 IntBitness::X16 => IntTy::I16,
401 IntBitness::X32 => IntTy::I32,
402 IntBitness::X64 => IntTy::I64,
403 IntBitness::X128 => IntTy::I128,
404 }),
405 Signedness::Unsigned => Scalar::Uint(match int_ty.bitness {
406 IntBitness::Xsize => UintTy::Usize,
407 IntBitness::X8 => UintTy::U8,
408 IntBitness::X16 => UintTy::U16,
409 IntBitness::X32 => UintTy::U32,
410 IntBitness::X64 => UintTy::U64,
411 IntBitness::X128 => UintTy::U128,
412 }),
413 }
414}
415
416impl ToChalk for Mutability {
417 type Chalk = chalk_ir::Mutability;
418 fn to_chalk(self, _db: &dyn HirDatabase) -> Self::Chalk {
419 match self {
420 Mutability::Shared => chalk_ir::Mutability::Not,
421 Mutability::Mut => chalk_ir::Mutability::Mut,
422 }
423 }
424 fn from_chalk(_db: &dyn HirDatabase, chalk: Self::Chalk) -> Self {
425 match chalk {
426 chalk_ir::Mutability::Mut => Mutability::Mut,
427 chalk_ir::Mutability::Not => Mutability::Shared,
428 }
429 }
430}
431
432impl ToChalk for hir_def::ImplId { 316impl ToChalk for hir_def::ImplId {
433 type Chalk = ImplId; 317 type Chalk = ImplId;
434 318
@@ -632,20 +516,12 @@ where
632 type Chalk = chalk_ir::Canonical<T::Chalk>; 516 type Chalk = chalk_ir::Canonical<T::Chalk>;
633 517
634 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> { 518 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> {
635 let kinds = self 519 let kinds = self.kinds.iter().map(|&tk| {
636 .kinds 520 chalk_ir::CanonicalVarKind::new(
637 .iter() 521 chalk_ir::VariableKind::Ty(tk),
638 .map(|k| match k { 522 chalk_ir::UniverseIndex::ROOT,
639 TyKind::General => chalk_ir::TyVariableKind::General, 523 )
640 TyKind::Integer => chalk_ir::TyVariableKind::Integer, 524 });
641 TyKind::Float => chalk_ir::TyVariableKind::Float,
642 })
643 .map(|tk| {
644 chalk_ir::CanonicalVarKind::new(
645 chalk_ir::VariableKind::Ty(tk),
646 chalk_ir::UniverseIndex::ROOT,
647 )
648 });
649 let value = self.value.to_chalk(db); 525 let value = self.value.to_chalk(db);
650 chalk_ir::Canonical { 526 chalk_ir::Canonical {
651 value, 527 value,
@@ -658,17 +534,13 @@ where
658 .binders 534 .binders
659 .iter(&Interner) 535 .iter(&Interner)
660 .map(|k| match k.kind { 536 .map(|k| match k.kind {
661 chalk_ir::VariableKind::Ty(tk) => match tk { 537 chalk_ir::VariableKind::Ty(tk) => tk,
662 chalk_ir::TyVariableKind::General => TyKind::General,
663 chalk_ir::TyVariableKind::Integer => TyKind::Integer,
664 chalk_ir::TyVariableKind::Float => TyKind::Float,
665 },
666 // HACK: Chalk can sometimes return new lifetime variables. We 538 // HACK: Chalk can sometimes return new lifetime variables. We
667 // want to just skip them, but to not mess up the indices of 539 // want to just skip them, but to not mess up the indices of
668 // other variables, we'll just create a new type variable in 540 // other variables, we'll just create a new type variable in
669 // their place instead. This should not matter (we never see the 541 // their place instead. This should not matter (we never see the
670 // actual *uses* of the lifetime variable). 542 // actual *uses* of the lifetime variable).
671 chalk_ir::VariableKind::Lifetime => TyKind::General, 543 chalk_ir::VariableKind::Lifetime => chalk_ir::TyVariableKind::General,
672 chalk_ir::VariableKind::Const(_) => panic!("unexpected const from Chalk"), 544 chalk_ir::VariableKind::Const(_) => panic!("unexpected const from Chalk"),
673 }) 545 })
674 .collect(); 546 .collect();
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 9a605b09d..20b799490 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -3496,4 +3496,33 @@ mod foo$0;
3496 "#]], 3496 "#]],
3497 ); 3497 );
3498 } 3498 }
3499
3500 #[test]
3501 fn hover_self_in_use() {
3502 check(
3503 r#"
3504//! This should not appear
3505mod foo {
3506 /// But this should appear
3507 pub mod bar {}
3508}
3509use foo::bar::{self$0};
3510"#,
3511 expect![[r#"
3512 *self*
3513
3514 ```rust
3515 test::foo
3516 ```
3517
3518 ```rust
3519 pub mod bar
3520 ```
3521
3522 ---
3523
3524 But this should appear
3525 "#]],
3526 );
3527 }
3499} 3528}
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index 5d0449e56..fef70533d 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -39,6 +39,15 @@ pub struct Declaration {
39 pub access: Option<ReferenceAccess>, 39 pub access: Option<ReferenceAccess>,
40} 40}
41 41
42// Feature: Find All References
43//
44// Shows all references of the item at the cursor location
45//
46// |===
47// | Editor | Shortcut
48//
49// | VS Code | kbd:[Shift+Alt+F12]
50// |===
42pub(crate) fn find_all_refs( 51pub(crate) fn find_all_refs(
43 sema: &Semantics<RootDatabase>, 52 sema: &Semantics<RootDatabase>,
44 position: FilePosition, 53 position: FilePosition,
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs
index 175ddd759..22ddeeae3 100644
--- a/crates/ide/src/references/rename.rs
+++ b/crates/ide/src/references/rename.rs
@@ -59,6 +59,15 @@ pub(crate) fn prepare_rename(
59 Ok(RangeInfo::new(range, ())) 59 Ok(RangeInfo::new(range, ()))
60} 60}
61 61
62// Feature: Rename
63//
64// Renames the item below the cursor and all of its references
65//
66// |===
67// | Editor | Shortcut
68//
69// | VS Code | kbd:[F2]
70// |===
62pub(crate) fn rename( 71pub(crate) fn rename(
63 db: &RootDatabase, 72 db: &RootDatabase,
64 position: FilePosition, 73 position: FilePosition,
diff --git a/crates/ide_assists/src/handlers/convert_comment_block.rs b/crates/ide_assists/src/handlers/convert_comment_block.rs
new file mode 100644
index 000000000..cdc45fc42
--- /dev/null
+++ b/crates/ide_assists/src/handlers/convert_comment_block.rs
@@ -0,0 +1,419 @@
1use itertools::Itertools;
2use std::convert::identity;
3use syntax::{
4 ast::{
5 self,
6 edit::IndentLevel,
7 Comment, CommentKind,
8 CommentPlacement::{Inner, Outer},
9 CommentShape::{self, Block, Line},
10 Whitespace,
11 },
12 AstToken, Direction, SyntaxElement, TextRange,
13};
14
15use crate::{AssistContext, AssistId, AssistKind, Assists};
16
17/// Assist: line_to_block
18///
19/// Converts comments between block and single-line form
20///
21/// ```
22/// // Multi-line
23/// // comment
24/// ```
25/// ->
26/// ```
27/// /**
28/// Multi-line
29/// comment
30/// */
31/// ```
32pub(crate) fn convert_comment_block(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
33 if let Some(comment) = ctx.find_token_at_offset::<ast::Comment>() {
34 // Only allow comments which are alone on their line
35 if let Some(prev) = comment.syntax().prev_token() {
36 if Whitespace::cast(prev).filter(|w| w.text().contains('\n')).is_none() {
37 return None;
38 }
39 }
40
41 return match comment.kind().shape {
42 ast::CommentShape::Block => block_to_line(acc, comment),
43 ast::CommentShape::Line => line_to_block(acc, comment),
44 };
45 }
46
47 return None;
48}
49
50fn block_to_line(acc: &mut Assists, comment: ast::Comment) -> Option<()> {
51 let target = comment.syntax().text_range();
52
53 acc.add(
54 AssistId("block_to_line", AssistKind::RefactorRewrite),
55 "Replace block comment with line comments",
56 target,
57 |edit| {
58 let indentation = IndentLevel::from_token(comment.syntax());
59 let line_prefix =
60 comment_kind_prefix(CommentKind { shape: CommentShape::Line, ..comment.kind() });
61
62 let text = comment.text();
63 let text = &text[comment.prefix().len()..(text.len() - "*/".len())].trim();
64
65 let lines = text.lines().peekable();
66
67 let indent_spaces = indentation.to_string();
68 let output = lines
69 .map(|l| l.trim_start_matches(&indent_spaces))
70 .map(|l| {
71 // Don't introduce trailing whitespace
72 if l.is_empty() {
73 line_prefix.to_string()
74 } else {
75 format!("{} {}", line_prefix, l.trim_start_matches(&indent_spaces))
76 }
77 })
78 .join(&format!("\n{}", indent_spaces));
79
80 edit.replace(target, output)
81 },
82 )
83}
84
85fn line_to_block(acc: &mut Assists, comment: ast::Comment) -> Option<()> {
86 // Find all the comments we'll be collapsing into a block
87 let comments = relevant_line_comments(&comment);
88
89 // Establish the target of our edit based on the comments we found
90 let target = TextRange::new(
91 comments[0].syntax().text_range().start(),
92 comments.last().unwrap().syntax().text_range().end(),
93 );
94
95 acc.add(
96 AssistId("line_to_block", AssistKind::RefactorRewrite),
97 "Replace line comments with a single block comment",
98 target,
99 |edit| {
100 // We pick a single indentation level for the whole block comment based on the
101 // comment where the assist was invoked. This will be prepended to the
102 // contents of each line comment when they're put into the block comment.
103 let indentation = IndentLevel::from_token(&comment.syntax());
104
105 let block_comment_body =
106 comments.into_iter().map(|c| line_comment_text(indentation, c)).join("\n");
107
108 let block_prefix =
109 comment_kind_prefix(CommentKind { shape: CommentShape::Block, ..comment.kind() });
110
111 let output =
112 format!("{}\n{}\n{}*/", block_prefix, block_comment_body, indentation.to_string());
113
114 edit.replace(target, output)
115 },
116 )
117}
118
119/// The line -> block assist can be invoked from anywhere within a sequence of line comments.
120/// relevant_line_comments crawls backwards and forwards finding the complete sequence of comments that will
121/// be joined.
122fn relevant_line_comments(comment: &ast::Comment) -> Vec<Comment> {
123 // The prefix identifies the kind of comment we're dealing with
124 let prefix = comment.prefix();
125 let same_prefix = |c: &ast::Comment| c.prefix() == prefix;
126
127 // These tokens are allowed to exist between comments
128 let skippable = |not: &SyntaxElement| {
129 not.clone()
130 .into_token()
131 .and_then(Whitespace::cast)
132 .map(|w| !w.spans_multiple_lines())
133 .unwrap_or(false)
134 };
135
136 // Find all preceding comments (in reverse order) that have the same prefix
137 let prev_comments = comment
138 .syntax()
139 .siblings_with_tokens(Direction::Prev)
140 .filter(|s| !skippable(s))
141 .map(|not| not.into_token().and_then(Comment::cast).filter(same_prefix))
142 .take_while(|opt_com| opt_com.is_some())
143 .filter_map(identity)
144 .skip(1); // skip the first element so we don't duplicate it in next_comments
145
146 let next_comments = comment
147 .syntax()
148 .siblings_with_tokens(Direction::Next)
149 .filter(|s| !skippable(s))
150 .map(|not| not.into_token().and_then(Comment::cast).filter(same_prefix))
151 .take_while(|opt_com| opt_com.is_some())
152 .filter_map(identity);
153
154 let mut comments: Vec<_> = prev_comments.collect();
155 comments.reverse();
156 comments.extend(next_comments);
157 comments
158}
159
160// Line comments usually begin with a single space character following the prefix as seen here:
161//^
162// But comments can also include indented text:
163// > Hello there
164//
165// We handle this by stripping *AT MOST* one space character from the start of the line
166// This has its own problems because it can cause alignment issues:
167//
168// /*
169// a ----> a
170//b ----> b
171// */
172//
173// But since such comments aren't idiomatic we're okay with this.
174fn line_comment_text(indentation: IndentLevel, comm: ast::Comment) -> String {
175 let contents_without_prefix = comm.text().strip_prefix(comm.prefix()).unwrap();
176 let contents = contents_without_prefix.strip_prefix(' ').unwrap_or(contents_without_prefix);
177
178 // Don't add the indentation if the line is empty
179 if contents.is_empty() {
180 contents.to_owned()
181 } else {
182 indentation.to_string() + &contents
183 }
184}
185
186fn comment_kind_prefix(ck: ast::CommentKind) -> &'static str {
187 match (ck.shape, ck.doc) {
188 (Line, Some(Inner)) => "//!",
189 (Line, Some(Outer)) => "///",
190 (Line, None) => "//",
191 (Block, Some(Inner)) => "/*!",
192 (Block, Some(Outer)) => "/**",
193 (Block, None) => "/*",
194 }
195}
196
197#[cfg(test)]
198mod tests {
199 use crate::tests::{check_assist, check_assist_not_applicable};
200
201 use super::*;
202
203 #[test]
204 fn single_line_to_block() {
205 check_assist(
206 convert_comment_block,
207 r#"
208// line$0 comment
209fn main() {
210 foo();
211}
212"#,
213 r#"
214/*
215line comment
216*/
217fn main() {
218 foo();
219}
220"#,
221 );
222 }
223
224 #[test]
225 fn single_line_to_block_indented() {
226 check_assist(
227 convert_comment_block,
228 r#"
229fn main() {
230 // line$0 comment
231 foo();
232}
233"#,
234 r#"
235fn main() {
236 /*
237 line comment
238 */
239 foo();
240}
241"#,
242 );
243 }
244
245 #[test]
246 fn multiline_to_block() {
247 check_assist(
248 convert_comment_block,
249 r#"
250fn main() {
251 // above
252 // line$0 comment
253 //
254 // below
255 foo();
256}
257"#,
258 r#"
259fn main() {
260 /*
261 above
262 line comment
263
264 below
265 */
266 foo();
267}
268"#,
269 );
270 }
271
272 #[test]
273 fn end_of_line_to_block() {
274 check_assist_not_applicable(
275 convert_comment_block,
276 r#"
277fn main() {
278 foo(); // end-of-line$0 comment
279}
280"#,
281 );
282 }
283
284 #[test]
285 fn single_line_different_kinds() {
286 check_assist(
287 convert_comment_block,
288 r#"
289fn main() {
290 /// different prefix
291 // line$0 comment
292 // below
293 foo();
294}
295"#,
296 r#"
297fn main() {
298 /// different prefix
299 /*
300 line comment
301 below
302 */
303 foo();
304}
305"#,
306 );
307 }
308
309 #[test]
310 fn single_line_separate_chunks() {
311 check_assist(
312 convert_comment_block,
313 r#"
314fn main() {
315 // different chunk
316
317 // line$0 comment
318 // below
319 foo();
320}
321"#,
322 r#"
323fn main() {
324 // different chunk
325
326 /*
327 line comment
328 below
329 */
330 foo();
331}
332"#,
333 );
334 }
335
336 #[test]
337 fn doc_block_comment_to_lines() {
338 check_assist(
339 convert_comment_block,
340 r#"
341/**
342 hi$0 there
343*/
344"#,
345 r#"
346/// hi there
347"#,
348 );
349 }
350
351 #[test]
352 fn block_comment_to_lines() {
353 check_assist(
354 convert_comment_block,
355 r#"
356/*
357 hi$0 there
358*/
359"#,
360 r#"
361// hi there
362"#,
363 );
364 }
365
366 #[test]
367 fn inner_doc_block_to_lines() {
368 check_assist(
369 convert_comment_block,
370 r#"
371/*!
372 hi$0 there
373*/
374"#,
375 r#"
376//! hi there
377"#,
378 );
379 }
380
381 #[test]
382 fn block_to_lines_indent() {
383 check_assist(
384 convert_comment_block,
385 r#"
386fn main() {
387 /*!
388 hi$0 there
389
390 ```
391 code_sample
392 ```
393 */
394}
395"#,
396 r#"
397fn main() {
398 //! hi there
399 //!
400 //! ```
401 //! code_sample
402 //! ```
403}
404"#,
405 );
406 }
407
408 #[test]
409 fn end_of_line_block_to_line() {
410 check_assist_not_applicable(
411 convert_comment_block,
412 r#"
413fn main() {
414 foo(); /* end-of-line$0 comment */
415}
416"#,
417 );
418 }
419}
diff --git a/crates/ide_assists/src/handlers/convert_for_to_iter_for_each.rs b/crates/ide_assists/src/handlers/replace_for_loop_with_for_each.rs
index 9fddf889c..27da28bc0 100644
--- a/crates/ide_assists/src/handlers/convert_for_to_iter_for_each.rs
+++ b/crates/ide_assists/src/handlers/replace_for_loop_with_for_each.rs
@@ -3,17 +3,18 @@ use hir::known;
3use ide_db::helpers::FamousDefs; 3use ide_db::helpers::FamousDefs;
4use stdx::format_to; 4use stdx::format_to;
5use syntax::{ast, AstNode}; 5use syntax::{ast, AstNode};
6use test_utils::mark;
6 7
7use crate::{AssistContext, AssistId, AssistKind, Assists}; 8use crate::{AssistContext, AssistId, AssistKind, Assists};
8 9
9// Assist: convert_for_to_iter_for_each 10// Assist: replace_for_loop_with_for_each
10// 11//
11// Converts a for loop into a for_each loop on the Iterator. 12// Converts a for loop into a for_each loop on the Iterator.
12// 13//
13// ``` 14// ```
14// fn main() { 15// fn main() {
15// let x = vec![1, 2, 3]; 16// let x = vec![1, 2, 3];
16// for $0v in x { 17// for$0 v in x {
17// let y = v * 2; 18// let y = v * 2;
18// } 19// }
19// } 20// }
@@ -27,15 +28,19 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
27// }); 28// });
28// } 29// }
29// ``` 30// ```
30pub(crate) fn convert_for_to_iter_for_each(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 31pub(crate) fn replace_for_loop_with_for_each(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
31 let for_loop = ctx.find_node_at_offset::<ast::ForExpr>()?; 32 let for_loop = ctx.find_node_at_offset::<ast::ForExpr>()?;
32 let iterable = for_loop.iterable()?; 33 let iterable = for_loop.iterable()?;
33 let pat = for_loop.pat()?; 34 let pat = for_loop.pat()?;
34 let body = for_loop.loop_body()?; 35 let body = for_loop.loop_body()?;
36 if body.syntax().text_range().start() < ctx.offset() {
37 mark::hit!(not_available_in_body);
38 return None;
39 }
35 40
36 acc.add( 41 acc.add(
37 AssistId("convert_for_to_iter_for_each", AssistKind::RefactorRewrite), 42 AssistId("replace_for_loop_with_for_each", AssistKind::RefactorRewrite),
38 "Convert a for loop into an Iterator::for_each", 43 "Replace this for loop with `Iterator::for_each`",
39 for_loop.syntax().text_range(), 44 for_loop.syntax().text_range(),
40 |builder| { 45 |builder| {
41 let mut buf = String::new(); 46 let mut buf = String::new();
@@ -145,13 +150,13 @@ pub struct NoIterMethod;
145 FamousDefs::FIXTURE, 150 FamousDefs::FIXTURE,
146 EMPTY_ITER_FIXTURE 151 EMPTY_ITER_FIXTURE
147 ); 152 );
148 check_assist(convert_for_to_iter_for_each, before, after); 153 check_assist(replace_for_loop_with_for_each, before, after);
149 } 154 }
150 155
151 #[test] 156 #[test]
152 fn test_not_for() { 157 fn test_not_for() {
153 check_assist_not_applicable( 158 check_assist_not_applicable(
154 convert_for_to_iter_for_each, 159 replace_for_loop_with_for_each,
155 r" 160 r"
156let mut x = vec![1, 2, 3]; 161let mut x = vec![1, 2, 3];
157x.iter_mut().$0for_each(|v| *v *= 2); 162x.iter_mut().$0for_each(|v| *v *= 2);
@@ -162,7 +167,7 @@ x.iter_mut().$0for_each(|v| *v *= 2);
162 #[test] 167 #[test]
163 fn test_simple_for() { 168 fn test_simple_for() {
164 check_assist( 169 check_assist(
165 convert_for_to_iter_for_each, 170 replace_for_loop_with_for_each,
166 r" 171 r"
167fn main() { 172fn main() {
168 let x = vec![1, 2, 3]; 173 let x = vec![1, 2, 3];
@@ -181,6 +186,21 @@ fn main() {
181 } 186 }
182 187
183 #[test] 188 #[test]
189 fn not_available_in_body() {
190 mark::check!(not_available_in_body);
191 check_assist_not_applicable(
192 replace_for_loop_with_for_each,
193 r"
194fn main() {
195 let x = vec![1, 2, 3];
196 for v in x {
197 $0v *= 2;
198 }
199}",
200 )
201 }
202
203 #[test]
184 fn test_for_borrowed() { 204 fn test_for_borrowed() {
185 check_assist_with_fixtures( 205 check_assist_with_fixtures(
186 r" 206 r"
@@ -255,7 +275,7 @@ fn main() {
255 #[test] 275 #[test]
256 fn test_for_borrowed_mut_behind_var() { 276 fn test_for_borrowed_mut_behind_var() {
257 check_assist( 277 check_assist(
258 convert_for_to_iter_for_each, 278 replace_for_loop_with_for_each,
259 r" 279 r"
260fn main() { 280fn main() {
261 let x = vec![1, 2, 3]; 281 let x = vec![1, 2, 3];
diff --git a/crates/ide_assists/src/handlers/replace_let_with_if_let.rs b/crates/ide_assists/src/handlers/replace_let_with_if_let.rs
index 5a27ada6b..be7e724b5 100644
--- a/crates/ide_assists/src/handlers/replace_let_with_if_let.rs
+++ b/crates/ide_assists/src/handlers/replace_let_with_if_let.rs
@@ -1,5 +1,6 @@
1use std::iter::once; 1use std::iter::once;
2 2
3use ide_db::ty_filter::TryEnum;
3use syntax::{ 4use syntax::{
4 ast::{ 5 ast::{
5 self, 6 self,
@@ -10,7 +11,6 @@ use syntax::{
10}; 11};
11 12
12use crate::{AssistContext, AssistId, AssistKind, Assists}; 13use crate::{AssistContext, AssistId, AssistKind, Assists};
13use ide_db::ty_filter::TryEnum;
14 14
15// Assist: replace_let_with_if_let 15// Assist: replace_let_with_if_let
16// 16//
diff --git a/crates/ide_assists/src/lib.rs b/crates/ide_assists/src/lib.rs
index 4c067d451..9c8148462 100644
--- a/crates/ide_assists/src/lib.rs
+++ b/crates/ide_assists/src/lib.rs
@@ -114,8 +114,8 @@ mod handlers {
114 mod apply_demorgan; 114 mod apply_demorgan;
115 mod auto_import; 115 mod auto_import;
116 mod change_visibility; 116 mod change_visibility;
117 mod convert_for_to_iter_for_each;
118 mod convert_integer_literal; 117 mod convert_integer_literal;
118 mod convert_comment_block;
119 mod early_return; 119 mod early_return;
120 mod expand_glob_import; 120 mod expand_glob_import;
121 mod extract_function; 121 mod extract_function;
@@ -132,8 +132,8 @@ mod handlers {
132 mod generate_enum_projection_method; 132 mod generate_enum_projection_method;
133 mod generate_from_impl_for_enum; 133 mod generate_from_impl_for_enum;
134 mod generate_function; 134 mod generate_function;
135 mod generate_getter;
136 mod generate_getter_mut; 135 mod generate_getter_mut;
136 mod generate_getter;
137 mod generate_impl; 137 mod generate_impl;
138 mod generate_new; 138 mod generate_new;
139 mod generate_setter; 139 mod generate_setter;
@@ -156,6 +156,7 @@ mod handlers {
156 mod reorder_fields; 156 mod reorder_fields;
157 mod reorder_impl; 157 mod reorder_impl;
158 mod replace_derive_with_manual_impl; 158 mod replace_derive_with_manual_impl;
159 mod replace_for_loop_with_for_each;
159 mod replace_if_let_with_match; 160 mod replace_if_let_with_match;
160 mod replace_impl_trait_with_generic; 161 mod replace_impl_trait_with_generic;
161 mod replace_let_with_if_let; 162 mod replace_let_with_if_let;
@@ -177,11 +178,10 @@ mod handlers {
177 apply_demorgan::apply_demorgan, 178 apply_demorgan::apply_demorgan,
178 auto_import::auto_import, 179 auto_import::auto_import,
179 change_visibility::change_visibility, 180 change_visibility::change_visibility,
180 convert_for_to_iter_for_each::convert_for_to_iter_for_each,
181 convert_integer_literal::convert_integer_literal, 181 convert_integer_literal::convert_integer_literal,
182 convert_comment_block::convert_comment_block,
182 early_return::convert_to_guarded_return, 183 early_return::convert_to_guarded_return,
183 expand_glob_import::expand_glob_import, 184 expand_glob_import::expand_glob_import,
184 move_module_to_file::move_module_to_file,
185 extract_struct_from_enum_variant::extract_struct_from_enum_variant, 185 extract_struct_from_enum_variant::extract_struct_from_enum_variant,
186 fill_match_arms::fill_match_arms, 186 fill_match_arms::fill_match_arms,
187 fix_visibility::fix_visibility, 187 fix_visibility::fix_visibility,
@@ -191,12 +191,12 @@ mod handlers {
191 generate_default_from_enum_variant::generate_default_from_enum_variant, 191 generate_default_from_enum_variant::generate_default_from_enum_variant,
192 generate_derive::generate_derive, 192 generate_derive::generate_derive,
193 generate_enum_is_method::generate_enum_is_method, 193 generate_enum_is_method::generate_enum_is_method,
194 generate_enum_projection_method::generate_enum_try_into_method,
195 generate_enum_projection_method::generate_enum_as_method, 194 generate_enum_projection_method::generate_enum_as_method,
195 generate_enum_projection_method::generate_enum_try_into_method,
196 generate_from_impl_for_enum::generate_from_impl_for_enum, 196 generate_from_impl_for_enum::generate_from_impl_for_enum,
197 generate_function::generate_function, 197 generate_function::generate_function,
198 generate_getter::generate_getter,
199 generate_getter_mut::generate_getter_mut, 198 generate_getter_mut::generate_getter_mut,
199 generate_getter::generate_getter,
200 generate_impl::generate_impl, 200 generate_impl::generate_impl,
201 generate_new::generate_new, 201 generate_new::generate_new,
202 generate_setter::generate_setter, 202 generate_setter::generate_setter,
@@ -210,6 +210,7 @@ mod handlers {
210 move_bounds::move_bounds_to_where_clause, 210 move_bounds::move_bounds_to_where_clause,
211 move_guard::move_arm_cond_to_match_guard, 211 move_guard::move_arm_cond_to_match_guard,
212 move_guard::move_guard_to_arm_body, 212 move_guard::move_guard_to_arm_body,
213 move_module_to_file::move_module_to_file,
213 pull_assignment_up::pull_assignment_up, 214 pull_assignment_up::pull_assignment_up,
214 qualify_path::qualify_path, 215 qualify_path::qualify_path,
215 raw_string::add_hash, 216 raw_string::add_hash,
@@ -221,6 +222,7 @@ mod handlers {
221 reorder_fields::reorder_fields, 222 reorder_fields::reorder_fields,
222 reorder_impl::reorder_impl, 223 reorder_impl::reorder_impl,
223 replace_derive_with_manual_impl::replace_derive_with_manual_impl, 224 replace_derive_with_manual_impl::replace_derive_with_manual_impl,
225 replace_for_loop_with_for_each::replace_for_loop_with_for_each,
224 replace_if_let_with_match::replace_if_let_with_match, 226 replace_if_let_with_match::replace_if_let_with_match,
225 replace_if_let_with_match::replace_match_with_if_let, 227 replace_if_let_with_match::replace_match_with_if_let,
226 replace_impl_trait_with_generic::replace_impl_trait_with_generic, 228 replace_impl_trait_with_generic::replace_impl_trait_with_generic,
diff --git a/crates/ide_assists/src/tests.rs b/crates/ide_assists/src/tests.rs
index 384eb7eee..b7f616760 100644
--- a/crates/ide_assists/src/tests.rs
+++ b/crates/ide_assists/src/tests.rs
@@ -190,8 +190,8 @@ fn assist_order_field_struct() {
190 let mut assists = assists.iter(); 190 let mut assists = assists.iter();
191 191
192 assert_eq!(assists.next().expect("expected assist").label, "Change visibility to pub(crate)"); 192 assert_eq!(assists.next().expect("expected assist").label, "Change visibility to pub(crate)");
193 assert_eq!(assists.next().expect("expected assist").label, "Generate a getter method");
194 assert_eq!(assists.next().expect("expected assist").label, "Generate a mut getter method"); 193 assert_eq!(assists.next().expect("expected assist").label, "Generate a mut getter method");
194 assert_eq!(assists.next().expect("expected assist").label, "Generate a getter method");
195 assert_eq!(assists.next().expect("expected assist").label, "Generate a setter method"); 195 assert_eq!(assists.next().expect("expected assist").label, "Generate a setter method");
196 assert_eq!(assists.next().expect("expected assist").label, "Add `#[derive]`"); 196 assert_eq!(assists.next().expect("expected assist").label, "Add `#[derive]`");
197} 197}
diff --git a/crates/ide_assists/src/tests/generated.rs b/crates/ide_assists/src/tests/generated.rs
index 7f6dbbccf..4f007aa48 100644
--- a/crates/ide_assists/src/tests/generated.rs
+++ b/crates/ide_assists/src/tests/generated.rs
@@ -193,29 +193,6 @@ pub(crate) fn frobnicate() {}
193} 193}
194 194
195#[test] 195#[test]
196fn doctest_convert_for_to_iter_for_each() {
197 check_doc_test(
198 "convert_for_to_iter_for_each",
199 r#####"
200fn main() {
201 let x = vec![1, 2, 3];
202 for $0v in x {
203 let y = v * 2;
204 }
205}
206"#####,
207 r#####"
208fn main() {
209 let x = vec![1, 2, 3];
210 x.into_iter().for_each(|v| {
211 let y = v * 2;
212 });
213}
214"#####,
215 )
216}
217
218#[test]
219fn doctest_convert_integer_literal() { 196fn doctest_convert_integer_literal() {
220 check_doc_test( 197 check_doc_test(
221 "convert_integer_literal", 198 "convert_integer_literal",
@@ -1180,6 +1157,29 @@ impl Debug for S {
1180} 1157}
1181 1158
1182#[test] 1159#[test]
1160fn doctest_replace_for_loop_with_for_each() {
1161 check_doc_test(
1162 "replace_for_loop_with_for_each",
1163 r#####"
1164fn main() {
1165 let x = vec![1, 2, 3];
1166 for$0 v in x {
1167 let y = v * 2;
1168 }
1169}
1170"#####,
1171 r#####"
1172fn main() {
1173 let x = vec![1, 2, 3];
1174 x.into_iter().for_each(|v| {
1175 let y = v * 2;
1176 });
1177}
1178"#####,
1179 )
1180}
1181
1182#[test]
1183fn doctest_replace_if_let_with_match() { 1183fn doctest_replace_if_let_with_match() {
1184 check_doc_test( 1184 check_doc_test(
1185 "replace_if_let_with_match", 1185 "replace_if_let_with_match",
diff --git a/crates/mbe/Cargo.toml b/crates/mbe/Cargo.toml
index 46f11ad38..bb2656a80 100644
--- a/crates/mbe/Cargo.toml
+++ b/crates/mbe/Cargo.toml
@@ -21,5 +21,4 @@ test_utils = { path = "../test_utils", version = "0.0.0" }
21stdx = { path = "../stdx", version = "0.0.0" } 21stdx = { path = "../stdx", version = "0.0.0" }
22 22
23[dev-dependencies] 23[dev-dependencies]
24profile = { path = "../profile", version = "0.0.0" } 24profile = { path = "../profile" }
25
diff --git a/crates/mbe/src/benchmark.rs b/crates/mbe/src/benchmark.rs
index 13db5eef1..503ad1355 100644
--- a/crates/mbe/src/benchmark.rs
+++ b/crates/mbe/src/benchmark.rs
@@ -191,7 +191,7 @@ fn invocation_fixtures(rules: &FxHashMap<String, MacroRules>) -> Vec<(String, tt
191 let c = 1013904223; 191 let c = 1013904223;
192 *seed = usize::wrapping_add(usize::wrapping_mul(*seed, a), c); 192 *seed = usize::wrapping_add(usize::wrapping_mul(*seed, a), c);
193 return *seed; 193 return *seed;
194 }; 194 }
195 fn make_ident(ident: &str) -> tt::TokenTree { 195 fn make_ident(ident: &str) -> tt::TokenTree {
196 tt::Leaf::Ident(tt::Ident { id: tt::TokenId::unspecified(), text: SmolStr::new(ident) }) 196 tt::Leaf::Ident(tt::Ident { id: tt::TokenId::unspecified(), text: SmolStr::new(ident) })
197 .into() 197 .into()
diff --git a/crates/proc_macro_srv/Cargo.toml b/crates/proc_macro_srv/Cargo.toml
index 6c8c28980..4c1b3036a 100644
--- a/crates/proc_macro_srv/Cargo.toml
+++ b/crates/proc_macro_srv/Cargo.toml
@@ -20,7 +20,7 @@ proc_macro_api = { path = "../proc_macro_api", version = "0.0.0" }
20test_utils = { path = "../test_utils", version = "0.0.0" } 20test_utils = { path = "../test_utils", version = "0.0.0" }
21 21
22[dev-dependencies] 22[dev-dependencies]
23cargo_metadata = "0.12.2" 23cargo_metadata = "0.13"
24 24
25# used as proc macro test targets 25# used as proc macro test targets
26serde_derive = "1.0.106" 26serde_derive = "1.0.106"
diff --git a/crates/proc_macro_srv/src/rustc_server.rs b/crates/proc_macro_srv/src/rustc_server.rs
index a8504f762..952b4a97f 100644
--- a/crates/proc_macro_srv/src/rustc_server.rs
+++ b/crates/proc_macro_srv/src/rustc_server.rs
@@ -14,7 +14,6 @@ use std::collections::HashMap;
14use std::hash::Hash; 14use std::hash::Hash;
15use std::iter::FromIterator; 15use std::iter::FromIterator;
16use std::ops::Bound; 16use std::ops::Bound;
17use std::str::FromStr;
18use std::{ascii, vec::IntoIter}; 17use std::{ascii, vec::IntoIter};
19 18
20type Group = tt::Subtree; 19type Group = tt::Subtree;
@@ -278,6 +277,42 @@ impl server::FreeFunctions for Rustc {
278 } 277 }
279} 278}
280 279
280fn subtree_replace_token_ids_with_unspecified(subtree: tt::Subtree) -> tt::Subtree {
281 tt::Subtree {
282 delimiter: subtree.delimiter.map(|d| tt::Delimiter { id: tt::TokenId::unspecified(), ..d }),
283 token_trees: subtree
284 .token_trees
285 .into_iter()
286 .map(|t| token_tree_replace_token_ids_with_unspecified(t))
287 .collect(),
288 }
289}
290
291fn token_tree_replace_token_ids_with_unspecified(tt: tt::TokenTree) -> tt::TokenTree {
292 match tt {
293 tt::TokenTree::Leaf(leaf) => {
294 tt::TokenTree::Leaf(leaf_replace_token_ids_with_unspecified(leaf))
295 }
296 tt::TokenTree::Subtree(subtree) => {
297 tt::TokenTree::Subtree(subtree_replace_token_ids_with_unspecified(subtree))
298 }
299 }
300}
301
302fn leaf_replace_token_ids_with_unspecified(leaf: tt::Leaf) -> tt::Leaf {
303 match leaf {
304 tt::Leaf::Literal(lit) => {
305 tt::Leaf::Literal(tt::Literal { id: tt::TokenId::unspecified(), ..lit })
306 }
307 tt::Leaf::Punct(punct) => {
308 tt::Leaf::Punct(tt::Punct { id: tt::TokenId::unspecified(), ..punct })
309 }
310 tt::Leaf::Ident(ident) => {
311 tt::Leaf::Ident(tt::Ident { id: tt::TokenId::unspecified(), ..ident })
312 }
313 }
314}
315
281impl server::TokenStream for Rustc { 316impl server::TokenStream for Rustc {
282 fn new(&mut self) -> Self::TokenStream { 317 fn new(&mut self) -> Self::TokenStream {
283 Self::TokenStream::new() 318 Self::TokenStream::new()
@@ -287,7 +322,8 @@ impl server::TokenStream for Rustc {
287 stream.is_empty() 322 stream.is_empty()
288 } 323 }
289 fn from_str(&mut self, src: &str) -> Self::TokenStream { 324 fn from_str(&mut self, src: &str) -> Self::TokenStream {
290 Self::TokenStream::from_str(src).expect("cannot parse string") 325 let (subtree, _) = mbe::parse_to_token_tree(src).expect("cannot parse string");
326 TokenStream::with_subtree(subtree_replace_token_ids_with_unspecified(subtree))
291 } 327 }
292 fn to_string(&mut self, stream: &Self::TokenStream) -> String { 328 fn to_string(&mut self, stream: &Self::TokenStream) -> String {
293 stream.to_string() 329 stream.to_string()
diff --git a/crates/proc_macro_srv/src/tests/utils.rs b/crates/proc_macro_srv/src/tests/utils.rs
index 196abb8fc..22813052d 100644
--- a/crates/proc_macro_srv/src/tests/utils.rs
+++ b/crates/proc_macro_srv/src/tests/utils.rs
@@ -8,6 +8,7 @@ use test_utils::assert_eq_text;
8 8
9mod fixtures { 9mod fixtures {
10 use cargo_metadata::Message; 10 use cargo_metadata::Message;
11 use std::path::PathBuf;
11 use std::process::Command; 12 use std::process::Command;
12 13
13 // Use current project metadata to get the proc-macro dylib path 14 // Use current project metadata to get the proc-macro dylib path
@@ -24,7 +25,7 @@ mod fixtures {
24 if artifact.target.kind.contains(&"proc-macro".to_string()) { 25 if artifact.target.kind.contains(&"proc-macro".to_string()) {
25 let repr = format!("{} {}", crate_name, version); 26 let repr = format!("{} {}", crate_name, version);
26 if artifact.package_id.repr.starts_with(&repr) { 27 if artifact.package_id.repr.starts_with(&repr) {
27 return artifact.filenames[0].clone(); 28 return PathBuf::from(&artifact.filenames[0]);
28 } 29 }
29 } 30 }
30 } 31 }
diff --git a/crates/project_model/Cargo.toml b/crates/project_model/Cargo.toml
index 293cb5bfe..fe3258332 100644
--- a/crates/project_model/Cargo.toml
+++ b/crates/project_model/Cargo.toml
@@ -12,7 +12,7 @@ doctest = false
12[dependencies] 12[dependencies]
13log = "0.4.8" 13log = "0.4.8"
14rustc-hash = "1.1.0" 14rustc-hash = "1.1.0"
15cargo_metadata = "0.12.2" 15cargo_metadata = "0.13"
16serde = { version = "1.0.106", features = ["derive"] } 16serde = { version = "1.0.106", features = ["derive"] }
17serde_json = "1.0.48" 17serde_json = "1.0.48"
18anyhow = "1.0.26" 18anyhow = "1.0.26"
@@ -22,7 +22,7 @@ la-arena = { version = "0.2.0", path = "../../lib/arena" }
22cfg = { path = "../cfg", version = "0.0.0" } 22cfg = { path = "../cfg", version = "0.0.0" }
23base_db = { path = "../base_db", version = "0.0.0" } 23base_db = { path = "../base_db", version = "0.0.0" }
24toolchain = { path = "../toolchain", version = "0.0.0" } 24toolchain = { path = "../toolchain", version = "0.0.0" }
25proc_macro_api = { path = "../proc_macro_api", version = "0.0.0" } 25proc_macro_api = { path = "../proc_macro_api", version = "0.0.0" }
26paths = { path = "../paths", version = "0.0.0" } 26paths = { path = "../paths", version = "0.0.0" }
27stdx = { path = "../stdx", version = "0.0.0" } 27stdx = { path = "../stdx", version = "0.0.0" }
28profile = { path = "../profile", version = "0.0.0" } 28profile = { path = "../profile", version = "0.0.0" }
diff --git a/crates/project_model/src/build_data.rs b/crates/project_model/src/build_data.rs
index 295b5f8ef..728a258ea 100644
--- a/crates/project_model/src/build_data.rs
+++ b/crates/project_model/src/build_data.rs
@@ -1,14 +1,14 @@
1//! Handles build script specific information 1//! Handles build script specific information
2 2
3use std::{ 3use std::{
4 ffi::OsStr,
5 io::BufReader, 4 io::BufReader,
6 path::{Path, PathBuf}, 5 path::PathBuf,
7 process::{Command, Stdio}, 6 process::{Command, Stdio},
8 sync::Arc, 7 sync::Arc,
9}; 8};
10 9
11use anyhow::Result; 10use anyhow::Result;
11use cargo_metadata::camino::Utf8Path;
12use cargo_metadata::{BuildScript, Message}; 12use cargo_metadata::{BuildScript, Message};
13use itertools::Itertools; 13use itertools::Itertools;
14use paths::{AbsPath, AbsPathBuf}; 14use paths::{AbsPath, AbsPathBuf};
@@ -162,8 +162,8 @@ fn collect_from_workspace(
162 let res = res.entry(package_id.repr.clone()).or_default(); 162 let res = res.entry(package_id.repr.clone()).or_default();
163 // cargo_metadata crate returns default (empty) path for 163 // cargo_metadata crate returns default (empty) path for
164 // older cargos, which is not absolute, so work around that. 164 // older cargos, which is not absolute, so work around that.
165 if out_dir != PathBuf::default() { 165 if !out_dir.as_str().is_empty() {
166 let out_dir = AbsPathBuf::assert(out_dir); 166 let out_dir = AbsPathBuf::assert(PathBuf::from(out_dir.into_os_string()));
167 res.out_dir = Some(out_dir); 167 res.out_dir = Some(out_dir);
168 res.cfgs = cfgs; 168 res.cfgs = cfgs;
169 } 169 }
@@ -178,7 +178,7 @@ fn collect_from_workspace(
178 // Skip rmeta file 178 // Skip rmeta file
179 if let Some(filename) = message.filenames.iter().find(|name| is_dylib(name)) 179 if let Some(filename) = message.filenames.iter().find(|name| is_dylib(name))
180 { 180 {
181 let filename = AbsPathBuf::assert(filename.clone()); 181 let filename = AbsPathBuf::assert(PathBuf::from(&filename));
182 let res = res.entry(package_id.repr.clone()).or_default(); 182 let res = res.entry(package_id.repr.clone()).or_default();
183 res.proc_macro_dylib_path = Some(filename); 183 res.proc_macro_dylib_path = Some(filename);
184 } 184 }
@@ -187,9 +187,9 @@ fn collect_from_workspace(
187 Message::CompilerMessage(message) => { 187 Message::CompilerMessage(message) => {
188 progress(message.target.name.clone()); 188 progress(message.target.name.clone());
189 } 189 }
190 Message::Unknown => (),
191 Message::BuildFinished(_) => {} 190 Message::BuildFinished(_) => {}
192 Message::TextLine(_) => {} 191 Message::TextLine(_) => {}
192 _ => {}
193 } 193 }
194 } 194 }
195 } 195 }
@@ -209,8 +209,8 @@ fn collect_from_workspace(
209} 209}
210 210
211// FIXME: File a better way to know if it is a dylib 211// FIXME: File a better way to know if it is a dylib
212fn is_dylib(path: &Path) -> bool { 212fn is_dylib(path: &Utf8Path) -> bool {
213 match path.extension().and_then(OsStr::to_str).map(|it| it.to_string().to_lowercase()) { 213 match path.extension().map(|e| e.to_string().to_lowercase()) {
214 None => false, 214 None => false,
215 Some(ext) => matches!(ext.as_str(), "dll" | "dylib" | "so"), 215 Some(ext) => matches!(ext.as_str(), "dll" | "dylib" | "so"),
216 } 216 }
@@ -227,9 +227,7 @@ fn inject_cargo_env(package: &cargo_metadata::Package, build_data: &mut BuildDat
227 227
228 let mut manifest_dir = package.manifest_path.clone(); 228 let mut manifest_dir = package.manifest_path.clone();
229 manifest_dir.pop(); 229 manifest_dir.pop();
230 if let Some(cargo_manifest_dir) = manifest_dir.to_str() { 230 env.push(("CARGO_MANIFEST_DIR".into(), manifest_dir.into_string()));
231 env.push(("CARGO_MANIFEST_DIR".into(), cargo_manifest_dir.into()));
232 }
233 231
234 // Not always right, but works for common cases. 232 // Not always right, but works for common cases.
235 env.push(("CARGO".into(), "cargo".into())); 233 env.push(("CARGO".into(), "cargo".into()));
@@ -251,7 +249,6 @@ fn inject_cargo_env(package: &cargo_metadata::Package, build_data: &mut BuildDat
251 env.push(("CARGO_PKG_REPOSITORY".into(), package.repository.clone().unwrap_or_default())); 249 env.push(("CARGO_PKG_REPOSITORY".into(), package.repository.clone().unwrap_or_default()));
252 env.push(("CARGO_PKG_LICENSE".into(), package.license.clone().unwrap_or_default())); 250 env.push(("CARGO_PKG_LICENSE".into(), package.license.clone().unwrap_or_default()));
253 251
254 let license_file = 252 let license_file = package.license_file.as_ref().map(|buf| buf.to_string()).unwrap_or_default();
255 package.license_file.as_ref().map(|buf| buf.display().to_string()).unwrap_or_default();
256 env.push(("CARGO_PKG_LICENSE_FILE".into(), license_file)); 253 env.push(("CARGO_PKG_LICENSE_FILE".into(), license_file));
257} 254}
diff --git a/crates/project_model/src/cargo_workspace.rs b/crates/project_model/src/cargo_workspace.rs
index 1d8d34a0b..f7241b711 100644
--- a/crates/project_model/src/cargo_workspace.rs
+++ b/crates/project_model/src/cargo_workspace.rs
@@ -1,5 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use std::path::PathBuf;
3use std::{convert::TryInto, ops, process::Command, sync::Arc}; 4use std::{convert::TryInto, ops, process::Command, sync::Arc};
4 5
5use anyhow::{Context, Result}; 6use anyhow::{Context, Result};
@@ -249,11 +250,12 @@ impl CargoWorkspace {
249 let edition = edition 250 let edition = edition
250 .parse::<Edition>() 251 .parse::<Edition>()
251 .with_context(|| format!("Failed to parse edition {}", edition))?; 252 .with_context(|| format!("Failed to parse edition {}", edition))?;
253
252 let pkg = packages.alloc(PackageData { 254 let pkg = packages.alloc(PackageData {
253 id: id.repr.clone(), 255 id: id.repr.clone(),
254 name: name.clone(), 256 name: name.clone(),
255 version: version.to_string(), 257 version: version.to_string(),
256 manifest: AbsPathBuf::assert(manifest_path.clone()), 258 manifest: AbsPathBuf::assert(PathBuf::from(&manifest_path)),
257 targets: Vec::new(), 259 targets: Vec::new(),
258 is_member, 260 is_member,
259 edition, 261 edition,
@@ -268,7 +270,7 @@ impl CargoWorkspace {
268 let tgt = targets.alloc(TargetData { 270 let tgt = targets.alloc(TargetData {
269 package: pkg, 271 package: pkg,
270 name: meta_tgt.name.clone(), 272 name: meta_tgt.name.clone(),
271 root: AbsPathBuf::assert(meta_tgt.src_path.clone()), 273 root: AbsPathBuf::assert(PathBuf::from(&meta_tgt.src_path)),
272 kind: TargetKind::new(meta_tgt.kind.as_slice()), 274 kind: TargetKind::new(meta_tgt.kind.as_slice()),
273 is_proc_macro, 275 is_proc_macro,
274 }); 276 });
@@ -305,7 +307,8 @@ impl CargoWorkspace {
305 packages[source].active_features.extend(node.features); 307 packages[source].active_features.extend(node.features);
306 } 308 }
307 309
308 let workspace_root = AbsPathBuf::assert(meta.workspace_root); 310 let workspace_root =
311 AbsPathBuf::assert(PathBuf::from(meta.workspace_root.into_os_string()));
309 let build_data_config = BuildDataConfig::new( 312 let build_data_config = BuildDataConfig::new(
310 cargo_toml.to_path_buf(), 313 cargo_toml.to_path_buf(),
311 config.clone(), 314 config.clone(),
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml
index b881cc229..8789f0852 100644
--- a/crates/rust-analyzer/Cargo.toml
+++ b/crates/rust-analyzer/Cargo.toml
@@ -24,7 +24,7 @@ jod-thread = "0.1.0"
24log = "0.4.8" 24log = "0.4.8"
25lsp-types = { version = "0.88.0", features = ["proposed"] } 25lsp-types = { version = "0.88.0", features = ["proposed"] }
26parking_lot = "0.11.0" 26parking_lot = "0.11.0"
27pico-args = "0.4.0" 27xflags = "0.1.2"
28oorandom = "11.1.2" 28oorandom = "11.1.2"
29rustc-hash = "1.1.0" 29rustc-hash = "1.1.0"
30serde = { version = "1.0.106", features = ["derive"] } 30serde = { version = "1.0.106", features = ["derive"] }
diff --git a/crates/rust-analyzer/src/bin/args.rs b/crates/rust-analyzer/src/bin/args.rs
deleted file mode 100644
index 164d94a30..000000000
--- a/crates/rust-analyzer/src/bin/args.rs
+++ /dev/null
@@ -1,274 +0,0 @@
1//! Command like parsing for rust-analyzer.
2//!
3//! If run started args, we run the LSP server loop. With a subcommand, we do a
4//! one-time batch processing.
5
6use std::{env, path::PathBuf};
7
8use anyhow::{bail, format_err, Result};
9use ide_ssr::{SsrPattern, SsrRule};
10use pico_args::Arguments;
11use rust_analyzer::cli::{AnalysisStatsCmd, BenchCmd, BenchWhat, Position, Verbosity};
12use vfs::AbsPathBuf;
13
14pub(crate) struct Args {
15 pub(crate) verbosity: Verbosity,
16 pub(crate) log_file: Option<PathBuf>,
17 pub(crate) no_buffering: bool,
18 pub(crate) command: Command,
19 #[allow(unused)]
20 pub(crate) wait_dbg: bool,
21}
22
23pub(crate) enum Command {
24 Parse { no_dump: bool },
25 Symbols,
26 Highlight { rainbow: bool },
27 AnalysisStats(AnalysisStatsCmd),
28 Bench(BenchCmd),
29 Diagnostics { path: PathBuf, load_output_dirs: bool, with_proc_macro: bool },
30 Ssr { rules: Vec<SsrRule> },
31 StructuredSearch { debug_snippet: Option<String>, patterns: Vec<SsrPattern> },
32 ProcMacro,
33 RunServer,
34 PrintConfigSchema,
35 Version,
36 Help,
37}
38
39const HELP: &str = "\
40rust-analyzer
41
42USAGE:
43 rust-analyzer [FLAGS] [COMMAND] [COMMAND_OPTIONS]
44
45FLAGS:
46 --version Print version
47 -h, --help Print this help
48
49 -v, --verbose
50 -vv, --spammy
51 -q, --quiet Set verbosity
52
53 --print-config-schema
54 Dump a LSP config JSON schema
55 --log-file <PATH> Log to the specified file instead of stderr
56 --no-log-buffering
57 Flush log records to the file immediately
58
59 --wait-dbg Wait until a debugger is attached to.
60 The flag is valid for debug builds only
61
62ENVIRONMENTAL VARIABLES:
63 RA_LOG Set log filter in env_logger format
64 RA_PROFILE Enable hierarchical profiler
65 RA_WAIT_DBG If set acts like a --wait-dbg flag
66
67COMMANDS:
68
69not specified Launch LSP server
70
71parse < main.rs Parse tree
72 --no-dump Suppress printing
73
74symbols < main.rs Parse input an print the list of symbols
75
76highlight < main.rs Highlight input as html
77 --rainbow Enable rainbow highlighting of identifiers
78
79analysis-stats <PATH> Batch typecheck project and print summary statistics
80 <PATH> Directory with Cargo.toml
81 --randomize Randomize order in which crates, modules, and items are processed
82 --parallel Run type inference in parallel
83 --memory-usage Collect memory usage statistics
84 -o, --only <PATH> Only analyze items matching this path
85 --with-deps Also analyze all dependencies
86 --load-output-dirs
87 Load OUT_DIR values by running `cargo check` before analysis
88 --with-proc-macro Use proc-macro-srv for proc-macro expanding
89
90analysis-bench <PATH> Benchmark specific analysis operation
91 <PATH> Directory with Cargo.toml
92 --highlight <PATH>
93 Compute syntax highlighting for this file
94 --complete <PATH:LINE:COLUMN>
95 Compute completions at this location
96 --goto-def <PATH:LINE:COLUMN>
97 Compute goto definition at this location
98 --memory-usage Collect memory usage statistics
99 --load-output-dirs
100 Load OUT_DIR values by running `cargo check` before analysis
101 --with-proc-macro Use proc-macro-srv for proc-macro expanding
102
103diagnostics <PATH>
104 <PATH> Directory with Cargo.toml
105 --load-output-dirs
106 Load OUT_DIR values by running `cargo check` before analysis
107 --with-proc-macro Use proc-macro-srv for proc-macro expanding
108
109ssr [RULE...]
110 <RULE> A structured search replace rule (`$a.foo($b) ==> bar($a, $b)`)
111
112search [PATTERN..]
113 <PATTERN> A structured search replace pattern (`$a.foo($b)`)
114 --debug <snippet> Prints debug information for any nodes with source exactly
115 equal to <snippet>
116";
117
118impl Args {
119 pub(crate) fn parse() -> Result<Args> {
120 let mut matches = Arguments::from_env();
121
122 if matches.contains("--version") {
123 finish_args(matches)?;
124 return Ok(Args {
125 verbosity: Verbosity::Normal,
126 log_file: None,
127 command: Command::Version,
128 no_buffering: false,
129 wait_dbg: false,
130 });
131 }
132
133 let verbosity = match (
134 matches.contains(["-vv", "--spammy"]),
135 matches.contains(["-v", "--verbose"]),
136 matches.contains(["-q", "--quiet"]),
137 ) {
138 (true, _, true) => bail!("Invalid flags: -q conflicts with -vv"),
139 (true, _, false) => Verbosity::Spammy,
140 (false, false, false) => Verbosity::Normal,
141 (false, false, true) => Verbosity::Quiet,
142 (false, true, false) => Verbosity::Verbose,
143 (false, true, true) => bail!("Invalid flags: -q conflicts with -v"),
144 };
145 let log_file = matches.opt_value_from_str("--log-file")?;
146 let no_buffering = matches.contains("--no-log-buffering");
147 let wait_dbg = matches.contains("--wait-dbg");
148
149 if matches.contains(["-h", "--help"]) {
150 eprintln!("{}", HELP);
151 return Ok(Args {
152 verbosity,
153 log_file: None,
154 command: Command::Help,
155 no_buffering,
156 wait_dbg,
157 });
158 }
159
160 if matches.contains("--print-config-schema") {
161 return Ok(Args {
162 verbosity,
163 log_file,
164 command: Command::PrintConfigSchema,
165 no_buffering,
166 wait_dbg,
167 });
168 }
169
170 let subcommand = match matches.subcommand()? {
171 Some(it) => it,
172 None => {
173 finish_args(matches)?;
174 return Ok(Args {
175 verbosity,
176 log_file,
177 command: Command::RunServer,
178 no_buffering,
179 wait_dbg,
180 });
181 }
182 };
183 let command = match subcommand.as_str() {
184 "parse" => Command::Parse { no_dump: matches.contains("--no-dump") },
185 "symbols" => Command::Symbols,
186 "highlight" => Command::Highlight { rainbow: matches.contains("--rainbow") },
187 "analysis-stats" => Command::AnalysisStats(AnalysisStatsCmd {
188 randomize: matches.contains("--randomize"),
189 parallel: matches.contains("--parallel"),
190 memory_usage: matches.contains("--memory-usage"),
191 only: matches.opt_value_from_str(["-o", "--only"])?,
192 with_deps: matches.contains("--with-deps"),
193 load_output_dirs: matches.contains("--load-output-dirs"),
194 with_proc_macro: matches.contains("--with-proc-macro"),
195 path: matches
196 .opt_free_from_str()?
197 .ok_or_else(|| format_err!("expected positional argument"))?,
198 }),
199 "analysis-bench" => Command::Bench(BenchCmd {
200 what: {
201 let highlight_path: Option<String> =
202 matches.opt_value_from_str("--highlight")?;
203 let complete_path: Option<Position> =
204 matches.opt_value_from_str("--complete")?;
205 let goto_def_path: Option<Position> =
206 matches.opt_value_from_str("--goto-def")?;
207 match (highlight_path, complete_path, goto_def_path) {
208 (Some(path), None, None) => {
209 let path = env::current_dir().unwrap().join(path);
210 BenchWhat::Highlight { path: AbsPathBuf::assert(path) }
211 }
212 (None, Some(position), None) => BenchWhat::Complete(position),
213 (None, None, Some(position)) => BenchWhat::GotoDef(position),
214 _ => panic!(
215 "exactly one of `--highlight`, `--complete` or `--goto-def` must be set"
216 ),
217 }
218 },
219 memory_usage: matches.contains("--memory-usage"),
220 load_output_dirs: matches.contains("--load-output-dirs"),
221 with_proc_macro: matches.contains("--with-proc-macro"),
222 path: matches
223 .opt_free_from_str()?
224 .ok_or_else(|| format_err!("expected positional argument"))?,
225 }),
226 "diagnostics" => Command::Diagnostics {
227 load_output_dirs: matches.contains("--load-output-dirs"),
228 with_proc_macro: matches.contains("--with-proc-macro"),
229 path: matches
230 .opt_free_from_str()?
231 .ok_or_else(|| format_err!("expected positional argument"))?,
232 },
233 "proc-macro" => Command::ProcMacro,
234 "ssr" => Command::Ssr {
235 rules: {
236 let mut acc = Vec::new();
237 while let Some(rule) = matches.opt_free_from_str()? {
238 acc.push(rule);
239 }
240 acc
241 },
242 },
243 "search" => Command::StructuredSearch {
244 debug_snippet: matches.opt_value_from_str("--debug")?,
245 patterns: {
246 let mut acc = Vec::new();
247 while let Some(rule) = matches.opt_free_from_str()? {
248 acc.push(rule);
249 }
250 acc
251 },
252 },
253 _ => {
254 eprintln!("{}", HELP);
255 return Ok(Args {
256 verbosity,
257 log_file: None,
258 command: Command::Help,
259 no_buffering,
260 wait_dbg,
261 });
262 }
263 };
264 finish_args(matches)?;
265 Ok(Args { verbosity, log_file, command, no_buffering, wait_dbg })
266 }
267}
268
269fn finish_args(args: Arguments) -> Result<()> {
270 if !args.finish().is_empty() {
271 bail!("Unused arguments.");
272 }
273 Ok(())
274}
diff --git a/crates/rust-analyzer/src/bin/flags.rs b/crates/rust-analyzer/src/bin/flags.rs
new file mode 100644
index 000000000..244912d26
--- /dev/null
+++ b/crates/rust-analyzer/src/bin/flags.rs
@@ -0,0 +1,251 @@
1//! Grammar for the command-line arguments.
2#![allow(unreachable_pub)]
3use std::{env, path::PathBuf};
4
5use ide_ssr::{SsrPattern, SsrRule};
6use rust_analyzer::cli::{BenchWhat, Position, Verbosity};
7use vfs::AbsPathBuf;
8
9xflags::args_parser! {
10 /// LSP server for the Rust programming language.
11 cmd rust-analyzer {
12 /// Verbosity level, can be repeated multiple times.
13 repeated -v, --verbose
14 /// Verbosity level.
15 optional -q, --quiet
16
17 /// Log to the specified file instead of stderr.
18 optional --log-file path: PathBuf
19 /// Flush log records to the file immediately.
20 optional --no-log-buffering
21
22 /// Wait until a debugger is attached to (requires debug build).
23 optional --wait-dbg
24
25 default cmd lsp-server {
26 /// Print version.
27 optional --version
28 /// Print help.
29 optional -h, --help
30
31 /// Dump a LSP config JSON schema.
32 optional --print-config-schema
33 }
34
35 /// Parse stdin.
36 cmd parse {
37 /// Suppress printing.
38 optional --no-dump
39 }
40
41 /// Parse stdin and print the list of symbols.
42 cmd symbols {}
43
44 /// Highlight stdin as html.
45 cmd highlight {
46 /// Enable rainbow highlighting of identifiers.
47 optional --rainbow
48 }
49
50 /// Batch typecheck project and print summary statistics
51 cmd analysis-stats
52 /// Directory with Cargo.toml.
53 required path: PathBuf
54 {
55 /// Randomize order in which crates, modules, and items are processed.
56 optional --randomize
57 /// Run type inference in parallel.
58 optional --parallel
59 /// Collect memory usage statistics.
60 optional --memory-usage
61
62 /// Only analyze items matching this path.
63 optional -o, --only path: String
64 /// Also analyze all dependencies.
65 optional --with-deps
66
67 /// Load OUT_DIR values by running `cargo check` before analysis.
68 optional --load-output-dirs
69 /// Use proc-macro-srv for proc-macro expanding.
70 optional --with-proc-macro
71 }
72
73 /// Benchmark specific analysis operation
74 cmd analysis-bench
75 /// Directory with Cargo.toml.
76 required path: PathBuf
77 {
78 /// Collect memory usage statistics.
79 optional --memory-usage
80
81 /// Compute syntax highlighting for this file
82 optional --highlight path: PathBuf
83 /// Compute completions at file:line:column location.
84 optional --complete location: Position
85 /// Compute goto definition at file:line:column location.
86 optional --goto-def location: Position
87
88 /// Load OUT_DIR values by running `cargo check` before analysis.
89 optional --load-output-dirs
90 /// Use proc-macro-srv for proc-macro expanding.
91 optional --with-proc-macro
92 }
93
94 cmd diagnostics
95 /// Directory with Cargo.toml.
96 required path: PathBuf
97 {
98 /// Load OUT_DIR values by running `cargo check` before analysis.
99 optional --load-output-dirs
100 /// Use proc-macro-srv for proc-macro expanding.
101 optional --with-proc-macro
102 }
103
104 cmd ssr
105 /// A structured search replace rule (`$a.foo($b) ==> bar($a, $b)`)
106 repeated rule: SsrRule
107 {}
108
109 cmd search
110 /// A structured search replace pattern (`$a.foo($b)`)
111 repeated pattern: SsrPattern
112 {
113 /// Prints debug information for any nodes with source exactly equal to snippet.
114 optional --debug snippet: String
115 }
116
117 cmd proc-macro {}
118 }
119}
120
121// generated start
122// The following code is generated by `xflags` macro.
123// Run `env XFLAGS_DUMP= cargo build` to regenerate.
124#[derive(Debug)]
125pub struct RustAnalyzer {
126 pub verbose: u32,
127 pub quiet: bool,
128 pub log_file: Option<PathBuf>,
129 pub no_log_buffering: bool,
130 pub wait_dbg: bool,
131 pub subcommand: RustAnalyzerCmd,
132}
133
134#[derive(Debug)]
135pub enum RustAnalyzerCmd {
136 LspServer(LspServer),
137 Parse(Parse),
138 Symbols(Symbols),
139 Highlight(Highlight),
140 AnalysisStats(AnalysisStats),
141 AnalysisBench(AnalysisBench),
142 Diagnostics(Diagnostics),
143 Ssr(Ssr),
144 Search(Search),
145 ProcMacro(ProcMacro),
146}
147
148#[derive(Debug)]
149pub struct LspServer {
150 pub version: bool,
151 pub help: bool,
152 pub print_config_schema: bool,
153}
154
155#[derive(Debug)]
156pub struct Parse {
157 pub no_dump: bool,
158}
159
160#[derive(Debug)]
161pub struct Symbols {}
162
163#[derive(Debug)]
164pub struct Highlight {
165 pub rainbow: bool,
166}
167
168#[derive(Debug)]
169pub struct AnalysisStats {
170 pub path: PathBuf,
171
172 pub randomize: bool,
173 pub parallel: bool,
174 pub memory_usage: bool,
175 pub only: Option<String>,
176 pub with_deps: bool,
177 pub load_output_dirs: bool,
178 pub with_proc_macro: bool,
179}
180
181#[derive(Debug)]
182pub struct AnalysisBench {
183 pub path: PathBuf,
184
185 pub memory_usage: bool,
186 pub highlight: Option<PathBuf>,
187 pub complete: Option<Position>,
188 pub goto_def: Option<Position>,
189 pub load_output_dirs: bool,
190 pub with_proc_macro: bool,
191}
192
193#[derive(Debug)]
194pub struct Diagnostics {
195 pub path: PathBuf,
196
197 pub load_output_dirs: bool,
198 pub with_proc_macro: bool,
199}
200
201#[derive(Debug)]
202pub struct Ssr {
203 pub rule: Vec<SsrRule>,
204}
205
206#[derive(Debug)]
207pub struct Search {
208 pub pattern: Vec<SsrPattern>,
209
210 pub debug: Option<String>,
211}
212
213#[derive(Debug)]
214pub struct ProcMacro {}
215
216impl RustAnalyzer {
217 pub const HELP: &'static str = Self::_HELP;
218
219 pub fn from_env() -> xflags::Result<Self> {
220 let mut p = xflags::rt::Parser::new_from_env();
221 Self::_parse(&mut p)
222 }
223}
224// generated end
225
226impl RustAnalyzer {
227 pub(crate) fn verbosity(&self) -> Verbosity {
228 if self.quiet {
229 return Verbosity::Quiet;
230 }
231 match self.verbose {
232 0 => Verbosity::Normal,
233 1 => Verbosity::Verbose,
234 _ => Verbosity::Spammy,
235 }
236 }
237}
238
239impl AnalysisBench {
240 pub(crate) fn what(&self) -> BenchWhat {
241 match (&self.highlight, &self.complete, &self.goto_def) {
242 (Some(path), None, None) => {
243 let path = env::current_dir().unwrap().join(path);
244 BenchWhat::Highlight { path: AbsPathBuf::assert(path) }
245 }
246 (None, Some(position), None) => BenchWhat::Complete(position.clone()),
247 (None, None, Some(position)) => BenchWhat::GotoDef(position.clone()),
248 _ => panic!("exactly one of `--highlight`, `--complete` or `--goto-def` must be set"),
249 }
250 }
251}
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs
index 89482b952..288847980 100644
--- a/crates/rust-analyzer/src/bin/main.rs
+++ b/crates/rust-analyzer/src/bin/main.rs
@@ -1,14 +1,20 @@
1//! Driver for rust-analyzer. 1//! Driver for rust-analyzer.
2//! 2//!
3//! Based on cli flags, either spawns an LSP server, or runs a batch analysis 3//! Based on cli flags, either spawns an LSP server, or runs a batch analysis
4mod args; 4mod flags;
5mod logger; 5mod logger;
6 6
7use std::{convert::TryFrom, env, fs, path::PathBuf, process}; 7use std::{convert::TryFrom, env, fs, path::Path, process};
8 8
9use lsp_server::Connection; 9use lsp_server::Connection;
10use project_model::ProjectManifest; 10use project_model::ProjectManifest;
11use rust_analyzer::{cli, config::Config, from_json, lsp_ext::supports_utf8, Result}; 11use rust_analyzer::{
12 cli::{self, AnalysisStatsCmd, BenchCmd},
13 config::Config,
14 from_json,
15 lsp_ext::supports_utf8,
16 Result,
17};
12use vfs::AbsPathBuf; 18use vfs::AbsPathBuf;
13 19
14#[cfg(all(feature = "mimalloc"))] 20#[cfg(all(feature = "mimalloc"))]
@@ -28,10 +34,10 @@ fn main() {
28} 34}
29 35
30fn try_main() -> Result<()> { 36fn try_main() -> Result<()> {
31 let args = args::Args::parse()?; 37 let flags = flags::RustAnalyzer::from_env()?;
32 38
33 #[cfg(debug_assertions)] 39 #[cfg(debug_assertions)]
34 if args.wait_dbg || env::var("RA_WAIT_DBG").is_ok() { 40 if flags.wait_dbg || env::var("RA_WAIT_DBG").is_ok() {
35 #[allow(unused_mut)] 41 #[allow(unused_mut)]
36 let mut d = 4; 42 let mut d = 4;
37 while d == 4 { 43 while d == 4 {
@@ -39,35 +45,62 @@ fn try_main() -> Result<()> {
39 } 45 }
40 } 46 }
41 47
42 setup_logging(args.log_file, args.no_buffering)?; 48 setup_logging(flags.log_file.as_deref(), flags.no_log_buffering)?;
43 match args.command { 49 let verbosity = flags.verbosity();
44 args::Command::RunServer => run_server()?, 50
45 args::Command::PrintConfigSchema => { 51 match flags.subcommand {
46 println!("{:#}", Config::json_schema()); 52 flags::RustAnalyzerCmd::LspServer(cmd) => {
53 if cmd.print_config_schema {
54 println!("{:#}", Config::json_schema());
55 return Ok(());
56 }
57 if cmd.version {
58 println!("rust-analyzer {}", env!("REV"));
59 return Ok(());
60 }
61 if cmd.help {
62 println!("{}", flags::RustAnalyzer::HELP);
63 return Ok(());
64 }
65 run_server()?
47 } 66 }
48 args::Command::ProcMacro => proc_macro_srv::cli::run()?, 67 flags::RustAnalyzerCmd::ProcMacro(_) => proc_macro_srv::cli::run()?,
49 68 flags::RustAnalyzerCmd::Parse(cmd) => cli::parse(cmd.no_dump)?,
50 args::Command::Parse { no_dump } => cli::parse(no_dump)?, 69 flags::RustAnalyzerCmd::Symbols(_) => cli::symbols()?,
51 args::Command::Symbols => cli::symbols()?, 70 flags::RustAnalyzerCmd::Highlight(cmd) => cli::highlight(cmd.rainbow)?,
52 args::Command::Highlight { rainbow } => cli::highlight(rainbow)?, 71 flags::RustAnalyzerCmd::AnalysisStats(cmd) => AnalysisStatsCmd {
53 args::Command::AnalysisStats(cmd) => cmd.run(args.verbosity)?, 72 randomize: cmd.randomize,
54 args::Command::Bench(cmd) => cmd.run(args.verbosity)?, 73 parallel: cmd.parallel,
55 args::Command::Diagnostics { path, load_output_dirs, with_proc_macro } => { 74 memory_usage: cmd.memory_usage,
56 cli::diagnostics(path.as_ref(), load_output_dirs, with_proc_macro)? 75 only: cmd.only,
76 with_deps: cmd.with_deps,
77 path: cmd.path,
78 load_output_dirs: cmd.load_output_dirs,
79 with_proc_macro: cmd.with_proc_macro,
57 } 80 }
58 args::Command::Ssr { rules } => { 81 .run(verbosity)?,
59 cli::apply_ssr_rules(rules)?; 82 flags::RustAnalyzerCmd::AnalysisBench(cmd) => {
83 let what = cmd.what();
84 BenchCmd {
85 memory_usage: cmd.memory_usage,
86 path: cmd.path,
87 load_output_dirs: cmd.load_output_dirs,
88 with_proc_macro: cmd.with_proc_macro,
89 what,
90 }
91 .run(verbosity)?
60 } 92 }
61 args::Command::StructuredSearch { patterns, debug_snippet } => { 93
62 cli::search_for_patterns(patterns, debug_snippet)?; 94 flags::RustAnalyzerCmd::Diagnostics(cmd) => {
95 cli::diagnostics(&cmd.path, cmd.load_output_dirs, cmd.with_proc_macro)?
63 } 96 }
64 args::Command::Version => println!("rust-analyzer {}", env!("REV")), 97 flags::RustAnalyzerCmd::Ssr(cmd) => cli::apply_ssr_rules(cmd.rule)?,
65 args::Command::Help => {} 98 flags::RustAnalyzerCmd::Search(cmd) => cli::search_for_patterns(cmd.pattern, cmd.debug)?,
66 } 99 }
67 Ok(()) 100 Ok(())
68} 101}
69 102
70fn setup_logging(log_file: Option<PathBuf>, no_buffering: bool) -> Result<()> { 103fn setup_logging(log_file: Option<&Path>, no_buffering: bool) -> Result<()> {
71 env::set_var("RUST_BACKTRACE", "short"); 104 env::set_var("RUST_BACKTRACE", "short");
72 105
73 let log_file = match log_file { 106 let log_file = match log_file {
diff --git a/crates/rust-analyzer/src/cli/analysis_bench.rs b/crates/rust-analyzer/src/cli/analysis_bench.rs
index 8991f3bdb..3bd7e678d 100644
--- a/crates/rust-analyzer/src/cli/analysis_bench.rs
+++ b/crates/rust-analyzer/src/cli/analysis_bench.rs
@@ -35,6 +35,7 @@ pub enum BenchWhat {
35 GotoDef(Position), 35 GotoDef(Position),
36} 36}
37 37
38#[derive(Debug, Clone)]
38pub struct Position { 39pub struct Position {
39 pub path: AbsPathBuf, 40 pub path: AbsPathBuf,
40 pub line: u32, 41 pub line: u32,
@@ -68,7 +69,7 @@ impl BenchCmd {
68 load_out_dirs_from_check: self.load_output_dirs, 69 load_out_dirs_from_check: self.load_output_dirs,
69 with_proc_macro: self.with_proc_macro, 70 with_proc_macro: self.with_proc_macro,
70 }; 71 };
71 let (mut host, vfs) = 72 let (mut host, vfs, _proc_macro) =
72 load_workspace_at(&self.path, &cargo_config, &load_cargo_config, &|_| {})?; 73 load_workspace_at(&self.path, &cargo_config, &load_cargo_config, &|_| {})?;
73 eprintln!("{:?}\n", start.elapsed()); 74 eprintln!("{:?}\n", start.elapsed());
74 75
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index 9072d8944..ad0759bda 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -64,7 +64,7 @@ impl AnalysisStatsCmd {
64 load_out_dirs_from_check: self.load_output_dirs, 64 load_out_dirs_from_check: self.load_output_dirs,
65 with_proc_macro: self.with_proc_macro, 65 with_proc_macro: self.with_proc_macro,
66 }; 66 };
67 let (host, vfs) = 67 let (host, vfs, _proc_macro) =
68 load_workspace_at(&self.path, &cargo_config, &load_cargo_config, &|_| {})?; 68 load_workspace_at(&self.path, &cargo_config, &load_cargo_config, &|_| {})?;
69 let db = host.raw_database(); 69 let db = host.raw_database();
70 eprintln!("{:<20} {}", "Database loaded:", db_load_sw.elapsed()); 70 eprintln!("{:<20} {}", "Database loaded:", db_load_sw.elapsed());
diff --git a/crates/rust-analyzer/src/cli/diagnostics.rs b/crates/rust-analyzer/src/cli/diagnostics.rs
index 876f6c44f..8b985716b 100644
--- a/crates/rust-analyzer/src/cli/diagnostics.rs
+++ b/crates/rust-analyzer/src/cli/diagnostics.rs
@@ -35,7 +35,8 @@ pub fn diagnostics(
35) -> Result<()> { 35) -> Result<()> {
36 let cargo_config = Default::default(); 36 let cargo_config = Default::default();
37 let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check, with_proc_macro }; 37 let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check, with_proc_macro };
38 let (host, _vfs) = load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {})?; 38 let (host, _vfs, _proc_macro) =
39 load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {})?;
39 let db = host.raw_database(); 40 let db = host.raw_database();
40 let analysis = host.analysis(); 41 let analysis = host.analysis();
41 42
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs
index 23442afac..310c36904 100644
--- a/crates/rust-analyzer/src/cli/load_cargo.rs
+++ b/crates/rust-analyzer/src/cli/load_cargo.rs
@@ -23,7 +23,7 @@ pub fn load_workspace_at(
23 cargo_config: &CargoConfig, 23 cargo_config: &CargoConfig,
24 load_config: &LoadCargoConfig, 24 load_config: &LoadCargoConfig,
25 progress: &dyn Fn(String), 25 progress: &dyn Fn(String),
26) -> Result<(AnalysisHost, vfs::Vfs)> { 26) -> Result<(AnalysisHost, vfs::Vfs, Option<ProcMacroClient>)> {
27 let root = AbsPathBuf::assert(std::env::current_dir()?.join(root)); 27 let root = AbsPathBuf::assert(std::env::current_dir()?.join(root));
28 let root = ProjectManifest::discover_single(&root)?; 28 let root = ProjectManifest::discover_single(&root)?;
29 let workspace = ProjectWorkspace::load(root, cargo_config, progress)?; 29 let workspace = ProjectWorkspace::load(root, cargo_config, progress)?;
@@ -35,7 +35,7 @@ pub fn load_workspace(
35 ws: ProjectWorkspace, 35 ws: ProjectWorkspace,
36 config: &LoadCargoConfig, 36 config: &LoadCargoConfig,
37 progress: &dyn Fn(String), 37 progress: &dyn Fn(String),
38) -> Result<(AnalysisHost, vfs::Vfs)> { 38) -> Result<(AnalysisHost, vfs::Vfs, Option<ProcMacroClient>)> {
39 let (sender, receiver) = unbounded(); 39 let (sender, receiver) = unbounded();
40 let mut vfs = vfs::Vfs::default(); 40 let mut vfs = vfs::Vfs::default();
41 let mut loader = { 41 let mut loader = {
@@ -80,7 +80,7 @@ pub fn load_workspace(
80 log::debug!("crate graph: {:?}", crate_graph); 80 log::debug!("crate graph: {:?}", crate_graph);
81 let host = 81 let host =
82 load_crate_graph(crate_graph, project_folders.source_root_config, &mut vfs, &receiver); 82 load_crate_graph(crate_graph, project_folders.source_root_config, &mut vfs, &receiver);
83 Ok((host, vfs)) 83 Ok((host, vfs, proc_macro_client))
84} 84}
85 85
86fn load_crate_graph( 86fn load_crate_graph(
@@ -138,7 +138,8 @@ mod tests {
138 let cargo_config = Default::default(); 138 let cargo_config = Default::default();
139 let load_cargo_config = 139 let load_cargo_config =
140 LoadCargoConfig { load_out_dirs_from_check: false, with_proc_macro: false }; 140 LoadCargoConfig { load_out_dirs_from_check: false, with_proc_macro: false };
141 let (host, _vfs) = load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {})?; 141 let (host, _vfs, _proc_macro) =
142 load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {})?;
142 143
143 let n_crates = Crate::all(host.raw_database()).len(); 144 let n_crates = Crate::all(host.raw_database()).len();
144 // RA has quite a few crates, but the exact count doesn't matter 145 // RA has quite a few crates, but the exact count doesn't matter
diff --git a/crates/rust-analyzer/src/cli/ssr.rs b/crates/rust-analyzer/src/cli/ssr.rs
index 71a8f8fb9..79f426fff 100644
--- a/crates/rust-analyzer/src/cli/ssr.rs
+++ b/crates/rust-analyzer/src/cli/ssr.rs
@@ -11,7 +11,7 @@ pub fn apply_ssr_rules(rules: Vec<SsrRule>) -> Result<()> {
11 let cargo_config = Default::default(); 11 let cargo_config = Default::default();
12 let load_cargo_config = 12 let load_cargo_config =
13 LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro: true }; 13 LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro: true };
14 let (host, vfs) = 14 let (host, vfs, _proc_macro) =
15 load_workspace_at(&std::env::current_dir()?, &cargo_config, &load_cargo_config, &|_| {})?; 15 load_workspace_at(&std::env::current_dir()?, &cargo_config, &load_cargo_config, &|_| {})?;
16 let db = host.raw_database(); 16 let db = host.raw_database();
17 let mut match_finder = MatchFinder::at_first_file(db)?; 17 let mut match_finder = MatchFinder::at_first_file(db)?;
@@ -38,7 +38,7 @@ pub fn search_for_patterns(patterns: Vec<SsrPattern>, debug_snippet: Option<Stri
38 let cargo_config = Default::default(); 38 let cargo_config = Default::default();
39 let load_cargo_config = 39 let load_cargo_config =
40 LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro: true }; 40 LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro: true };
41 let (host, _vfs) = 41 let (host, _vfs, _proc_macro) =
42 load_workspace_at(&std::env::current_dir()?, &cargo_config, &load_cargo_config, &|_| {})?; 42 load_workspace_at(&std::env::current_dir()?, &cargo_config, &load_cargo_config, &|_| {})?;
43 let db = host.raw_database(); 43 let db = host.raw_database();
44 let mut match_finder = MatchFinder::at_first_file(db)?; 44 let mut match_finder = MatchFinder::at_first_file(db)?;
diff --git a/crates/rust-analyzer/src/diagnostics/to_proto.rs b/crates/rust-analyzer/src/diagnostics/to_proto.rs
index 0ed87fe3e..0ad832c0e 100644
--- a/crates/rust-analyzer/src/diagnostics/to_proto.rs
+++ b/crates/rust-analyzer/src/diagnostics/to_proto.rs
@@ -29,7 +29,7 @@ fn diagnostic_severity(
29 }, 29 },
30 DiagnosticLevel::Note => lsp_types::DiagnosticSeverity::Information, 30 DiagnosticLevel::Note => lsp_types::DiagnosticSeverity::Information,
31 DiagnosticLevel::Help => lsp_types::DiagnosticSeverity::Hint, 31 DiagnosticLevel::Help => lsp_types::DiagnosticSeverity::Hint,
32 DiagnosticLevel::Unknown => return None, 32 _ => return None,
33 }; 33 };
34 Some(res) 34 Some(res)
35} 35}
diff --git a/crates/rust-analyzer/tests/rust-analyzer/main.rs b/crates/rust-analyzer/tests/rust-analyzer/main.rs
index 80bde29b9..7545b4a34 100644
--- a/crates/rust-analyzer/tests/rust-analyzer/main.rs
+++ b/crates/rust-analyzer/tests/rust-analyzer/main.rs
@@ -54,7 +54,9 @@ version = "0.0.0"
54use std::collections::Spam; 54use std::collections::Spam;
55"#, 55"#,
56 ) 56 )
57 .with_sysroot(true) 57 .with_config(serde_json::json!({
58 "cargo": { "noSysroot": false }
59 }))
58 .server() 60 .server()
59 .wait_until_workspace_is_loaded(); 61 .wait_until_workspace_is_loaded();
60 62
@@ -451,7 +453,9 @@ fn main() {{}}
451"#, 453"#,
452 librs, libs 454 librs, libs
453 )) 455 ))
454 .with_sysroot(true) 456 .with_config(serde_json::json!({
457 "cargo": { "noSysroot": false }
458 }))
455 .server() 459 .server()
456 .wait_until_workspace_is_loaded(); 460 .wait_until_workspace_is_loaded();
457 461
@@ -574,7 +578,10 @@ fn main() {
574"###, 578"###,
575 ) 579 )
576 .with_config(serde_json::json!({ 580 .with_config(serde_json::json!({
577 "cargo": { "loadOutDirsFromCheck": true } 581 "cargo": {
582 "loadOutDirsFromCheck": true,
583 "noSysroot": true,
584 }
578 })) 585 }))
579 .server() 586 .server()
580 .wait_until_workspace_is_loaded(); 587 .wait_until_workspace_is_loaded();
@@ -717,7 +724,10 @@ pub fn foo(_input: TokenStream) -> TokenStream {
717"###, 724"###,
718 ) 725 )
719 .with_config(serde_json::json!({ 726 .with_config(serde_json::json!({
720 "cargo": { "loadOutDirsFromCheck": true }, 727 "cargo": {
728 "loadOutDirsFromCheck": true,
729 "noSysroot": true,
730 },
721 "procMacro": { 731 "procMacro": {
722 "enable": true, 732 "enable": true,
723 "server": PathBuf::from(env!("CARGO_BIN_EXE_rust-analyzer")), 733 "server": PathBuf::from(env!("CARGO_BIN_EXE_rust-analyzer")),
diff --git a/crates/rust-analyzer/tests/rust-analyzer/support.rs b/crates/rust-analyzer/tests/rust-analyzer/support.rs
index 453ce4fa8..6b774073d 100644
--- a/crates/rust-analyzer/tests/rust-analyzer/support.rs
+++ b/crates/rust-analyzer/tests/rust-analyzer/support.rs
@@ -20,7 +20,6 @@ use crate::testdir::TestDir;
20 20
21pub(crate) struct Project<'a> { 21pub(crate) struct Project<'a> {
22 fixture: &'a str, 22 fixture: &'a str,
23 with_sysroot: bool,
24 tmp_dir: Option<TestDir>, 23 tmp_dir: Option<TestDir>,
25 roots: Vec<PathBuf>, 24 roots: Vec<PathBuf>,
26 config: serde_json::Value, 25 config: serde_json::Value,
@@ -32,8 +31,10 @@ impl<'a> Project<'a> {
32 fixture, 31 fixture,
33 tmp_dir: None, 32 tmp_dir: None,
34 roots: vec![], 33 roots: vec![],
35 with_sysroot: false, 34 config: serde_json::json!({
36 config: serde_json::Value::Null, 35 // Loading standard library is costly, let's ignore it by default
36 "cargo": { "noSysroot": true }
37 }),
37 } 38 }
38 } 39 }
39 40
@@ -47,11 +48,6 @@ impl<'a> Project<'a> {
47 self 48 self
48 } 49 }
49 50
50 pub(crate) fn with_sysroot(mut self, yes: bool) -> Project<'a> {
51 self.with_sysroot = yes;
52 self
53 }
54
55 pub(crate) fn with_config(mut self, config: serde_json::Value) -> Project<'a> { 51 pub(crate) fn with_config(mut self, config: serde_json::Value) -> Project<'a> {
56 self.config = config; 52 self.config = config;
57 self 53 self
diff --git a/crates/syntax/src/ast/edit.rs b/crates/syntax/src/ast/edit.rs
index 824ebf41c..0b3b76d4a 100644
--- a/crates/syntax/src/ast/edit.rs
+++ b/crates/syntax/src/ast/edit.rs
@@ -595,11 +595,14 @@ impl ops::Add<u8> for IndentLevel {
595 595
596impl IndentLevel { 596impl IndentLevel {
597 pub fn from_node(node: &SyntaxNode) -> IndentLevel { 597 pub fn from_node(node: &SyntaxNode) -> IndentLevel {
598 let first_token = match node.first_token() { 598 match node.first_token() {
599 Some(it) => it, 599 Some(it) => Self::from_token(&it),
600 None => return IndentLevel(0), 600 None => return IndentLevel(0),
601 }; 601 }
602 for ws in prev_tokens(first_token).filter_map(ast::Whitespace::cast) { 602 }
603
604 pub fn from_token(token: &SyntaxToken) -> IndentLevel {
605 for ws in prev_tokens(token.clone()).filter_map(ast::Whitespace::cast) {
603 let text = ws.syntax().text(); 606 let text = ws.syntax().text();
604 if let Some(pos) = text.rfind('\n') { 607 if let Some(pos) = text.rfind('\n') {
605 let level = text[pos + 1..].chars().count() / 4; 608 let level = text[pos + 1..].chars().count() / 4;
diff --git a/crates/syntax/src/ast/token_ext.rs b/crates/syntax/src/ast/token_ext.rs
index 044e3e5e8..977eb8181 100644
--- a/crates/syntax/src/ast/token_ext.rs
+++ b/crates/syntax/src/ast/token_ext.rs
@@ -85,8 +85,9 @@ pub enum CommentPlacement {
85} 85}
86 86
87impl CommentKind { 87impl CommentKind {
88 const BY_PREFIX: [(&'static str, CommentKind); 8] = [ 88 const BY_PREFIX: [(&'static str, CommentKind); 9] = [
89 ("/**/", CommentKind { shape: CommentShape::Block, doc: None }), 89 ("/**/", CommentKind { shape: CommentShape::Block, doc: None }),
90 ("/***", CommentKind { shape: CommentShape::Block, doc: None }),
90 ("////", CommentKind { shape: CommentShape::Line, doc: None }), 91 ("////", CommentKind { shape: CommentShape::Line, doc: None }),
91 ("///", CommentKind { shape: CommentShape::Line, doc: Some(CommentPlacement::Outer) }), 92 ("///", CommentKind { shape: CommentShape::Line, doc: Some(CommentPlacement::Outer) }),
92 ("//!", CommentKind { shape: CommentShape::Line, doc: Some(CommentPlacement::Inner) }), 93 ("//!", CommentKind { shape: CommentShape::Line, doc: Some(CommentPlacement::Inner) }),