diff options
Diffstat (limited to 'crates')
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] |
13 | crossbeam-channel = "0.5.0" | 13 | crossbeam-channel = "0.5.0" |
14 | log = "0.4.8" | 14 | log = "0.4.8" |
15 | cargo_metadata = "0.12.2" | 15 | cargo_metadata = "0.13" |
16 | serde_json = "1.0.48" | 16 | serde_json = "1.0.48" |
17 | jod-thread = "0.1.1" | 17 | jod-thread = "0.1.1" |
18 | 18 | ||
19 | toolchain = { path = "../toolchain", version = "0.0.0" } | 19 | toolchain = { path = "../toolchain", version = "0.0.0" } |
20 | stdx = { path = "../stdx", version = "0.0.0" } | 20 | stdx = { 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 | }; |
38 | use rustc_hash::FxHashSet; | 38 | use rustc_hash::FxHashSet; |
39 | use stdx::{format_to, impl_from}; | 39 | use stdx::{format_to, impl_from}; |
@@ -836,7 +836,7 @@ pub enum Access { | |||
836 | impl From<Mutability> for Access { | 836 | impl 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)] |
2011 | pub struct Callable { | 1978 | pub 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::{ | |||
20 | use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; | 20 | use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; |
21 | use hir_ty::{ | 21 | use 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 | }; |
25 | use syntax::{ | 25 | use 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; | |||
24 | use crate::{ | 24 | use 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 @@ | |||
6 | use std::fmt; | 6 | use std::fmt; |
7 | 7 | ||
8 | use hir_expand::name::{name, AsName, Name}; | 8 | use 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)] |
11 | pub enum Signedness { | 11 | pub 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, |
17 | pub 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)] | ||
27 | pub enum FloatBitness { | ||
28 | X32, | ||
29 | X64, | ||
30 | } | 18 | } |
31 | 19 | ||
32 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 20 | /// Different unsigned int types. |
33 | pub struct BuiltinInt { | 21 | #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] |
34 | pub signedness: Signedness, | 22 | pub 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)] |
39 | pub struct BuiltinFloat { | 32 | pub 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] |
115 | impl BuiltinInt { | 111 | impl 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] | ||
128 | impl 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] |
154 | impl BuiltinFloat { | 145 | impl 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}; | |||
17 | use syntax::ast::RangeOp; | 17 | use syntax::ast::RangeOp; |
18 | 18 | ||
19 | use crate::{ | 19 | use 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 | ||
3 | use std::iter; | ||
4 | |||
3 | use hir_expand::name::{known, AsName, Name}; | 5 | use hir_expand::name::{known, AsName, Name}; |
4 | use rustc_hash::FxHashSet; | 6 | use rustc_hash::FxHashSet; |
5 | use test_utils::mark; | 7 | use 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; | |||
12 | use test_utils::mark; | 12 | use test_utils::mark; |
13 | 13 | ||
14 | use crate::{ | 14 | use 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 | ||
536 | impl 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 | |||
532 | impl AttrDefId { | 555 | impl 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" | |||
17 | log = "0.4.8" | 17 | log = "0.4.8" |
18 | rustc-hash = "1.1.0" | 18 | rustc-hash = "1.1.0" |
19 | scoped-tls = "1" | 19 | scoped-tls = "1" |
20 | chalk-solve = { version = "0.58", default-features = false } | 20 | chalk-solve = { version = "0.59", default-features = false } |
21 | chalk-ir = "0.58" | 21 | chalk-ir = "0.59" |
22 | chalk-recursive = "0.58" | 22 | chalk-recursive = "0.59" |
23 | la-arena = { version = "0.2.0", path = "../../lib/arena" } | 23 | la-arena = { version = "0.2.0", path = "../../lib/arena" } |
24 | 24 | ||
25 | stdx = { path = "../stdx", version = "0.0.0" } | 25 | stdx = { 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 | ||
23 | pub(crate) use hir_def::{ | 23 | pub(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::{ | |||
227 | use la_arena::Idx; | 227 | use la_arena::Idx; |
228 | use smallvec::{smallvec, SmallVec}; | 228 | use smallvec::{smallvec, SmallVec}; |
229 | 229 | ||
230 | use crate::{db::HirDatabase, ApplicationTy, InferenceResult, Ty, TypeCtor}; | 230 | use 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 | }; |
12 | use hir_expand::diagnostics::DiagnosticSink; | 12 | use hir_expand::diagnostics::DiagnosticSink; |
13 | 13 | ||
14 | use crate::{ | 14 | use crate::{db::HirDatabase, diagnostics::MissingUnsafe, InferenceResult, Ty}; |
15 | db::HirDatabase, diagnostics::MissingUnsafe, ApplicationTy, InferenceResult, Ty, TypeCtor, | ||
16 | }; | ||
17 | 15 | ||
18 | pub(super) struct UnsafeValidator<'a, 'b: 'a> { | 16 | pub(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 @@ | |||
3 | use std::{borrow::Cow, fmt}; | 3 | use std::{borrow::Cow, fmt}; |
4 | 4 | ||
5 | use crate::{ | 5 | use 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 | }; |
9 | use arrayvec::ArrayVec; | 10 | use arrayvec::ArrayVec; |
11 | use chalk_ir::Mutability; | ||
10 | use hir_def::{ | 12 | use 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 | ||
237 | impl HirDisplay for ApplicationTy { | 239 | impl 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 | |||
263 | impl 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(¶meters.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(¶meters.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 | ¶meters.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(¶meters); |
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 | |||
509 | impl 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 | |||
533 | impl 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 | ||
594 | impl HirDisplay for FnSig { | 590 | impl 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; | |||
18 | use std::ops::Index; | 18 | use std::ops::Index; |
19 | use std::sync::Arc; | 19 | use std::sync::Arc; |
20 | 20 | ||
21 | use chalk_ir::Mutability; | ||
21 | use hir_def::{ | 22 | use 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; | |||
36 | use syntax::SmolStr; | 37 | use syntax::SmolStr; |
37 | 38 | ||
38 | use super::{ | 39 | use 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 | }; |
43 | use crate::{ | 43 | use crate::{ |
44 | db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, | 44 | db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, AliasTy, |
45 | }; | 45 | }; |
46 | 46 | ||
47 | pub(crate) use unify::unify; | 47 | pub(crate) use unify::unify; |
48 | 48 | ||
49 | macro_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 | |||
58 | mod unify; | 49 | mod unify; |
59 | mod path; | 50 | mod path; |
60 | mod expr; | 51 | mod 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)] |
667 | pub enum InferTy { | 658 | pub 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 | ||
674 | impl InferTy { | 662 | impl 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 | ||
7 | use hir_def::{lang_item::LangItemTarget, type_ref::Mutability}; | 7 | use chalk_ir::{Mutability, TyVariableKind}; |
8 | use hir_def::lang_item::LangItemTarget; | ||
8 | use test_utils::mark; | 9 | use test_utils::mark; |
9 | 10 | ||
10 | use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty, TypeCtor}; | 11 | use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty}; |
11 | 12 | ||
12 | use super::{unify::TypeVarValue, InEnvironment, InferTy, InferenceContext}; | 13 | use super::{InEnvironment, InferenceContext}; |
13 | 14 | ||
14 | impl<'a> InferenceContext<'a> { | 15 | impl<'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 @@ | |||
3 | use std::iter::{repeat, repeat_with}; | 3 | use std::iter::{repeat, repeat_with}; |
4 | use std::{mem, sync::Arc}; | 4 | use std::{mem, sync::Arc}; |
5 | 5 | ||
6 | use chalk_ir::{Mutability, TyVariableKind}; | ||
6 | use hir_def::{ | 7 | use 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; | |||
15 | use test_utils::mark; | 15 | use test_utils::mark; |
16 | 16 | ||
17 | use crate::{ | 17 | use 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 | ||
25 | use super::{ | 28 | use 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(¶meters) |
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(¶meters) |
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 @@ | |||
3 | use std::iter::repeat; | 3 | use std::iter::repeat; |
4 | use std::sync::Arc; | 4 | use std::sync::Arc; |
5 | 5 | ||
6 | use chalk_ir::Mutability; | ||
6 | use hir_def::{ | 7 | use 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 | }; |
12 | use hir_expand::name::Name; | 12 | use hir_expand::name::Name; |
13 | use test_utils::mark; | 13 | use test_utils::mark; |
14 | 14 | ||
15 | use super::{BindingMode, Expectation, InferenceContext}; | 15 | use super::{BindingMode, Expectation, InferenceContext}; |
16 | use crate::{utils::variant_data, Substs, Ty, TypeCtor}; | 16 | use crate::{lower::lower_to_chalk_mutability, utils::variant_data, Substs, Ty}; |
17 | 17 | ||
18 | impl<'a> InferenceContext<'a> { | 18 | impl<'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 | ||
3 | use std::borrow::Cow; | 3 | use std::borrow::Cow; |
4 | 4 | ||
5 | use chalk_ir::{FloatTy, IntTy, TyVariableKind}; | ||
5 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; | 6 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; |
6 | 7 | ||
7 | use test_utils::mark; | 8 | use test_utils::mark; |
8 | 9 | ||
9 | use super::{InferenceContext, Obligation}; | 10 | use super::{InferenceContext, Obligation}; |
10 | use crate::{ | 11 | use 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 | ||
15 | impl<'a> InferenceContext<'a> { | 16 | impl<'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)] |
37 | pub(super) struct Canonicalized<T> { | 38 | pub(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 | ||
42 | impl<'a, 'b> Canonicalizer<'a, 'b> | 43 | impl<'a, 'b> Canonicalizer<'a, 'b> { |
43 | where | 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)] |
182 | pub(super) struct TypeVariableTable { | ||
183 | inner: Vec<TypeVariableData>, | ||
184 | } | ||
185 | |||
186 | impl 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)] | ||
210 | pub(crate) struct TypeVariableData { | ||
211 | diverging: bool, | ||
212 | } | ||
213 | |||
214 | #[derive(Clone, Debug)] | ||
201 | pub(crate) struct InferenceTable { | 215 | pub(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 | ||
205 | impl InferenceTable { | 220 | impl 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)] |
429 | pub struct TypeVarId(pub(super) u32); | 469 | pub(super) struct TypeVarId(pub(super) u32); |
430 | 470 | ||
431 | impl UnifyKey for TypeVarId { | 471 | impl 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)] |
450 | pub enum TypeVarValue { | 490 | pub(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 | ||
26 | use std::{iter, mem, ops::Deref, sync::Arc}; | 26 | use std::{iter, mem, ops::Deref, sync::Arc}; |
27 | 27 | ||
28 | use base_db::{salsa, CrateId}; | 28 | use base_db::salsa; |
29 | use hir_def::{ | 29 | use 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 | }; |
36 | use itertools::Itertools; | 34 | use itertools::Itertools; |
37 | 35 | ||
38 | use crate::{ | 36 | use 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 | ||
45 | pub use autoderef::autoderef; | 42 | pub use autoderef::autoderef; |
46 | pub use infer::{InferTy, InferenceResult}; | 43 | pub use infer::{InferenceResult, InferenceVar}; |
47 | pub use lower::{ | 44 | pub 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 | }; |
51 | pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; | 48 | pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; |
52 | 49 | ||
53 | pub use chalk_ir::{BoundVar, DebruijnIndex}; | 50 | pub use chalk_ir::{BoundVar, DebruijnIndex, Mutability, Scalar, TyVariableKind}; |
54 | 51 | ||
55 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 52 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
56 | pub enum Lifetime { | 53 | pub 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)] | ||
65 | pub 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 | |||
152 | impl 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)] | ||
261 | pub 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)] |
267 | pub struct OpaqueTy { | 59 | pub 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 | /// | 101 | pub 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)] |
315 | pub enum Ty { | 106 | pub 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)] | ||
113 | pub 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)] | ||
132 | pub 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)] |
657 | pub struct Canonical<T> { | 534 | pub 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 | ||
662 | impl<T> Canonical<T> { | 539 | impl<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)] | ||
669 | pub 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)] |
678 | pub struct FnSig { | 548 | pub 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. |
684 | pub type PolyFnSig = Binders<FnSig>; | 554 | pub type PolyFnSig = Binders<CallableSig>; |
685 | 555 | ||
686 | impl FnSig { | 556 | impl 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 | ||
705 | impl TypeWalk for FnSig { | 582 | impl 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 | ||
723 | impl Ty { | 600 | impl 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(¶meters)) |
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 { | |||
1064 | impl TypeWalk for Ty { | 991 | impl 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 @@ | |||
8 | use std::{iter, sync::Arc}; | 8 | use std::{iter, sync::Arc}; |
9 | 9 | ||
10 | use base_db::CrateId; | 10 | use base_db::CrateId; |
11 | use chalk_ir::Mutability; | ||
11 | use hir_def::{ | 12 | use 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>( | |||
760 | impl ReturnTypeImplTrait { | 761 | impl 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 { | |||
1025 | fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> Binders<Ty> { | 1026 | fn 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 | ||
1074 | fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -> PolyFnSig { | 1075 | fn 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 | ||
1099 | fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> { | 1100 | fn 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 | ||
1105 | fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> { | 1106 | fn 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 | |||
1264 | pub(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 | ||
7 | use arrayvec::ArrayVec; | 7 | use arrayvec::ArrayVec; |
8 | use base_db::CrateId; | 8 | use base_db::CrateId; |
9 | use chalk_ir::Mutability; | ||
9 | use hir_def::{ | 10 | use 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 | }; |
16 | use hir_expand::name::Name; | 14 | use hir_expand::name::Name; |
17 | use rustc_hash::{FxHashMap, FxHashSet}; | 15 | use rustc_hash::{FxHashMap, FxHashSet}; |
@@ -19,17 +17,26 @@ use rustc_hash::{FxHashMap, FxHashSet}; | |||
19 | use crate::{ | 17 | use 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)] |
30 | pub enum TyFingerprint { | 28 | pub 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 | ||
35 | impl TyFingerprint { | 42 | impl 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 | ||
48 | pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [ | 65 | pub(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 | ||
99 | pub(crate) const ALL_FLOAT_FPS: [TyFingerprint; 2] = [ | 80 | pub(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( | |||
701 | fn fallback_bound_vars(s: Substs, num_vars_to_keep: usize) -> Substs { | 684 | fn 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. |
2 | use chalk_ir::TyVariableKind; | ||
2 | use hir_def::expr::{ArithOp, BinaryOp, CmpOp}; | 3 | use hir_def::expr::{ArithOp, BinaryOp, CmpOp}; |
3 | 4 | ||
4 | use super::{InferTy, Ty, TypeCtor}; | 5 | use crate::{Scalar, Ty}; |
5 | use crate::ApplicationTy; | ||
6 | 6 | ||
7 | pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty { | 7 | pub(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 | ||
30 | pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { | 30 | pub(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 | ||
6 | use std::fmt; | 6 | pub use chalk_ir::{FloatTy, IntTy, UintTy}; |
7 | 7 | pub use hir_def::builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint}; | |
8 | pub use hir_def::builtin_type::{BuiltinFloat, BuiltinInt, FloatBitness, IntBitness, Signedness}; | 8 | |
9 | 9 | pub fn int_ty_to_string(ty: IntTy) -> &'static str { | |
10 | #[derive(Copy, Clone, Eq, PartialEq, Hash)] | 10 | match ty { |
11 | pub 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", | |
16 | impl 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 | |||
22 | impl fmt::Display for IntTy { | ||
23 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
24 | write!(f, "{}", self.ty_to_string()) | ||
25 | } | ||
26 | } | ||
27 | |||
28 | impl 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)] | ||
96 | pub struct FloatTy { | ||
97 | pub bitness: FloatBitness, | ||
98 | } | 18 | } |
99 | 19 | ||
100 | impl fmt::Debug for FloatTy { | 20 | pub 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 | ||
106 | impl fmt::Display for FloatTy { | 31 | pub 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 | ||
112 | impl FloatTy { | 38 | pub(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 | ||
129 | impl From<BuiltinInt> for IntTy { | 49 | pub(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 | ||
135 | impl From<BuiltinFloat> for FloatTy { | 60 | pub(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] | ||
2496 | fn box_into_vec() { | ||
2497 | check_infer( | ||
2498 | r#" | ||
2499 | #[lang = "sized"] | ||
2500 | pub trait Sized {} | ||
2501 | |||
2502 | #[lang = "unsize"] | ||
2503 | pub trait Unsize<T: ?Sized> {} | ||
2504 | |||
2505 | #[lang = "coerce_unsized"] | ||
2506 | pub trait CoerceUnsized<T> {} | ||
2507 | |||
2508 | pub unsafe trait Allocator {} | ||
2509 | |||
2510 | pub struct Global; | ||
2511 | unsafe impl Allocator for Global {} | ||
2512 | |||
2513 | #[lang = "owned_box"] | ||
2514 | #[fundamental] | ||
2515 | pub struct Box<T: ?Sized, A: Allocator = Global>; | ||
2516 | |||
2517 | impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Box<U, A>> for Box<T, A> {} | ||
2518 | |||
2519 | pub struct Vec<T, A: Allocator = Global> {} | ||
2520 | |||
2521 | #[lang = "slice"] | ||
2522 | impl<T> [T] {} | ||
2523 | |||
2524 | #[lang = "slice_alloc"] | ||
2525 | impl<T> [T] { | ||
2526 | pub fn into_vec<A: Allocator>(self: Box<Self, A>) -> Vec<T, A> { | ||
2527 | unimplemented!() | ||
2528 | } | ||
2529 | } | ||
2530 | |||
2531 | fn 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 | }; |
25 | use mapping::{ | 25 | use 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 | ||
6 | use chalk_ir::{ | 6 | use 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 | }; |
10 | use chalk_solve::rust_ir; | 10 | use chalk_solve::rust_ir; |
11 | 11 | ||
12 | use base_db::salsa::InternKey; | 12 | use base_db::salsa::InternKey; |
13 | use hir_def::{type_ref::Mutability, AssocContainerId, GenericDefId, Lookup, TypeAliasId}; | 13 | use hir_def::{AssocContainerId, GenericDefId, Lookup, TypeAliasId}; |
14 | 14 | ||
15 | use crate::{ | 15 | use 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 | ||
23 | use super::interner::*; | 23 | use 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 | ||
271 | fn 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. |
281 | fn ref_to_chalk( | 231 | fn 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. |
293 | fn array_to_chalk(db: &dyn HirDatabase, subst: Substs) -> chalk_ir::Ty<Interner> { | 243 | fn 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 | ||
367 | fn 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 | |||
380 | fn 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 | |||
393 | fn 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 | |||
416 | impl 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 | |||
432 | impl ToChalk for hir_def::ImplId { | 316 | impl 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 | ||
3505 | mod foo { | ||
3506 | /// But this should appear | ||
3507 | pub mod bar {} | ||
3508 | } | ||
3509 | use 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 | // |=== | ||
42 | pub(crate) fn find_all_refs( | 51 | pub(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 | // |=== | ||
62 | pub(crate) fn rename( | 71 | pub(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 @@ | |||
1 | use itertools::Itertools; | ||
2 | use std::convert::identity; | ||
3 | use 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 | |||
15 | use 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 | /// ``` | ||
32 | pub(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 | |||
50 | fn 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 | |||
85 | fn 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. | ||
122 | fn 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. | ||
174 | fn 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 | |||
186 | fn 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)] | ||
198 | mod 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 | ||
209 | fn main() { | ||
210 | foo(); | ||
211 | } | ||
212 | "#, | ||
213 | r#" | ||
214 | /* | ||
215 | line comment | ||
216 | */ | ||
217 | fn 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#" | ||
229 | fn main() { | ||
230 | // line$0 comment | ||
231 | foo(); | ||
232 | } | ||
233 | "#, | ||
234 | r#" | ||
235 | fn 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#" | ||
250 | fn main() { | ||
251 | // above | ||
252 | // line$0 comment | ||
253 | // | ||
254 | // below | ||
255 | foo(); | ||
256 | } | ||
257 | "#, | ||
258 | r#" | ||
259 | fn 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#" | ||
277 | fn 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#" | ||
289 | fn main() { | ||
290 | /// different prefix | ||
291 | // line$0 comment | ||
292 | // below | ||
293 | foo(); | ||
294 | } | ||
295 | "#, | ||
296 | r#" | ||
297 | fn 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#" | ||
314 | fn main() { | ||
315 | // different chunk | ||
316 | |||
317 | // line$0 comment | ||
318 | // below | ||
319 | foo(); | ||
320 | } | ||
321 | "#, | ||
322 | r#" | ||
323 | fn 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#" | ||
386 | fn main() { | ||
387 | /*! | ||
388 | hi$0 there | ||
389 | |||
390 | ``` | ||
391 | code_sample | ||
392 | ``` | ||
393 | */ | ||
394 | } | ||
395 | "#, | ||
396 | r#" | ||
397 | fn 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#" | ||
413 | fn 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; | |||
3 | use ide_db::helpers::FamousDefs; | 3 | use ide_db::helpers::FamousDefs; |
4 | use stdx::format_to; | 4 | use stdx::format_to; |
5 | use syntax::{ast, AstNode}; | 5 | use syntax::{ast, AstNode}; |
6 | use test_utils::mark; | ||
6 | 7 | ||
7 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | 8 | use 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 | // ``` |
30 | pub(crate) fn convert_for_to_iter_for_each(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 31 | pub(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" |
156 | let mut x = vec![1, 2, 3]; | 161 | let mut x = vec![1, 2, 3]; |
157 | x.iter_mut().$0for_each(|v| *v *= 2); | 162 | x.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" |
167 | fn main() { | 172 | fn 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" | ||
194 | fn 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" |
260 | fn main() { | 280 | fn 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 @@ | |||
1 | use std::iter::once; | 1 | use std::iter::once; |
2 | 2 | ||
3 | use ide_db::ty_filter::TryEnum; | ||
3 | use syntax::{ | 4 | use syntax::{ |
4 | ast::{ | 5 | ast::{ |
5 | self, | 6 | self, |
@@ -10,7 +11,6 @@ use syntax::{ | |||
10 | }; | 11 | }; |
11 | 12 | ||
12 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | 13 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
13 | use 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] |
196 | fn doctest_convert_for_to_iter_for_each() { | ||
197 | check_doc_test( | ||
198 | "convert_for_to_iter_for_each", | ||
199 | r#####" | ||
200 | fn main() { | ||
201 | let x = vec![1, 2, 3]; | ||
202 | for $0v in x { | ||
203 | let y = v * 2; | ||
204 | } | ||
205 | } | ||
206 | "#####, | ||
207 | r#####" | ||
208 | fn 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] | ||
219 | fn doctest_convert_integer_literal() { | 196 | fn 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] |
1160 | fn doctest_replace_for_loop_with_for_each() { | ||
1161 | check_doc_test( | ||
1162 | "replace_for_loop_with_for_each", | ||
1163 | r#####" | ||
1164 | fn main() { | ||
1165 | let x = vec![1, 2, 3]; | ||
1166 | for$0 v in x { | ||
1167 | let y = v * 2; | ||
1168 | } | ||
1169 | } | ||
1170 | "#####, | ||
1171 | r#####" | ||
1172 | fn 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] | ||
1183 | fn doctest_replace_if_let_with_match() { | 1183 | fn 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" } | |||
21 | stdx = { path = "../stdx", version = "0.0.0" } | 21 | stdx = { path = "../stdx", version = "0.0.0" } |
22 | 22 | ||
23 | [dev-dependencies] | 23 | [dev-dependencies] |
24 | profile = { path = "../profile", version = "0.0.0" } | 24 | profile = { 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" } | |||
20 | test_utils = { path = "../test_utils", version = "0.0.0" } | 20 | test_utils = { path = "../test_utils", version = "0.0.0" } |
21 | 21 | ||
22 | [dev-dependencies] | 22 | [dev-dependencies] |
23 | cargo_metadata = "0.12.2" | 23 | cargo_metadata = "0.13" |
24 | 24 | ||
25 | # used as proc macro test targets | 25 | # used as proc macro test targets |
26 | serde_derive = "1.0.106" | 26 | serde_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; | |||
14 | use std::hash::Hash; | 14 | use std::hash::Hash; |
15 | use std::iter::FromIterator; | 15 | use std::iter::FromIterator; |
16 | use std::ops::Bound; | 16 | use std::ops::Bound; |
17 | use std::str::FromStr; | ||
18 | use std::{ascii, vec::IntoIter}; | 17 | use std::{ascii, vec::IntoIter}; |
19 | 18 | ||
20 | type Group = tt::Subtree; | 19 | type Group = tt::Subtree; |
@@ -278,6 +277,42 @@ impl server::FreeFunctions for Rustc { | |||
278 | } | 277 | } |
279 | } | 278 | } |
280 | 279 | ||
280 | fn 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 | |||
291 | fn 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 | |||
302 | fn 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 | |||
281 | impl server::TokenStream for Rustc { | 316 | impl 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 | ||
9 | mod fixtures { | 9 | mod 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] |
13 | log = "0.4.8" | 13 | log = "0.4.8" |
14 | rustc-hash = "1.1.0" | 14 | rustc-hash = "1.1.0" |
15 | cargo_metadata = "0.12.2" | 15 | cargo_metadata = "0.13" |
16 | serde = { version = "1.0.106", features = ["derive"] } | 16 | serde = { version = "1.0.106", features = ["derive"] } |
17 | serde_json = "1.0.48" | 17 | serde_json = "1.0.48" |
18 | anyhow = "1.0.26" | 18 | anyhow = "1.0.26" |
@@ -22,7 +22,7 @@ la-arena = { version = "0.2.0", path = "../../lib/arena" } | |||
22 | cfg = { path = "../cfg", version = "0.0.0" } | 22 | cfg = { path = "../cfg", version = "0.0.0" } |
23 | base_db = { path = "../base_db", version = "0.0.0" } | 23 | base_db = { path = "../base_db", version = "0.0.0" } |
24 | toolchain = { path = "../toolchain", version = "0.0.0" } | 24 | toolchain = { path = "../toolchain", version = "0.0.0" } |
25 | proc_macro_api = { path = "../proc_macro_api", version = "0.0.0" } | 25 | proc_macro_api = { path = "../proc_macro_api", version = "0.0.0" } |
26 | paths = { path = "../paths", version = "0.0.0" } | 26 | paths = { path = "../paths", version = "0.0.0" } |
27 | stdx = { path = "../stdx", version = "0.0.0" } | 27 | stdx = { path = "../stdx", version = "0.0.0" } |
28 | profile = { path = "../profile", version = "0.0.0" } | 28 | profile = { 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 | ||
3 | use std::{ | 3 | use 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 | ||
11 | use anyhow::Result; | 10 | use anyhow::Result; |
11 | use cargo_metadata::camino::Utf8Path; | ||
12 | use cargo_metadata::{BuildScript, Message}; | 12 | use cargo_metadata::{BuildScript, Message}; |
13 | use itertools::Itertools; | 13 | use itertools::Itertools; |
14 | use paths::{AbsPath, AbsPathBuf}; | 14 | use 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 |
212 | fn is_dylib(path: &Path) -> bool { | 212 | fn 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 | ||
3 | use std::path::PathBuf; | ||
3 | use std::{convert::TryInto, ops, process::Command, sync::Arc}; | 4 | use std::{convert::TryInto, ops, process::Command, sync::Arc}; |
4 | 5 | ||
5 | use anyhow::{Context, Result}; | 6 | use 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" | |||
24 | log = "0.4.8" | 24 | log = "0.4.8" |
25 | lsp-types = { version = "0.88.0", features = ["proposed"] } | 25 | lsp-types = { version = "0.88.0", features = ["proposed"] } |
26 | parking_lot = "0.11.0" | 26 | parking_lot = "0.11.0" |
27 | pico-args = "0.4.0" | 27 | xflags = "0.1.2" |
28 | oorandom = "11.1.2" | 28 | oorandom = "11.1.2" |
29 | rustc-hash = "1.1.0" | 29 | rustc-hash = "1.1.0" |
30 | serde = { version = "1.0.106", features = ["derive"] } | 30 | serde = { 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 | |||
6 | use std::{env, path::PathBuf}; | ||
7 | |||
8 | use anyhow::{bail, format_err, Result}; | ||
9 | use ide_ssr::{SsrPattern, SsrRule}; | ||
10 | use pico_args::Arguments; | ||
11 | use rust_analyzer::cli::{AnalysisStatsCmd, BenchCmd, BenchWhat, Position, Verbosity}; | ||
12 | use vfs::AbsPathBuf; | ||
13 | |||
14 | pub(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 | |||
23 | pub(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 | |||
39 | const HELP: &str = "\ | ||
40 | rust-analyzer | ||
41 | |||
42 | USAGE: | ||
43 | rust-analyzer [FLAGS] [COMMAND] [COMMAND_OPTIONS] | ||
44 | |||
45 | FLAGS: | ||
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 | |||
62 | ENVIRONMENTAL 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 | |||
67 | COMMANDS: | ||
68 | |||
69 | not specified Launch LSP server | ||
70 | |||
71 | parse < main.rs Parse tree | ||
72 | --no-dump Suppress printing | ||
73 | |||
74 | symbols < main.rs Parse input an print the list of symbols | ||
75 | |||
76 | highlight < main.rs Highlight input as html | ||
77 | --rainbow Enable rainbow highlighting of identifiers | ||
78 | |||
79 | analysis-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 | |||
90 | analysis-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 | |||
103 | diagnostics <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 | |||
109 | ssr [RULE...] | ||
110 | <RULE> A structured search replace rule (`$a.foo($b) ==> bar($a, $b)`) | ||
111 | |||
112 | search [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 | |||
118 | impl 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 | |||
269 | fn 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)] | ||
3 | use std::{env, path::PathBuf}; | ||
4 | |||
5 | use ide_ssr::{SsrPattern, SsrRule}; | ||
6 | use rust_analyzer::cli::{BenchWhat, Position, Verbosity}; | ||
7 | use vfs::AbsPathBuf; | ||
8 | |||
9 | xflags::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)] | ||
125 | pub 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)] | ||
135 | pub 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)] | ||
149 | pub struct LspServer { | ||
150 | pub version: bool, | ||
151 | pub help: bool, | ||
152 | pub print_config_schema: bool, | ||
153 | } | ||
154 | |||
155 | #[derive(Debug)] | ||
156 | pub struct Parse { | ||
157 | pub no_dump: bool, | ||
158 | } | ||
159 | |||
160 | #[derive(Debug)] | ||
161 | pub struct Symbols {} | ||
162 | |||
163 | #[derive(Debug)] | ||
164 | pub struct Highlight { | ||
165 | pub rainbow: bool, | ||
166 | } | ||
167 | |||
168 | #[derive(Debug)] | ||
169 | pub 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)] | ||
182 | pub 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)] | ||
194 | pub struct Diagnostics { | ||
195 | pub path: PathBuf, | ||
196 | |||
197 | pub load_output_dirs: bool, | ||
198 | pub with_proc_macro: bool, | ||
199 | } | ||
200 | |||
201 | #[derive(Debug)] | ||
202 | pub struct Ssr { | ||
203 | pub rule: Vec<SsrRule>, | ||
204 | } | ||
205 | |||
206 | #[derive(Debug)] | ||
207 | pub struct Search { | ||
208 | pub pattern: Vec<SsrPattern>, | ||
209 | |||
210 | pub debug: Option<String>, | ||
211 | } | ||
212 | |||
213 | #[derive(Debug)] | ||
214 | pub struct ProcMacro {} | ||
215 | |||
216 | impl 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 | |||
226 | impl 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 | |||
239 | impl 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 |
4 | mod args; | 4 | mod flags; |
5 | mod logger; | 5 | mod logger; |
6 | 6 | ||
7 | use std::{convert::TryFrom, env, fs, path::PathBuf, process}; | 7 | use std::{convert::TryFrom, env, fs, path::Path, process}; |
8 | 8 | ||
9 | use lsp_server::Connection; | 9 | use lsp_server::Connection; |
10 | use project_model::ProjectManifest; | 10 | use project_model::ProjectManifest; |
11 | use rust_analyzer::{cli, config::Config, from_json, lsp_ext::supports_utf8, Result}; | 11 | use rust_analyzer::{ |
12 | cli::{self, AnalysisStatsCmd, BenchCmd}, | ||
13 | config::Config, | ||
14 | from_json, | ||
15 | lsp_ext::supports_utf8, | ||
16 | Result, | ||
17 | }; | ||
12 | use vfs::AbsPathBuf; | 18 | use vfs::AbsPathBuf; |
13 | 19 | ||
14 | #[cfg(all(feature = "mimalloc"))] | 20 | #[cfg(all(feature = "mimalloc"))] |
@@ -28,10 +34,10 @@ fn main() { | |||
28 | } | 34 | } |
29 | 35 | ||
30 | fn try_main() -> Result<()> { | 36 | fn 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 | ||
70 | fn setup_logging(log_file: Option<PathBuf>, no_buffering: bool) -> Result<()> { | 103 | fn 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)] | ||
38 | pub struct Position { | 39 | pub 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 | ||
86 | fn load_crate_graph( | 86 | fn 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" | |||
54 | use std::collections::Spam; | 54 | use 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 | ||
21 | pub(crate) struct Project<'a> { | 21 | pub(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 | ||
596 | impl IndentLevel { | 596 | impl 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 | ||
87 | impl CommentKind { | 87 | impl 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) }), |