diff options
Diffstat (limited to 'crates')
37 files changed, 1378 insertions, 401 deletions
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 9f6d7be48..97a78ca25 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs | |||
@@ -217,7 +217,7 @@ impl HirDisplay for Variant { | |||
217 | 217 | ||
218 | impl HirDisplay for Type { | 218 | impl HirDisplay for Type { |
219 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 219 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
220 | self.ty.value.hir_fmt(f) | 220 | self.ty.hir_fmt(f) |
221 | } | 221 | } |
222 | } | 222 | } |
223 | 223 | ||
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index e3ac37e4c..30b96d7e2 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -56,9 +56,9 @@ use hir_ty::{ | |||
56 | primitive::UintTy, | 56 | primitive::UintTy, |
57 | to_assoc_type_id, | 57 | to_assoc_type_id, |
58 | traits::{FnTrait, Solution, SolutionVariables}, | 58 | traits::{FnTrait, Solution, SolutionVariables}, |
59 | AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, Cast, DebruijnIndex, | 59 | AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, |
60 | InEnvironment, Interner, ProjectionTy, Scalar, Substitution, Ty, TyDefId, TyKind, | 60 | DebruijnIndex, InEnvironment, Interner, ProjectionTy, QuantifiedWhereClause, Scalar, |
61 | TyVariableKind, WhereClause, | 61 | Substitution, TraitEnvironment, Ty, TyDefId, TyKind, TyVariableKind, WhereClause, |
62 | }; | 62 | }; |
63 | use itertools::Itertools; | 63 | use itertools::Itertools; |
64 | use rustc_hash::FxHashSet; | 64 | use rustc_hash::FxHashSet; |
@@ -851,13 +851,7 @@ impl Function { | |||
851 | .iter() | 851 | .iter() |
852 | .enumerate() | 852 | .enumerate() |
853 | .map(|(idx, type_ref)| { | 853 | .map(|(idx, type_ref)| { |
854 | let ty = Type { | 854 | let ty = Type { krate, env: environment.clone(), ty: ctx.lower_ty(type_ref) }; |
855 | krate, | ||
856 | ty: InEnvironment { | ||
857 | value: ctx.lower_ty(type_ref), | ||
858 | environment: environment.clone(), | ||
859 | }, | ||
860 | }; | ||
861 | Param { func: self, ty, idx } | 855 | Param { func: self, ty, idx } |
862 | }) | 856 | }) |
863 | .collect() | 857 | .collect() |
@@ -1460,7 +1454,7 @@ impl TypeParam { | |||
1460 | pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> { | 1454 | pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> { |
1461 | db.generic_predicates_for_param(self.id) | 1455 | db.generic_predicates_for_param(self.id) |
1462 | .into_iter() | 1456 | .into_iter() |
1463 | .filter_map(|pred| match &pred.value { | 1457 | .filter_map(|pred| match &pred.skip_binders().skip_binders() { |
1464 | hir_ty::WhereClause::Implemented(trait_ref) => { | 1458 | hir_ty::WhereClause::Implemented(trait_ref) => { |
1465 | Some(Trait::from(trait_ref.hir_trait_id())) | 1459 | Some(Trait::from(trait_ref.hir_trait_id())) |
1466 | } | 1460 | } |
@@ -1540,8 +1534,8 @@ impl Impl { | |||
1540 | inherent.all_impls().chain(trait_.all_impls()).map(Self::from).collect() | 1534 | inherent.all_impls().chain(trait_.all_impls()).map(Self::from).collect() |
1541 | } | 1535 | } |
1542 | 1536 | ||
1543 | pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty }: Type) -> Vec<Impl> { | 1537 | pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty, .. }: Type) -> Vec<Impl> { |
1544 | let def_crates = match ty.value.def_crates(db, krate) { | 1538 | let def_crates = match ty.def_crates(db, krate) { |
1545 | Some(def_crates) => def_crates, | 1539 | Some(def_crates) => def_crates, |
1546 | None => return Vec::new(), | 1540 | None => return Vec::new(), |
1547 | }; | 1541 | }; |
@@ -1549,14 +1543,14 @@ impl Impl { | |||
1549 | let filter = |impl_def: &Impl| { | 1543 | let filter = |impl_def: &Impl| { |
1550 | let target_ty = impl_def.target_ty(db); | 1544 | let target_ty = impl_def.target_ty(db); |
1551 | let rref = target_ty.remove_ref(); | 1545 | let rref = target_ty.remove_ref(); |
1552 | ty.value.equals_ctor(rref.as_ref().map_or(&target_ty.ty.value, |it| &it.ty.value)) | 1546 | ty.equals_ctor(rref.as_ref().map_or(&target_ty.ty, |it| &it.ty)) |
1553 | }; | 1547 | }; |
1554 | 1548 | ||
1555 | let mut all = Vec::new(); | 1549 | let mut all = Vec::new(); |
1556 | def_crates.iter().for_each(|&id| { | 1550 | def_crates.iter().for_each(|&id| { |
1557 | all.extend(db.inherent_impls_in_crate(id).all_impls().map(Self::from).filter(filter)) | 1551 | all.extend(db.inherent_impls_in_crate(id).all_impls().map(Self::from).filter(filter)) |
1558 | }); | 1552 | }); |
1559 | let fp = TyFingerprint::for_impl(&ty.value); | 1553 | let fp = TyFingerprint::for_impl(&ty); |
1560 | for id in def_crates | 1554 | for id in def_crates |
1561 | .iter() | 1555 | .iter() |
1562 | .flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db)) | 1556 | .flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db)) |
@@ -1643,7 +1637,8 @@ impl Impl { | |||
1643 | #[derive(Clone, PartialEq, Eq, Debug)] | 1637 | #[derive(Clone, PartialEq, Eq, Debug)] |
1644 | pub struct Type { | 1638 | pub struct Type { |
1645 | krate: CrateId, | 1639 | krate: CrateId, |
1646 | ty: InEnvironment<Ty>, | 1640 | env: Arc<TraitEnvironment>, |
1641 | ty: Ty, | ||
1647 | } | 1642 | } |
1648 | 1643 | ||
1649 | impl Type { | 1644 | impl Type { |
@@ -1663,14 +1658,14 @@ impl Type { | |||
1663 | ) -> Type { | 1658 | ) -> Type { |
1664 | let environment = | 1659 | let environment = |
1665 | resolver.generic_def().map_or_else(Default::default, |d| db.trait_environment(d)); | 1660 | resolver.generic_def().map_or_else(Default::default, |d| db.trait_environment(d)); |
1666 | Type { krate, ty: InEnvironment { value: ty, environment } } | 1661 | Type { krate, env: environment, ty } |
1667 | } | 1662 | } |
1668 | 1663 | ||
1669 | fn new(db: &dyn HirDatabase, krate: CrateId, lexical_env: impl HasResolver, ty: Ty) -> Type { | 1664 | fn new(db: &dyn HirDatabase, krate: CrateId, lexical_env: impl HasResolver, ty: Ty) -> Type { |
1670 | let resolver = lexical_env.resolver(db.upcast()); | 1665 | let resolver = lexical_env.resolver(db.upcast()); |
1671 | let environment = | 1666 | let environment = |
1672 | resolver.generic_def().map_or_else(Default::default, |d| db.trait_environment(d)); | 1667 | resolver.generic_def().map_or_else(Default::default, |d| db.trait_environment(d)); |
1673 | Type { krate, ty: InEnvironment { value: ty, environment } } | 1668 | Type { krate, env: environment, ty } |
1674 | } | 1669 | } |
1675 | 1670 | ||
1676 | fn from_def( | 1671 | fn from_def( |
@@ -1684,29 +1679,29 @@ impl Type { | |||
1684 | } | 1679 | } |
1685 | 1680 | ||
1686 | pub fn is_unit(&self) -> bool { | 1681 | pub fn is_unit(&self) -> bool { |
1687 | matches!(self.ty.value.interned(&Interner), TyKind::Tuple(0, ..)) | 1682 | matches!(self.ty.interned(&Interner), TyKind::Tuple(0, ..)) |
1688 | } | 1683 | } |
1689 | pub fn is_bool(&self) -> bool { | 1684 | pub fn is_bool(&self) -> bool { |
1690 | matches!(self.ty.value.interned(&Interner), TyKind::Scalar(Scalar::Bool)) | 1685 | matches!(self.ty.interned(&Interner), TyKind::Scalar(Scalar::Bool)) |
1691 | } | 1686 | } |
1692 | 1687 | ||
1693 | pub fn is_mutable_reference(&self) -> bool { | 1688 | pub fn is_mutable_reference(&self) -> bool { |
1694 | matches!(self.ty.value.interned(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..)) | 1689 | matches!(self.ty.interned(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..)) |
1695 | } | 1690 | } |
1696 | 1691 | ||
1697 | pub fn is_usize(&self) -> bool { | 1692 | pub fn is_usize(&self) -> bool { |
1698 | matches!(self.ty.value.interned(&Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize))) | 1693 | matches!(self.ty.interned(&Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize))) |
1699 | } | 1694 | } |
1700 | 1695 | ||
1701 | pub fn remove_ref(&self) -> Option<Type> { | 1696 | pub fn remove_ref(&self) -> Option<Type> { |
1702 | match &self.ty.value.interned(&Interner) { | 1697 | match &self.ty.interned(&Interner) { |
1703 | TyKind::Ref(.., ty) => Some(self.derived(ty.clone())), | 1698 | TyKind::Ref(.., ty) => Some(self.derived(ty.clone())), |
1704 | _ => None, | 1699 | _ => None, |
1705 | } | 1700 | } |
1706 | } | 1701 | } |
1707 | 1702 | ||
1708 | pub fn is_unknown(&self) -> bool { | 1703 | pub fn is_unknown(&self) -> bool { |
1709 | self.ty.value.is_unknown() | 1704 | self.ty.is_unknown() |
1710 | } | 1705 | } |
1711 | 1706 | ||
1712 | /// Checks that particular type `ty` implements `std::future::Future`. | 1707 | /// Checks that particular type `ty` implements `std::future::Future`. |
@@ -1723,11 +1718,12 @@ impl Type { | |||
1723 | None => return false, | 1718 | None => return false, |
1724 | }; | 1719 | }; |
1725 | 1720 | ||
1726 | let canonical_ty = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; | 1721 | let canonical_ty = |
1722 | Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(&Interner) }; | ||
1727 | method_resolution::implements_trait( | 1723 | method_resolution::implements_trait( |
1728 | &canonical_ty, | 1724 | &canonical_ty, |
1729 | db, | 1725 | db, |
1730 | self.ty.environment.clone(), | 1726 | self.env.clone(), |
1731 | krate, | 1727 | krate, |
1732 | std_future_trait, | 1728 | std_future_trait, |
1733 | ) | 1729 | ) |
@@ -1745,11 +1741,12 @@ impl Type { | |||
1745 | None => return false, | 1741 | None => return false, |
1746 | }; | 1742 | }; |
1747 | 1743 | ||
1748 | let canonical_ty = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; | 1744 | let canonical_ty = |
1745 | Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(&Interner) }; | ||
1749 | method_resolution::implements_trait_unique( | 1746 | method_resolution::implements_trait_unique( |
1750 | &canonical_ty, | 1747 | &canonical_ty, |
1751 | db, | 1748 | db, |
1752 | self.ty.environment.clone(), | 1749 | self.env.clone(), |
1753 | krate, | 1750 | krate, |
1754 | fnonce_trait, | 1751 | fnonce_trait, |
1755 | ) | 1752 | ) |
@@ -1759,17 +1756,14 @@ impl Type { | |||
1759 | let trait_ref = hir_ty::TraitRef { | 1756 | let trait_ref = hir_ty::TraitRef { |
1760 | trait_id: hir_ty::to_chalk_trait_id(trait_.id), | 1757 | trait_id: hir_ty::to_chalk_trait_id(trait_.id), |
1761 | substitution: Substitution::build_for_def(db, trait_.id) | 1758 | substitution: Substitution::build_for_def(db, trait_.id) |
1762 | .push(self.ty.value.clone()) | 1759 | .push(self.ty.clone()) |
1763 | .fill(args.iter().map(|t| t.ty.value.clone())) | 1760 | .fill(args.iter().map(|t| t.ty.clone())) |
1764 | .build(), | 1761 | .build(), |
1765 | }; | 1762 | }; |
1766 | 1763 | ||
1767 | let goal = Canonical { | 1764 | let goal = Canonical { |
1768 | value: hir_ty::InEnvironment::new( | 1765 | value: hir_ty::InEnvironment::new(self.env.env.clone(), trait_ref.cast(&Interner)), |
1769 | self.ty.environment.clone(), | 1766 | binders: CanonicalVarKinds::empty(&Interner), |
1770 | trait_ref.cast(&Interner), | ||
1771 | ), | ||
1772 | kinds: Arc::new([]), | ||
1773 | }; | 1767 | }; |
1774 | 1768 | ||
1775 | db.trait_solve(self.krate, goal).is_some() | 1769 | db.trait_solve(self.krate, goal).is_some() |
@@ -1783,12 +1777,12 @@ impl Type { | |||
1783 | alias: TypeAlias, | 1777 | alias: TypeAlias, |
1784 | ) -> Option<Type> { | 1778 | ) -> Option<Type> { |
1785 | let subst = Substitution::build_for_def(db, trait_.id) | 1779 | let subst = Substitution::build_for_def(db, trait_.id) |
1786 | .push(self.ty.value.clone()) | 1780 | .push(self.ty.clone()) |
1787 | .fill(args.iter().map(|t| t.ty.value.clone())) | 1781 | .fill(args.iter().map(|t| t.ty.clone())) |
1788 | .build(); | 1782 | .build(); |
1789 | let goal = Canonical { | 1783 | let goal = Canonical::new( |
1790 | value: InEnvironment::new( | 1784 | InEnvironment::new( |
1791 | self.ty.environment.clone(), | 1785 | self.env.env.clone(), |
1792 | AliasEq { | 1786 | AliasEq { |
1793 | alias: AliasTy::Projection(ProjectionTy { | 1787 | alias: AliasTy::Projection(ProjectionTy { |
1794 | associated_ty_id: to_assoc_type_id(alias.id), | 1788 | associated_ty_id: to_assoc_type_id(alias.id), |
@@ -1799,8 +1793,8 @@ impl Type { | |||
1799 | } | 1793 | } |
1800 | .cast(&Interner), | 1794 | .cast(&Interner), |
1801 | ), | 1795 | ), |
1802 | kinds: Arc::new([TyVariableKind::General]), | 1796 | [TyVariableKind::General].iter().copied(), |
1803 | }; | 1797 | ); |
1804 | 1798 | ||
1805 | match db.trait_solve(self.krate, goal)? { | 1799 | match db.trait_solve(self.krate, goal)? { |
1806 | Solution::Unique(SolutionVariables(subst)) => { | 1800 | Solution::Unique(SolutionVariables(subst)) => { |
@@ -1820,22 +1814,22 @@ impl Type { | |||
1820 | } | 1814 | } |
1821 | 1815 | ||
1822 | pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> { | 1816 | pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> { |
1823 | let def = self.ty.value.callable_def(db); | 1817 | let def = self.ty.callable_def(db); |
1824 | 1818 | ||
1825 | let sig = self.ty.value.callable_sig(db)?; | 1819 | let sig = self.ty.callable_sig(db)?; |
1826 | Some(Callable { ty: self.clone(), sig, def, is_bound_method: false }) | 1820 | Some(Callable { ty: self.clone(), sig, def, is_bound_method: false }) |
1827 | } | 1821 | } |
1828 | 1822 | ||
1829 | pub fn is_closure(&self) -> bool { | 1823 | pub fn is_closure(&self) -> bool { |
1830 | matches!(&self.ty.value.interned(&Interner), TyKind::Closure { .. }) | 1824 | matches!(&self.ty.interned(&Interner), TyKind::Closure { .. }) |
1831 | } | 1825 | } |
1832 | 1826 | ||
1833 | pub fn is_fn(&self) -> bool { | 1827 | pub fn is_fn(&self) -> bool { |
1834 | matches!(&self.ty.value.interned(&Interner), TyKind::FnDef(..) | TyKind::Function { .. }) | 1828 | matches!(&self.ty.interned(&Interner), TyKind::FnDef(..) | TyKind::Function { .. }) |
1835 | } | 1829 | } |
1836 | 1830 | ||
1837 | pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { | 1831 | pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { |
1838 | let adt_id = match self.ty.value.interned(&Interner) { | 1832 | let adt_id = match self.ty.interned(&Interner) { |
1839 | &TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id, | 1833 | &TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id, |
1840 | _ => return false, | 1834 | _ => return false, |
1841 | }; | 1835 | }; |
@@ -1848,11 +1842,11 @@ impl Type { | |||
1848 | } | 1842 | } |
1849 | 1843 | ||
1850 | pub fn is_raw_ptr(&self) -> bool { | 1844 | pub fn is_raw_ptr(&self) -> bool { |
1851 | matches!(&self.ty.value.interned(&Interner), TyKind::Raw(..)) | 1845 | matches!(&self.ty.interned(&Interner), TyKind::Raw(..)) |
1852 | } | 1846 | } |
1853 | 1847 | ||
1854 | pub fn contains_unknown(&self) -> bool { | 1848 | pub fn contains_unknown(&self) -> bool { |
1855 | return go(&self.ty.value); | 1849 | return go(&self.ty); |
1856 | 1850 | ||
1857 | fn go(ty: &Ty) -> bool { | 1851 | fn go(ty: &Ty) -> bool { |
1858 | match ty.interned(&Interner) { | 1852 | match ty.interned(&Interner) { |
@@ -1884,7 +1878,7 @@ impl Type { | |||
1884 | } | 1878 | } |
1885 | 1879 | ||
1886 | pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> { | 1880 | pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> { |
1887 | let (variant_id, substs) = match self.ty.value.interned(&Interner) { | 1881 | let (variant_id, substs) = match self.ty.interned(&Interner) { |
1888 | &TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs), | 1882 | &TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs), |
1889 | &TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs), | 1883 | &TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs), |
1890 | _ => return Vec::new(), | 1884 | _ => return Vec::new(), |
@@ -1901,7 +1895,7 @@ impl Type { | |||
1901 | } | 1895 | } |
1902 | 1896 | ||
1903 | pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> { | 1897 | pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> { |
1904 | if let TyKind::Tuple(_, substs) = &self.ty.value.interned(&Interner) { | 1898 | if let TyKind::Tuple(_, substs) = &self.ty.interned(&Interner) { |
1905 | substs.iter().map(|ty| self.derived(ty.clone())).collect() | 1899 | substs.iter().map(|ty| self.derived(ty.clone())).collect() |
1906 | } else { | 1900 | } else { |
1907 | Vec::new() | 1901 | Vec::new() |
@@ -1911,9 +1905,10 @@ impl Type { | |||
1911 | pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a { | 1905 | pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a { |
1912 | // There should be no inference vars in types passed here | 1906 | // There should be no inference vars in types passed here |
1913 | // FIXME check that? | 1907 | // FIXME check that? |
1914 | let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; | 1908 | let canonical = |
1915 | let environment = self.ty.environment.clone(); | 1909 | Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(&Interner) }; |
1916 | let ty = InEnvironment { value: canonical, environment }; | 1910 | let environment = self.env.env.clone(); |
1911 | let ty = InEnvironment { goal: canonical, environment }; | ||
1917 | autoderef(db, Some(self.krate), ty) | 1912 | autoderef(db, Some(self.krate), ty) |
1918 | .map(|canonical| canonical.value) | 1913 | .map(|canonical| canonical.value) |
1919 | .map(move |ty| self.derived(ty)) | 1914 | .map(move |ty| self.derived(ty)) |
@@ -1927,10 +1922,10 @@ impl Type { | |||
1927 | krate: Crate, | 1922 | krate: Crate, |
1928 | mut callback: impl FnMut(AssocItem) -> Option<T>, | 1923 | mut callback: impl FnMut(AssocItem) -> Option<T>, |
1929 | ) -> Option<T> { | 1924 | ) -> Option<T> { |
1930 | for krate in self.ty.value.def_crates(db, krate.id)? { | 1925 | for krate in self.ty.def_crates(db, krate.id)? { |
1931 | let impls = db.inherent_impls_in_crate(krate); | 1926 | let impls = db.inherent_impls_in_crate(krate); |
1932 | 1927 | ||
1933 | for impl_def in impls.for_self_ty(&self.ty.value) { | 1928 | for impl_def in impls.for_self_ty(&self.ty) { |
1934 | for &item in db.impl_data(*impl_def).items.iter() { | 1929 | for &item in db.impl_data(*impl_def).items.iter() { |
1935 | if let Some(result) = callback(item.into()) { | 1930 | if let Some(result) = callback(item.into()) { |
1936 | return Some(result); | 1931 | return Some(result); |
@@ -1943,7 +1938,6 @@ impl Type { | |||
1943 | 1938 | ||
1944 | pub fn type_parameters(&self) -> impl Iterator<Item = Type> + '_ { | 1939 | pub fn type_parameters(&self) -> impl Iterator<Item = Type> + '_ { |
1945 | self.ty | 1940 | self.ty |
1946 | .value | ||
1947 | .strip_references() | 1941 | .strip_references() |
1948 | .substs() | 1942 | .substs() |
1949 | .into_iter() | 1943 | .into_iter() |
@@ -1962,9 +1956,10 @@ impl Type { | |||
1962 | // There should be no inference vars in types passed here | 1956 | // There should be no inference vars in types passed here |
1963 | // FIXME check that? | 1957 | // FIXME check that? |
1964 | // FIXME replace Unknown by bound vars here | 1958 | // FIXME replace Unknown by bound vars here |
1965 | let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; | 1959 | let canonical = |
1960 | Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(&Interner) }; | ||
1966 | 1961 | ||
1967 | let env = self.ty.environment.clone(); | 1962 | let env = self.env.clone(); |
1968 | let krate = krate.id; | 1963 | let krate = krate.id; |
1969 | 1964 | ||
1970 | method_resolution::iterate_method_candidates( | 1965 | method_resolution::iterate_method_candidates( |
@@ -1993,9 +1988,10 @@ impl Type { | |||
1993 | // There should be no inference vars in types passed here | 1988 | // There should be no inference vars in types passed here |
1994 | // FIXME check that? | 1989 | // FIXME check that? |
1995 | // FIXME replace Unknown by bound vars here | 1990 | // FIXME replace Unknown by bound vars here |
1996 | let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; | 1991 | let canonical = |
1992 | Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(&Interner) }; | ||
1997 | 1993 | ||
1998 | let env = self.ty.environment.clone(); | 1994 | let env = self.env.clone(); |
1999 | let krate = krate.id; | 1995 | let krate = krate.id; |
2000 | 1996 | ||
2001 | method_resolution::iterate_method_candidates( | 1997 | method_resolution::iterate_method_candidates( |
@@ -2011,18 +2007,18 @@ impl Type { | |||
2011 | } | 2007 | } |
2012 | 2008 | ||
2013 | pub fn as_adt(&self) -> Option<Adt> { | 2009 | pub fn as_adt(&self) -> Option<Adt> { |
2014 | let (adt, _subst) = self.ty.value.as_adt()?; | 2010 | let (adt, _subst) = self.ty.as_adt()?; |
2015 | Some(adt.into()) | 2011 | Some(adt.into()) |
2016 | } | 2012 | } |
2017 | 2013 | ||
2018 | pub fn as_dyn_trait(&self) -> Option<Trait> { | 2014 | pub fn as_dyn_trait(&self) -> Option<Trait> { |
2019 | self.ty.value.dyn_trait().map(Into::into) | 2015 | self.ty.dyn_trait().map(Into::into) |
2020 | } | 2016 | } |
2021 | 2017 | ||
2022 | pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> { | 2018 | pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> { |
2023 | self.ty.value.impl_trait_bounds(db).map(|it| { | 2019 | self.ty.impl_trait_bounds(db).map(|it| { |
2024 | it.into_iter() | 2020 | it.into_iter() |
2025 | .filter_map(|pred| match pred { | 2021 | .filter_map(|pred| match pred.skip_binders() { |
2026 | hir_ty::WhereClause::Implemented(trait_ref) => { | 2022 | hir_ty::WhereClause::Implemented(trait_ref) => { |
2027 | Some(Trait::from(trait_ref.hir_trait_id())) | 2023 | Some(Trait::from(trait_ref.hir_trait_id())) |
2028 | } | 2024 | } |
@@ -2033,14 +2029,11 @@ impl Type { | |||
2033 | } | 2029 | } |
2034 | 2030 | ||
2035 | pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait> { | 2031 | pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait> { |
2036 | self.ty.value.associated_type_parent_trait(db).map(Into::into) | 2032 | self.ty.associated_type_parent_trait(db).map(Into::into) |
2037 | } | 2033 | } |
2038 | 2034 | ||
2039 | fn derived(&self, ty: Ty) -> Type { | 2035 | fn derived(&self, ty: Ty) -> Type { |
2040 | Type { | 2036 | Type { krate: self.krate, env: self.env.clone(), ty } |
2041 | krate: self.krate, | ||
2042 | ty: InEnvironment { value: ty, environment: self.ty.environment.clone() }, | ||
2043 | } | ||
2044 | } | 2037 | } |
2045 | 2038 | ||
2046 | pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) { | 2039 | pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) { |
@@ -2061,11 +2054,11 @@ impl Type { | |||
2061 | fn walk_bounds( | 2054 | fn walk_bounds( |
2062 | db: &dyn HirDatabase, | 2055 | db: &dyn HirDatabase, |
2063 | type_: &Type, | 2056 | type_: &Type, |
2064 | bounds: &[WhereClause], | 2057 | bounds: &[QuantifiedWhereClause], |
2065 | cb: &mut impl FnMut(Type), | 2058 | cb: &mut impl FnMut(Type), |
2066 | ) { | 2059 | ) { |
2067 | for pred in bounds { | 2060 | for pred in bounds { |
2068 | match pred { | 2061 | match pred.skip_binders() { |
2069 | WhereClause::Implemented(trait_ref) => { | 2062 | WhereClause::Implemented(trait_ref) => { |
2070 | cb(type_.clone()); | 2063 | cb(type_.clone()); |
2071 | // skip the self type. it's likely the type we just got the bounds from | 2064 | // skip the self type. it's likely the type we just got the bounds from |
@@ -2079,7 +2072,7 @@ impl Type { | |||
2079 | } | 2072 | } |
2080 | 2073 | ||
2081 | fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) { | 2074 | fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) { |
2082 | let ty = type_.ty.value.strip_references(); | 2075 | let ty = type_.ty.strip_references(); |
2083 | match ty.interned(&Interner) { | 2076 | match ty.interned(&Interner) { |
2084 | TyKind::Adt(..) => { | 2077 | TyKind::Adt(..) => { |
2085 | cb(type_.derived(ty.clone())); | 2078 | cb(type_.derived(ty.clone())); |
@@ -2107,7 +2100,12 @@ impl Type { | |||
2107 | } | 2100 | } |
2108 | } | 2101 | } |
2109 | TyKind::Dyn(bounds) => { | 2102 | TyKind::Dyn(bounds) => { |
2110 | walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb); | 2103 | walk_bounds( |
2104 | db, | ||
2105 | &type_.derived(ty.clone()), | ||
2106 | bounds.bounds.skip_binders().interned(), | ||
2107 | cb, | ||
2108 | ); | ||
2111 | } | 2109 | } |
2112 | 2110 | ||
2113 | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) | TyKind::Array(ty) | TyKind::Slice(ty) => { | 2111 | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) | TyKind::Array(ty) | TyKind::Slice(ty) => { |
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs index de08e2737..109d3552f 100644 --- a/crates/hir_def/src/find_path.rs +++ b/crates/hir_def/src/find_path.rs | |||
@@ -18,7 +18,8 @@ use crate::{ | |||
18 | /// *from where* you're referring to the item, hence the `from` parameter. | 18 | /// *from where* you're referring to the item, hence the `from` parameter. |
19 | pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> { | 19 | pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> { |
20 | let _p = profile::span("find_path"); | 20 | let _p = profile::span("find_path"); |
21 | find_path_inner(db, item, from, MAX_PATH_LEN, None) | 21 | let mut visited_modules = FxHashSet::default(); |
22 | find_path_inner(db, item, from, MAX_PATH_LEN, None, &mut visited_modules) | ||
22 | } | 23 | } |
23 | 24 | ||
24 | pub fn find_path_prefixed( | 25 | pub fn find_path_prefixed( |
@@ -28,7 +29,8 @@ pub fn find_path_prefixed( | |||
28 | prefix_kind: PrefixKind, | 29 | prefix_kind: PrefixKind, |
29 | ) -> Option<ModPath> { | 30 | ) -> Option<ModPath> { |
30 | let _p = profile::span("find_path_prefixed"); | 31 | let _p = profile::span("find_path_prefixed"); |
31 | find_path_inner(db, item, from, MAX_PATH_LEN, Some(prefix_kind)) | 32 | let mut visited_modules = FxHashSet::default(); |
33 | find_path_inner(db, item, from, MAX_PATH_LEN, Some(prefix_kind), &mut visited_modules) | ||
32 | } | 34 | } |
33 | 35 | ||
34 | const MAX_PATH_LEN: usize = 15; | 36 | const MAX_PATH_LEN: usize = 15; |
@@ -97,6 +99,7 @@ fn find_path_inner( | |||
97 | from: ModuleId, | 99 | from: ModuleId, |
98 | max_len: usize, | 100 | max_len: usize, |
99 | mut prefixed: Option<PrefixKind>, | 101 | mut prefixed: Option<PrefixKind>, |
102 | visited_modules: &mut FxHashSet<ModuleId>, | ||
100 | ) -> Option<ModPath> { | 103 | ) -> Option<ModPath> { |
101 | if max_len == 0 { | 104 | if max_len == 0 { |
102 | return None; | 105 | return None; |
@@ -176,15 +179,18 @@ fn find_path_inner( | |||
176 | if item.krate(db) == Some(from.krate) { | 179 | if item.krate(db) == Some(from.krate) { |
177 | // Item was defined in the same crate that wants to import it. It cannot be found in any | 180 | // Item was defined in the same crate that wants to import it. It cannot be found in any |
178 | // dependency in this case. | 181 | // dependency in this case. |
179 | 182 | for (module_id, name) in find_local_import_locations(db, item, from) { | |
180 | let local_imports = find_local_import_locations(db, item, from); | 183 | if !visited_modules.insert(module_id) { |
181 | for (module_id, name) in local_imports { | 184 | cov_mark::hit!(recursive_imports); |
185 | continue; | ||
186 | } | ||
182 | if let Some(mut path) = find_path_inner( | 187 | if let Some(mut path) = find_path_inner( |
183 | db, | 188 | db, |
184 | ItemInNs::Types(ModuleDefId::ModuleId(module_id)), | 189 | ItemInNs::Types(ModuleDefId::ModuleId(module_id)), |
185 | from, | 190 | from, |
186 | best_path_len - 1, | 191 | best_path_len - 1, |
187 | prefixed, | 192 | prefixed, |
193 | visited_modules, | ||
188 | ) { | 194 | ) { |
189 | path.push_segment(name); | 195 | path.push_segment(name); |
190 | 196 | ||
@@ -213,6 +219,7 @@ fn find_path_inner( | |||
213 | from, | 219 | from, |
214 | best_path_len - 1, | 220 | best_path_len - 1, |
215 | prefixed, | 221 | prefixed, |
222 | visited_modules, | ||
216 | )?; | 223 | )?; |
217 | cov_mark::hit!(partially_imported); | 224 | cov_mark::hit!(partially_imported); |
218 | path.push_segment(info.path.segments.last().unwrap().clone()); | 225 | path.push_segment(info.path.segments.last().unwrap().clone()); |
@@ -391,8 +398,15 @@ mod tests { | |||
391 | .take_types() | 398 | .take_types() |
392 | .unwrap(); | 399 | .unwrap(); |
393 | 400 | ||
394 | let found_path = | 401 | let mut visited_modules = FxHashSet::default(); |
395 | find_path_inner(&db, ItemInNs::Types(resolved), module, MAX_PATH_LEN, prefix_kind); | 402 | let found_path = find_path_inner( |
403 | &db, | ||
404 | ItemInNs::Types(resolved), | ||
405 | module, | ||
406 | MAX_PATH_LEN, | ||
407 | prefix_kind, | ||
408 | &mut visited_modules, | ||
409 | ); | ||
396 | assert_eq!(found_path, Some(mod_path), "{:?}", prefix_kind); | 410 | assert_eq!(found_path, Some(mod_path), "{:?}", prefix_kind); |
397 | } | 411 | } |
398 | 412 | ||
@@ -878,4 +892,32 @@ mod tests { | |||
878 | "self::module::CompleteMe", | 892 | "self::module::CompleteMe", |
879 | ) | 893 | ) |
880 | } | 894 | } |
895 | |||
896 | #[test] | ||
897 | fn recursive_pub_mod_reexport() { | ||
898 | cov_mark::check!(recursive_imports); | ||
899 | check_found_path( | ||
900 | r#" | ||
901 | fn main() { | ||
902 | let _ = 22_i32.as_name$0(); | ||
903 | } | ||
904 | |||
905 | pub mod name { | ||
906 | pub trait AsName { | ||
907 | fn as_name(&self) -> String; | ||
908 | } | ||
909 | impl AsName for i32 { | ||
910 | fn as_name(&self) -> String { | ||
911 | format!("Name: {}", self) | ||
912 | } | ||
913 | } | ||
914 | pub use crate::name; | ||
915 | } | ||
916 | "#, | ||
917 | "name::AsName", | ||
918 | "name::AsName", | ||
919 | "crate::name::AsName", | ||
920 | "self::name::AsName", | ||
921 | ); | ||
922 | } | ||
881 | } | 923 | } |
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index 0d3a0b54f..9e8e4e9ec 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs | |||
@@ -322,6 +322,23 @@ impl DefMap { | |||
322 | (res.resolved_def, res.segment_index) | 322 | (res.resolved_def, res.segment_index) |
323 | } | 323 | } |
324 | 324 | ||
325 | pub(crate) fn resolve_path_locally( | ||
326 | &self, | ||
327 | db: &dyn DefDatabase, | ||
328 | original_module: LocalModuleId, | ||
329 | path: &ModPath, | ||
330 | shadow: BuiltinShadowMode, | ||
331 | ) -> (PerNs, Option<usize>) { | ||
332 | let res = self.resolve_path_fp_with_macro_single( | ||
333 | db, | ||
334 | ResolveMode::Other, | ||
335 | original_module, | ||
336 | path, | ||
337 | shadow, | ||
338 | ); | ||
339 | (res.resolved_def, res.segment_index) | ||
340 | } | ||
341 | |||
325 | /// Ascends the `DefMap` hierarchy and calls `f` with every `DefMap` and containing module. | 342 | /// Ascends the `DefMap` hierarchy and calls `f` with every `DefMap` and containing module. |
326 | /// | 343 | /// |
327 | /// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns | 344 | /// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns |
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs index db459b1ed..60471937c 100644 --- a/crates/hir_def/src/nameres/path_resolution.rs +++ b/crates/hir_def/src/nameres/path_resolution.rs | |||
@@ -156,7 +156,7 @@ impl DefMap { | |||
156 | } | 156 | } |
157 | } | 157 | } |
158 | 158 | ||
159 | fn resolve_path_fp_with_macro_single( | 159 | pub(super) fn resolve_path_fp_with_macro_single( |
160 | &self, | 160 | &self, |
161 | db: &dyn DefDatabase, | 161 | db: &dyn DefDatabase, |
162 | mode: ResolveMode, | 162 | mode: ResolveMode, |
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index 04ea9c5d7..a73585ee7 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs | |||
@@ -548,7 +548,7 @@ impl ModuleItemMap { | |||
548 | path: &ModPath, | 548 | path: &ModPath, |
549 | ) -> Option<ResolveValueResult> { | 549 | ) -> Option<ResolveValueResult> { |
550 | let (module_def, idx) = | 550 | let (module_def, idx) = |
551 | self.def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other); | 551 | self.def_map.resolve_path_locally(db, self.module_id, &path, BuiltinShadowMode::Other); |
552 | match idx { | 552 | match idx { |
553 | None => { | 553 | None => { |
554 | let value = to_value_ns(module_def)?; | 554 | let value = to_value_ns(module_def)?; |
@@ -578,7 +578,7 @@ impl ModuleItemMap { | |||
578 | path: &ModPath, | 578 | path: &ModPath, |
579 | ) -> Option<(TypeNs, Option<usize>)> { | 579 | ) -> Option<(TypeNs, Option<usize>)> { |
580 | let (module_def, idx) = | 580 | let (module_def, idx) = |
581 | self.def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other); | 581 | self.def_map.resolve_path_locally(db, self.module_id, &path, BuiltinShadowMode::Other); |
582 | let res = to_type_ns(module_def)?; | 582 | let res = to_type_ns(module_def)?; |
583 | Some((res, idx)) | 583 | Some((res, idx)) |
584 | } | 584 | } |
@@ -627,8 +627,18 @@ pub trait HasResolver: Copy { | |||
627 | 627 | ||
628 | impl HasResolver for ModuleId { | 628 | impl HasResolver for ModuleId { |
629 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { | 629 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { |
630 | let def_map = self.def_map(db); | 630 | let mut def_map = self.def_map(db); |
631 | Resolver::default().push_module_scope(def_map, self.local_id) | 631 | let mut modules = Vec::new(); |
632 | modules.push((def_map.clone(), self.local_id)); | ||
633 | while let Some(parent) = def_map.parent() { | ||
634 | def_map = parent.def_map(db); | ||
635 | modules.push((def_map.clone(), parent.local_id)); | ||
636 | } | ||
637 | let mut resolver = Resolver::default(); | ||
638 | for (def_map, module) in modules.into_iter().rev() { | ||
639 | resolver = resolver.push_module_scope(def_map, module); | ||
640 | } | ||
641 | resolver | ||
632 | } | 642 | } |
633 | } | 643 | } |
634 | 644 | ||
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs index 23ab042c1..dc5fc759a 100644 --- a/crates/hir_ty/src/autoderef.rs +++ b/crates/hir_ty/src/autoderef.rs | |||
@@ -16,8 +16,8 @@ use crate::{ | |||
16 | to_assoc_type_id, to_chalk_trait_id, | 16 | to_assoc_type_id, to_chalk_trait_id, |
17 | traits::{InEnvironment, Solution}, | 17 | traits::{InEnvironment, Solution}, |
18 | utils::generics, | 18 | utils::generics, |
19 | AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, Interner, ProjectionTy, Substitution, | 19 | AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner, |
20 | TraitRef, Ty, TyKind, | 20 | ProjectionTy, Substitution, TraitRef, Ty, TyKind, |
21 | }; | 21 | }; |
22 | 22 | ||
23 | const AUTODEREF_RECURSION_LIMIT: usize = 10; | 23 | const AUTODEREF_RECURSION_LIMIT: usize = 10; |
@@ -27,9 +27,9 @@ pub fn autoderef<'a>( | |||
27 | krate: Option<CrateId>, | 27 | krate: Option<CrateId>, |
28 | ty: InEnvironment<Canonical<Ty>>, | 28 | ty: InEnvironment<Canonical<Ty>>, |
29 | ) -> impl Iterator<Item = Canonical<Ty>> + 'a { | 29 | ) -> impl Iterator<Item = Canonical<Ty>> + 'a { |
30 | let InEnvironment { value: ty, environment } = ty; | 30 | let InEnvironment { goal: ty, environment } = ty; |
31 | successors(Some(ty), move |ty| { | 31 | successors(Some(ty), move |ty| { |
32 | deref(db, krate?, InEnvironment { value: ty, environment: environment.clone() }) | 32 | deref(db, krate?, InEnvironment { goal: ty, environment: environment.clone() }) |
33 | }) | 33 | }) |
34 | .take(AUTODEREF_RECURSION_LIMIT) | 34 | .take(AUTODEREF_RECURSION_LIMIT) |
35 | } | 35 | } |
@@ -39,8 +39,8 @@ pub(crate) fn deref( | |||
39 | krate: CrateId, | 39 | krate: CrateId, |
40 | ty: InEnvironment<&Canonical<Ty>>, | 40 | ty: InEnvironment<&Canonical<Ty>>, |
41 | ) -> Option<Canonical<Ty>> { | 41 | ) -> Option<Canonical<Ty>> { |
42 | if let Some(derefed) = ty.value.value.builtin_deref() { | 42 | if let Some(derefed) = ty.goal.value.builtin_deref() { |
43 | Some(Canonical { value: derefed, kinds: ty.value.kinds.clone() }) | 43 | Some(Canonical { value: derefed, binders: ty.goal.binders.clone() }) |
44 | } else { | 44 | } else { |
45 | deref_by_trait(db, krate, ty) | 45 | deref_by_trait(db, krate, ty) |
46 | } | 46 | } |
@@ -67,15 +67,15 @@ fn deref_by_trait( | |||
67 | // FIXME make the Canonical / bound var handling nicer | 67 | // FIXME make the Canonical / bound var handling nicer |
68 | 68 | ||
69 | let parameters = | 69 | let parameters = |
70 | Substitution::build_for_generics(&generic_params).push(ty.value.value.clone()).build(); | 70 | Substitution::build_for_generics(&generic_params).push(ty.goal.value.clone()).build(); |
71 | 71 | ||
72 | // Check that the type implements Deref at all | 72 | // Check that the type implements Deref at all |
73 | let trait_ref = | 73 | let trait_ref = |
74 | TraitRef { trait_id: to_chalk_trait_id(deref_trait), substitution: parameters.clone() }; | 74 | TraitRef { trait_id: to_chalk_trait_id(deref_trait), substitution: parameters.clone() }; |
75 | let implements_goal = Canonical { | 75 | let implements_goal = Canonical { |
76 | kinds: ty.value.kinds.clone(), | 76 | binders: ty.goal.binders.clone(), |
77 | value: InEnvironment { | 77 | value: InEnvironment { |
78 | value: trait_ref.cast(&Interner), | 78 | goal: trait_ref.cast(&Interner), |
79 | environment: ty.environment.clone(), | 79 | environment: ty.environment.clone(), |
80 | }, | 80 | }, |
81 | }; | 81 | }; |
@@ -89,18 +89,27 @@ fn deref_by_trait( | |||
89 | associated_ty_id: to_assoc_type_id(target), | 89 | associated_ty_id: to_assoc_type_id(target), |
90 | substitution: parameters, | 90 | substitution: parameters, |
91 | }), | 91 | }), |
92 | ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len())) | 92 | ty: TyKind::BoundVar(BoundVar::new( |
93 | .intern(&Interner), | 93 | DebruijnIndex::INNERMOST, |
94 | ty.goal.binders.len(&Interner), | ||
95 | )) | ||
96 | .intern(&Interner), | ||
94 | }; | 97 | }; |
95 | 98 | ||
96 | let obligation = projection.cast(&Interner); | 99 | let obligation = projection.cast(&Interner); |
97 | 100 | ||
98 | let in_env = InEnvironment { value: obligation, environment: ty.environment }; | 101 | let in_env = InEnvironment { goal: obligation, environment: ty.environment }; |
99 | 102 | ||
100 | let canonical = Canonical::new( | 103 | let canonical = Canonical { |
101 | in_env, | 104 | value: in_env, |
102 | ty.value.kinds.iter().copied().chain(Some(chalk_ir::TyVariableKind::General)), | 105 | binders: CanonicalVarKinds::from_iter( |
103 | ); | 106 | &Interner, |
107 | ty.goal.binders.iter(&Interner).cloned().chain(Some(chalk_ir::WithKind::new( | ||
108 | chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), | ||
109 | chalk_ir::UniverseIndex::ROOT, | ||
110 | ))), | ||
111 | ), | ||
112 | }; | ||
104 | 113 | ||
105 | let solution = db.trait_solve(krate, canonical)?; | 114 | let solution = db.trait_solve(krate, canonical)?; |
106 | 115 | ||
@@ -121,21 +130,21 @@ fn deref_by_trait( | |||
121 | // assumptions will be broken. We would need to properly introduce | 130 | // assumptions will be broken. We would need to properly introduce |
122 | // new variables in that case | 131 | // new variables in that case |
123 | 132 | ||
124 | for i in 1..vars.0.kinds.len() { | 133 | for i in 1..vars.0.binders.len(&Interner) { |
125 | if vars.0.value[i - 1].interned(&Interner) | 134 | if vars.0.value[i - 1].interned(&Interner) |
126 | != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) | 135 | != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) |
127 | { | 136 | { |
128 | warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution); | 137 | warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution); |
129 | return None; | 138 | return None; |
130 | } | 139 | } |
131 | } | 140 | } |
132 | Some(Canonical { | 141 | Some(Canonical { |
133 | value: vars.0.value[vars.0.value.len() - 1].clone(), | 142 | value: vars.0.value[vars.0.value.len() - 1].clone(), |
134 | kinds: vars.0.kinds.clone(), | 143 | binders: vars.0.binders.clone(), |
135 | }) | 144 | }) |
136 | } | 145 | } |
137 | Solution::Ambig(_) => { | 146 | Solution::Ambig(_) => { |
138 | info!("Ambiguous solution for derefing {:?}: {:?}", ty.value, solution); | 147 | info!("Ambiguous solution for derefing {:?}: {:?}", ty.goal, solution); |
139 | None | 148 | None |
140 | } | 149 | } |
141 | } | 150 | } |
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs index 91a2e0b5b..58e4247c6 100644 --- a/crates/hir_ty/src/db.rs +++ b/crates/hir_ty/src/db.rs | |||
@@ -12,8 +12,8 @@ use la_arena::ArenaMap; | |||
12 | use crate::{ | 12 | use crate::{ |
13 | method_resolution::{InherentImpls, TraitImpls}, | 13 | method_resolution::{InherentImpls, TraitImpls}, |
14 | traits::chalk, | 14 | traits::chalk, |
15 | Binders, CallableDefId, FnDefId, ImplTraitId, InferenceResult, PolyFnSig, ReturnTypeImplTraits, | 15 | Binders, CallableDefId, FnDefId, ImplTraitId, InferenceResult, PolyFnSig, |
16 | TraitRef, Ty, TyDefId, ValueTyDefId, WhereClause, | 16 | QuantifiedWhereClause, ReturnTypeImplTraits, TraitRef, Ty, TyDefId, ValueTyDefId, |
17 | }; | 17 | }; |
18 | use hir_expand::name::Name; | 18 | use hir_expand::name::Name; |
19 | 19 | ||
@@ -57,10 +57,13 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { | |||
57 | 57 | ||
58 | #[salsa::invoke(crate::lower::generic_predicates_for_param_query)] | 58 | #[salsa::invoke(crate::lower::generic_predicates_for_param_query)] |
59 | #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)] | 59 | #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)] |
60 | fn generic_predicates_for_param(&self, param_id: TypeParamId) -> Arc<[Binders<WhereClause>]>; | 60 | fn generic_predicates_for_param( |
61 | &self, | ||
62 | param_id: TypeParamId, | ||
63 | ) -> Arc<[Binders<QuantifiedWhereClause>]>; | ||
61 | 64 | ||
62 | #[salsa::invoke(crate::lower::generic_predicates_query)] | 65 | #[salsa::invoke(crate::lower::generic_predicates_query)] |
63 | fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<WhereClause>]>; | 66 | fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<QuantifiedWhereClause>]>; |
64 | 67 | ||
65 | #[salsa::invoke(crate::lower::trait_environment_query)] | 68 | #[salsa::invoke(crate::lower::trait_environment_query)] |
66 | fn trait_environment(&self, def: GenericDefId) -> Arc<crate::TraitEnvironment>; | 69 | fn trait_environment(&self, def: GenericDefId) -> Arc<crate::TraitEnvironment>; |
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 9d3b79be3..6149067c7 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use std::{borrow::Cow, fmt}; | 3 | use std::fmt; |
4 | 4 | ||
5 | use arrayvec::ArrayVec; | 5 | use arrayvec::ArrayVec; |
6 | use chalk_ir::Mutability; | 6 | use chalk_ir::Mutability; |
@@ -20,7 +20,7 @@ use crate::{ | |||
20 | db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, | 20 | db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, |
21 | to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, | 21 | to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, |
22 | CallableDefId, CallableSig, DomainGoal, ImplTraitId, Interner, Lifetime, OpaqueTy, | 22 | CallableDefId, CallableSig, DomainGoal, ImplTraitId, Interner, Lifetime, OpaqueTy, |
23 | ProjectionTy, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause, | 23 | ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause, |
24 | }; | 24 | }; |
25 | 25 | ||
26 | pub struct HirFormatter<'a> { | 26 | pub struct HirFormatter<'a> { |
@@ -190,6 +190,7 @@ impl DisplayTarget { | |||
190 | pub enum DisplaySourceCodeError { | 190 | pub enum DisplaySourceCodeError { |
191 | PathNotFound, | 191 | PathNotFound, |
192 | UnknownType, | 192 | UnknownType, |
193 | Closure, | ||
193 | } | 194 | } |
194 | 195 | ||
195 | pub enum HirDisplayError { | 196 | pub enum HirDisplayError { |
@@ -328,9 +329,9 @@ impl HirDisplay for Ty { | |||
328 | 329 | ||
329 | // FIXME: all this just to decide whether to use parentheses... | 330 | // FIXME: all this just to decide whether to use parentheses... |
330 | let datas; | 331 | let datas; |
331 | let predicates = match t.interned(&Interner) { | 332 | let predicates: Vec<_> = match t.interned(&Interner) { |
332 | TyKind::Dyn(predicates) if predicates.len() > 1 => { | 333 | TyKind::Dyn(dyn_ty) if dyn_ty.bounds.skip_binders().interned().len() > 1 => { |
333 | Cow::Borrowed(predicates.as_ref()) | 334 | dyn_ty.bounds.skip_binders().interned().iter().cloned().collect() |
334 | } | 335 | } |
335 | &TyKind::Alias(AliasTy::Opaque(OpaqueTy { | 336 | &TyKind::Alias(AliasTy::Opaque(OpaqueTy { |
336 | opaque_ty_id, | 337 | opaque_ty_id, |
@@ -345,17 +346,21 @@ impl HirDisplay for Ty { | |||
345 | .as_ref() | 346 | .as_ref() |
346 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); | 347 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); |
347 | let bounds = data.subst(parameters); | 348 | let bounds = data.subst(parameters); |
348 | Cow::Owned(bounds.value) | 349 | bounds.value |
349 | } else { | 350 | } else { |
350 | Cow::Borrowed(&[][..]) | 351 | Vec::new() |
351 | } | 352 | } |
352 | } | 353 | } |
353 | _ => Cow::Borrowed(&[][..]), | 354 | _ => Vec::new(), |
354 | }; | 355 | }; |
355 | 356 | ||
356 | if let [WhereClause::Implemented(trait_ref), _] = predicates.as_ref() { | 357 | if let Some(WhereClause::Implemented(trait_ref)) = |
358 | predicates.get(0).map(|b| b.skip_binders()) | ||
359 | { | ||
357 | let trait_ = trait_ref.hir_trait_id(); | 360 | let trait_ = trait_ref.hir_trait_id(); |
358 | if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_) { | 361 | if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_) |
362 | && predicates.len() <= 2 | ||
363 | { | ||
359 | return write!(f, "{}", ty_display); | 364 | return write!(f, "{}", ty_display); |
360 | } | 365 | } |
361 | } | 366 | } |
@@ -539,6 +544,11 @@ impl HirDisplay for Ty { | |||
539 | } | 544 | } |
540 | } | 545 | } |
541 | TyKind::Closure(.., substs) => { | 546 | TyKind::Closure(.., substs) => { |
547 | if f.display_target.is_source_code() { | ||
548 | return Err(HirDisplayError::DisplaySourceCodeError( | ||
549 | DisplaySourceCodeError::Closure, | ||
550 | )); | ||
551 | } | ||
542 | let sig = substs[0].callable_sig(f.db); | 552 | let sig = substs[0].callable_sig(f.db); |
543 | if let Some(sig) = sig { | 553 | if let Some(sig) = sig { |
544 | if sig.params().is_empty() { | 554 | if sig.params().is_empty() { |
@@ -577,7 +587,7 @@ impl HirDisplay for Ty { | |||
577 | .generic_predicates(id.parent) | 587 | .generic_predicates(id.parent) |
578 | .into_iter() | 588 | .into_iter() |
579 | .map(|pred| pred.clone().subst(&substs)) | 589 | .map(|pred| pred.clone().subst(&substs)) |
580 | .filter(|wc| match &wc { | 590 | .filter(|wc| match &wc.skip_binders() { |
581 | WhereClause::Implemented(tr) => tr.self_type_parameter() == self, | 591 | WhereClause::Implemented(tr) => tr.self_type_parameter() == self, |
582 | WhereClause::AliasEq(AliasEq { | 592 | WhereClause::AliasEq(AliasEq { |
583 | alias: AliasTy::Projection(proj), | 593 | alias: AliasTy::Projection(proj), |
@@ -591,8 +601,12 @@ impl HirDisplay for Ty { | |||
591 | } | 601 | } |
592 | } | 602 | } |
593 | TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, | 603 | TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, |
594 | TyKind::Dyn(predicates) => { | 604 | TyKind::Dyn(dyn_ty) => { |
595 | write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?; | 605 | write_bounds_like_dyn_trait_with_prefix( |
606 | "dyn", | ||
607 | dyn_ty.bounds.skip_binders().interned(), | ||
608 | f, | ||
609 | )?; | ||
596 | } | 610 | } |
597 | TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?, | 611 | TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?, |
598 | TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { | 612 | TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { |
@@ -661,7 +675,7 @@ fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = Trai | |||
661 | 675 | ||
662 | pub fn write_bounds_like_dyn_trait_with_prefix( | 676 | pub fn write_bounds_like_dyn_trait_with_prefix( |
663 | prefix: &str, | 677 | prefix: &str, |
664 | predicates: &[WhereClause], | 678 | predicates: &[QuantifiedWhereClause], |
665 | f: &mut HirFormatter, | 679 | f: &mut HirFormatter, |
666 | ) -> Result<(), HirDisplayError> { | 680 | ) -> Result<(), HirDisplayError> { |
667 | write!(f, "{}", prefix)?; | 681 | write!(f, "{}", prefix)?; |
@@ -674,7 +688,7 @@ pub fn write_bounds_like_dyn_trait_with_prefix( | |||
674 | } | 688 | } |
675 | 689 | ||
676 | fn write_bounds_like_dyn_trait( | 690 | fn write_bounds_like_dyn_trait( |
677 | predicates: &[WhereClause], | 691 | predicates: &[QuantifiedWhereClause], |
678 | f: &mut HirFormatter, | 692 | f: &mut HirFormatter, |
679 | ) -> Result<(), HirDisplayError> { | 693 | ) -> Result<(), HirDisplayError> { |
680 | // Note: This code is written to produce nice results (i.e. | 694 | // Note: This code is written to produce nice results (i.e. |
@@ -687,7 +701,7 @@ fn write_bounds_like_dyn_trait( | |||
687 | let mut angle_open = false; | 701 | let mut angle_open = false; |
688 | let mut is_fn_trait = false; | 702 | let mut is_fn_trait = false; |
689 | for p in predicates.iter() { | 703 | for p in predicates.iter() { |
690 | match p { | 704 | match p.skip_binders() { |
691 | WhereClause::Implemented(trait_ref) => { | 705 | WhereClause::Implemented(trait_ref) => { |
692 | let trait_ = trait_ref.hir_trait_id(); | 706 | let trait_ = trait_ref.hir_trait_id(); |
693 | if !is_fn_trait { | 707 | if !is_fn_trait { |
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index b9e434c78..8f9cf7480 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs | |||
@@ -331,7 +331,7 @@ impl<'a> InferenceContext<'a> { | |||
331 | fn resolve_obligations_as_possible(&mut self) { | 331 | fn resolve_obligations_as_possible(&mut self) { |
332 | let obligations = mem::replace(&mut self.obligations, Vec::new()); | 332 | let obligations = mem::replace(&mut self.obligations, Vec::new()); |
333 | for obligation in obligations { | 333 | for obligation in obligations { |
334 | let in_env = InEnvironment::new(self.trait_env.clone(), obligation.clone()); | 334 | let in_env = InEnvironment::new(self.trait_env.env.clone(), obligation.clone()); |
335 | let canonicalized = self.canonicalizer().canonicalize_obligation(in_env); | 335 | let canonicalized = self.canonicalizer().canonicalize_obligation(in_env); |
336 | let solution = | 336 | let solution = |
337 | self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone()); | 337 | self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone()); |
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index 07eb96573..9c62932b1 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs | |||
@@ -142,7 +142,7 @@ impl<'a> InferenceContext<'a> { | |||
142 | .build(); | 142 | .build(); |
143 | let trait_ref = | 143 | let trait_ref = |
144 | TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs }; | 144 | TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs }; |
145 | let goal = InEnvironment::new(self.trait_env.clone(), trait_ref.cast(&Interner)); | 145 | let goal = InEnvironment::new(self.trait_env.env.clone(), trait_ref.cast(&Interner)); |
146 | 146 | ||
147 | let canonicalizer = self.canonicalizer(); | 147 | let canonicalizer = self.canonicalizer(); |
148 | let canonicalized = canonicalizer.canonicalize_obligation(goal); | 148 | let canonicalized = canonicalizer.canonicalize_obligation(goal); |
@@ -170,8 +170,8 @@ impl<'a> InferenceContext<'a> { | |||
170 | self.db, | 170 | self.db, |
171 | self.resolver.krate(), | 171 | self.resolver.krate(), |
172 | InEnvironment { | 172 | InEnvironment { |
173 | value: canonicalized.value.clone(), | 173 | goal: canonicalized.value.clone(), |
174 | environment: self.trait_env.clone(), | 174 | environment: self.trait_env.env.clone(), |
175 | }, | 175 | }, |
176 | ) { | 176 | ) { |
177 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); | 177 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 24deff707..19249973c 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -11,6 +11,7 @@ use hir_def::{ | |||
11 | AssocContainerId, FieldId, Lookup, | 11 | AssocContainerId, FieldId, Lookup, |
12 | }; | 12 | }; |
13 | use hir_expand::name::{name, Name}; | 13 | use hir_expand::name::{name, Name}; |
14 | use stdx::always; | ||
14 | use syntax::ast::RangeOp; | 15 | use syntax::ast::RangeOp; |
15 | 16 | ||
16 | use crate::{ | 17 | use crate::{ |
@@ -89,12 +90,12 @@ impl<'a> InferenceContext<'a> { | |||
89 | let substs = | 90 | let substs = |
90 | Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); | 91 | Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); |
91 | 92 | ||
92 | let trait_env = Arc::clone(&self.trait_env); | 93 | let trait_env = self.trait_env.env.clone(); |
93 | let implements_fn_trait: DomainGoal = | 94 | let implements_fn_trait: DomainGoal = |
94 | TraitRef { trait_id: to_chalk_trait_id(fn_once_trait), substitution: substs.clone() } | 95 | TraitRef { trait_id: to_chalk_trait_id(fn_once_trait), substitution: substs.clone() } |
95 | .cast(&Interner); | 96 | .cast(&Interner); |
96 | let goal = self.canonicalizer().canonicalize_obligation(InEnvironment { | 97 | let goal = self.canonicalizer().canonicalize_obligation(InEnvironment { |
97 | value: implements_fn_trait.clone(), | 98 | goal: implements_fn_trait.clone(), |
98 | environment: trait_env, | 99 | environment: trait_env, |
99 | }); | 100 | }); |
100 | if self.db.trait_solve(krate, goal.value).is_some() { | 101 | if self.db.trait_solve(krate, goal.value).is_some() { |
@@ -298,8 +299,8 @@ impl<'a> InferenceContext<'a> { | |||
298 | self.db, | 299 | self.db, |
299 | self.resolver.krate(), | 300 | self.resolver.krate(), |
300 | InEnvironment { | 301 | InEnvironment { |
301 | value: canonicalized.value.clone(), | 302 | goal: canonicalized.value.clone(), |
302 | environment: self.trait_env.clone(), | 303 | environment: self.trait_env.env.clone(), |
303 | }, | 304 | }, |
304 | ); | 305 | ); |
305 | let (param_tys, ret_ty): (Vec<Ty>, Ty) = derefs | 306 | let (param_tys, ret_ty): (Vec<Ty>, Ty) = derefs |
@@ -437,8 +438,8 @@ impl<'a> InferenceContext<'a> { | |||
437 | self.db, | 438 | self.db, |
438 | self.resolver.krate(), | 439 | self.resolver.krate(), |
439 | InEnvironment { | 440 | InEnvironment { |
440 | value: canonicalized.value.clone(), | 441 | goal: canonicalized.value.clone(), |
441 | environment: self.trait_env.clone(), | 442 | environment: self.trait_env.env.clone(), |
442 | }, | 443 | }, |
443 | ) | 444 | ) |
444 | .find_map(|derefed_ty| { | 445 | .find_map(|derefed_ty| { |
@@ -537,8 +538,8 @@ impl<'a> InferenceContext<'a> { | |||
537 | self.db, | 538 | self.db, |
538 | krate, | 539 | krate, |
539 | InEnvironment { | 540 | InEnvironment { |
540 | value: &canonicalized.value, | 541 | goal: &canonicalized.value, |
541 | environment: self.trait_env.clone(), | 542 | environment: self.trait_env.env.clone(), |
542 | }, | 543 | }, |
543 | ) { | 544 | ) { |
544 | Some(derefed_ty) => { | 545 | Some(derefed_ty) => { |
@@ -936,7 +937,9 @@ impl<'a> InferenceContext<'a> { | |||
936 | let def: CallableDefId = from_chalk(self.db, *fn_def); | 937 | let def: CallableDefId = from_chalk(self.db, *fn_def); |
937 | let generic_predicates = self.db.generic_predicates(def.into()); | 938 | let generic_predicates = self.db.generic_predicates(def.into()); |
938 | for predicate in generic_predicates.iter() { | 939 | for predicate in generic_predicates.iter() { |
939 | let predicate = predicate.clone().subst(parameters); | 940 | let (predicate, binders) = |
941 | predicate.clone().subst(parameters).into_value_and_skipped_binders(); | ||
942 | always!(binders == 0); // quantified where clauses not yet handled | ||
940 | self.obligations.push(predicate.cast(&Interner)); | 943 | self.obligations.push(predicate.cast(&Interner)); |
941 | } | 944 | } |
942 | // add obligation for trait implementation, if this is a trait method | 945 | // add obligation for trait implementation, if this is a trait method |
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index 1fc03c8f4..75250a369 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs | |||
@@ -2,13 +2,13 @@ | |||
2 | 2 | ||
3 | use std::borrow::Cow; | 3 | use std::borrow::Cow; |
4 | 4 | ||
5 | use chalk_ir::{FloatTy, IntTy, TyVariableKind}; | 5 | use chalk_ir::{FloatTy, IntTy, TyVariableKind, UniverseIndex, VariableKind}; |
6 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; | 6 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; |
7 | 7 | ||
8 | use super::{DomainGoal, InferenceContext}; | 8 | use super::{DomainGoal, InferenceContext}; |
9 | use crate::{ | 9 | use crate::{ |
10 | AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, FnPointer, InEnvironment, InferenceVar, | 10 | AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, |
11 | Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, WhereClause, | 11 | InEnvironment, InferenceVar, Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, WhereClause, |
12 | }; | 12 | }; |
13 | 13 | ||
14 | impl<'a> InferenceContext<'a> { | 14 | impl<'a> InferenceContext<'a> { |
@@ -76,8 +76,17 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { | |||
76 | } | 76 | } |
77 | 77 | ||
78 | fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { | 78 | fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { |
79 | let kinds = self.free_vars.iter().map(|&(_, k)| k).collect(); | 79 | let kinds = self |
80 | Canonicalized { value: Canonical { value: result, kinds }, free_vars: self.free_vars } | 80 | .free_vars |
81 | .iter() | ||
82 | .map(|&(_, k)| chalk_ir::WithKind::new(VariableKind::Ty(k), UniverseIndex::ROOT)); | ||
83 | Canonicalized { | ||
84 | value: Canonical { | ||
85 | value: result, | ||
86 | binders: CanonicalVarKinds::from_iter(&Interner, kinds), | ||
87 | }, | ||
88 | free_vars: self.free_vars, | ||
89 | } | ||
81 | } | 90 | } |
82 | 91 | ||
83 | pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> { | 92 | pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> { |
@@ -89,15 +98,12 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { | |||
89 | mut self, | 98 | mut self, |
90 | obligation: InEnvironment<DomainGoal>, | 99 | obligation: InEnvironment<DomainGoal>, |
91 | ) -> Canonicalized<InEnvironment<DomainGoal>> { | 100 | ) -> Canonicalized<InEnvironment<DomainGoal>> { |
92 | let result = match obligation.value { | 101 | let result = match obligation.goal { |
93 | DomainGoal::Holds(wc) => { | 102 | DomainGoal::Holds(wc) => { |
94 | DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST)) | 103 | DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST)) |
95 | } | 104 | } |
96 | }; | 105 | }; |
97 | self.into_canonicalized(InEnvironment { | 106 | self.into_canonicalized(InEnvironment { goal: result, environment: obligation.environment }) |
98 | value: result, | ||
99 | environment: obligation.environment, | ||
100 | }) | ||
101 | } | 107 | } |
102 | } | 108 | } |
103 | 109 | ||
@@ -125,12 +131,19 @@ impl<T> Canonicalized<T> { | |||
125 | // the solution may contain new variables, which we need to convert to new inference vars | 131 | // the solution may contain new variables, which we need to convert to new inference vars |
126 | let new_vars = Substitution( | 132 | let new_vars = Substitution( |
127 | solution | 133 | solution |
128 | .kinds | 134 | .binders |
129 | .iter() | 135 | .iter(&Interner) |
130 | .map(|k| match k { | 136 | .map(|k| match k.kind { |
131 | TyVariableKind::General => ctx.table.new_type_var(), | 137 | VariableKind::Ty(TyVariableKind::General) => ctx.table.new_type_var(), |
132 | TyVariableKind::Integer => ctx.table.new_integer_var(), | 138 | VariableKind::Ty(TyVariableKind::Integer) => ctx.table.new_integer_var(), |
133 | TyVariableKind::Float => ctx.table.new_float_var(), | 139 | VariableKind::Ty(TyVariableKind::Float) => ctx.table.new_float_var(), |
140 | // HACK: Chalk can sometimes return new lifetime variables. We | ||
141 | // want to just skip them, but to not mess up the indices of | ||
142 | // other variables, we'll just create a new type variable in | ||
143 | // their place instead. This should not matter (we never see the | ||
144 | // actual *uses* of the lifetime variable). | ||
145 | VariableKind::Lifetime => ctx.table.new_type_var(), | ||
146 | _ => panic!("const variable in solution"), | ||
134 | }) | 147 | }) |
135 | .collect(), | 148 | .collect(), |
136 | ); | 149 | ); |
@@ -147,8 +160,8 @@ impl<T> Canonicalized<T> { | |||
147 | pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { | 160 | pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { |
148 | let mut table = InferenceTable::new(); | 161 | let mut table = InferenceTable::new(); |
149 | let vars = Substitution( | 162 | let vars = Substitution( |
150 | tys.kinds | 163 | tys.binders |
151 | .iter() | 164 | .iter(&Interner) |
152 | // we always use type vars here because we want everything to | 165 | // we always use type vars here because we want everything to |
153 | // fallback to Unknown in the end (kind of hacky, as below) | 166 | // fallback to Unknown in the end (kind of hacky, as below) |
154 | .map(|_| table.new_type_var()) | 167 | .map(|_| table.new_type_var()) |
@@ -170,7 +183,7 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { | |||
170 | } | 183 | } |
171 | } | 184 | } |
172 | Some( | 185 | Some( |
173 | Substitution::builder(tys.kinds.len()) | 186 | Substitution::builder(tys.binders.len(&Interner)) |
174 | .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))) | 187 | .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))) |
175 | .build(), | 188 | .build(), |
176 | ) | 189 | ) |
@@ -310,9 +323,18 @@ impl InferenceTable { | |||
310 | 323 | ||
311 | (TyKind::Placeholder(p1), TyKind::Placeholder(p2)) if *p1 == *p2 => true, | 324 | (TyKind::Placeholder(p1), TyKind::Placeholder(p2)) if *p1 == *p2 => true, |
312 | 325 | ||
313 | (TyKind::Dyn(dyn1), TyKind::Dyn(dyn2)) if dyn1.len() == dyn2.len() => { | 326 | (TyKind::Dyn(dyn1), TyKind::Dyn(dyn2)) |
314 | for (pred1, pred2) in dyn1.iter().zip(dyn2.iter()) { | 327 | if dyn1.bounds.skip_binders().interned().len() |
315 | if !self.unify_preds(pred1, pred2, depth + 1) { | 328 | == dyn2.bounds.skip_binders().interned().len() => |
329 | { | ||
330 | for (pred1, pred2) in dyn1 | ||
331 | .bounds | ||
332 | .skip_binders() | ||
333 | .interned() | ||
334 | .iter() | ||
335 | .zip(dyn2.bounds.skip_binders().interned().iter()) | ||
336 | { | ||
337 | if !self.unify_preds(pred1.skip_binders(), pred2.skip_binders(), depth + 1) { | ||
316 | return false; | 338 | return false; |
317 | } | 339 | } |
318 | } | 340 | } |
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index ad908f957..0f49dd39b 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs | |||
@@ -61,6 +61,8 @@ pub type ClosureId = chalk_ir::ClosureId<Interner>; | |||
61 | pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; | 61 | pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; |
62 | pub type PlaceholderIndex = chalk_ir::PlaceholderIndex; | 62 | pub type PlaceholderIndex = chalk_ir::PlaceholderIndex; |
63 | 63 | ||
64 | pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>; | ||
65 | |||
64 | pub type ChalkTraitId = chalk_ir::TraitId<Interner>; | 66 | pub type ChalkTraitId = chalk_ir::TraitId<Interner>; |
65 | 67 | ||
66 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 68 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
@@ -132,6 +134,12 @@ impl TypeWalk for ProjectionTy { | |||
132 | } | 134 | } |
133 | } | 135 | } |
134 | 136 | ||
137 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
138 | pub struct DynTy { | ||
139 | /// The unknown self type. | ||
140 | pub bounds: Binders<QuantifiedWhereClauses>, | ||
141 | } | ||
142 | |||
135 | pub type FnSig = chalk_ir::FnSig<Interner>; | 143 | pub type FnSig = chalk_ir::FnSig<Interner>; |
136 | 144 | ||
137 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 145 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
@@ -283,7 +291,7 @@ pub enum TyKind { | |||
283 | /// represents the `Self` type inside the bounds. This is currently | 291 | /// represents the `Self` type inside the bounds. This is currently |
284 | /// implicit; Chalk has the `Binders` struct to make it explicit, but it | 292 | /// implicit; Chalk has the `Binders` struct to make it explicit, but it |
285 | /// didn't seem worth the overhead yet. | 293 | /// didn't seem worth the overhead yet. |
286 | Dyn(Arc<[WhereClause]>), | 294 | Dyn(DynTy), |
287 | 295 | ||
288 | /// A placeholder for a type which could not be computed; this is propagated | 296 | /// A placeholder for a type which could not be computed; this is propagated |
289 | /// to avoid useless error messages. Doubles as a placeholder where type | 297 | /// to avoid useless error messages. Doubles as a placeholder where type |
@@ -490,6 +498,13 @@ impl<T> Binders<T> { | |||
490 | Self { num_binders, value } | 498 | Self { num_binders, value } |
491 | } | 499 | } |
492 | 500 | ||
501 | pub fn wrap_empty(value: T) -> Self | ||
502 | where | ||
503 | T: TypeWalk, | ||
504 | { | ||
505 | Self { num_binders: 0, value: value.shift_bound_vars(DebruijnIndex::ONE) } | ||
506 | } | ||
507 | |||
493 | pub fn as_ref(&self) -> Binders<&T> { | 508 | pub fn as_ref(&self) -> Binders<&T> { |
494 | Binders { num_binders: self.num_binders, value: &self.value } | 509 | Binders { num_binders: self.num_binders, value: &self.value } |
495 | } | 510 | } |
@@ -501,6 +516,14 @@ impl<T> Binders<T> { | |||
501 | pub fn filter_map<U>(self, f: impl FnOnce(T) -> Option<U>) -> Option<Binders<U>> { | 516 | pub fn filter_map<U>(self, f: impl FnOnce(T) -> Option<U>) -> Option<Binders<U>> { |
502 | Some(Binders { num_binders: self.num_binders, value: f(self.value)? }) | 517 | Some(Binders { num_binders: self.num_binders, value: f(self.value)? }) |
503 | } | 518 | } |
519 | |||
520 | pub fn skip_binders(&self) -> &T { | ||
521 | &self.value | ||
522 | } | ||
523 | |||
524 | pub fn into_value_and_skipped_binders(self) -> (T, usize) { | ||
525 | (self.value, self.num_binders) | ||
526 | } | ||
504 | } | 527 | } |
505 | 528 | ||
506 | impl<T: Clone> Binders<&T> { | 529 | impl<T: Clone> Binders<&T> { |
@@ -614,6 +637,24 @@ impl TypeWalk for WhereClause { | |||
614 | } | 637 | } |
615 | } | 638 | } |
616 | 639 | ||
640 | pub type QuantifiedWhereClause = Binders<WhereClause>; | ||
641 | |||
642 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
643 | pub struct QuantifiedWhereClauses(Arc<[QuantifiedWhereClause]>); | ||
644 | |||
645 | impl QuantifiedWhereClauses { | ||
646 | pub fn from_iter( | ||
647 | _interner: &Interner, | ||
648 | elements: impl IntoIterator<Item = QuantifiedWhereClause>, | ||
649 | ) -> Self { | ||
650 | QuantifiedWhereClauses(elements.into_iter().collect()) | ||
651 | } | ||
652 | |||
653 | pub fn interned(&self) -> &Arc<[QuantifiedWhereClause]> { | ||
654 | &self.0 | ||
655 | } | ||
656 | } | ||
657 | |||
617 | /// Basically a claim (currently not validated / checked) that the contained | 658 | /// Basically a claim (currently not validated / checked) that the contained |
618 | /// type / trait ref contains no inference variables; any inference variables it | 659 | /// type / trait ref contains no inference variables; any inference variables it |
619 | /// contained have been replaced by bound variables, and `kinds` tells us how | 660 | /// contained have been replaced by bound variables, and `kinds` tells us how |
@@ -623,12 +664,18 @@ impl TypeWalk for WhereClause { | |||
623 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 664 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
624 | pub struct Canonical<T> { | 665 | pub struct Canonical<T> { |
625 | pub value: T, | 666 | pub value: T, |
626 | pub kinds: Arc<[TyVariableKind]>, | 667 | pub binders: CanonicalVarKinds, |
627 | } | 668 | } |
628 | 669 | ||
629 | impl<T> Canonical<T> { | 670 | impl<T> Canonical<T> { |
630 | pub fn new(value: T, kinds: impl IntoIterator<Item = TyVariableKind>) -> Self { | 671 | pub fn new(value: T, kinds: impl IntoIterator<Item = TyVariableKind>) -> Self { |
631 | Self { value, kinds: kinds.into_iter().collect() } | 672 | let kinds = kinds.into_iter().map(|tk| { |
673 | chalk_ir::CanonicalVarKind::new( | ||
674 | chalk_ir::VariableKind::Ty(tk), | ||
675 | chalk_ir::UniverseIndex::ROOT, | ||
676 | ) | ||
677 | }); | ||
678 | Self { value, binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds) } | ||
632 | } | 679 | } |
633 | } | 680 | } |
634 | 681 | ||
@@ -810,12 +857,14 @@ impl Ty { | |||
810 | } | 857 | } |
811 | 858 | ||
812 | /// If this is a `dyn Trait` type, this returns the `Trait` part. | 859 | /// If this is a `dyn Trait` type, this returns the `Trait` part. |
813 | pub fn dyn_trait_ref(&self) -> Option<&TraitRef> { | 860 | fn dyn_trait_ref(&self) -> Option<&TraitRef> { |
814 | match self.interned(&Interner) { | 861 | match self.interned(&Interner) { |
815 | TyKind::Dyn(bounds) => bounds.get(0).and_then(|b| match b { | 862 | TyKind::Dyn(dyn_ty) => { |
816 | WhereClause::Implemented(trait_ref) => Some(trait_ref), | 863 | dyn_ty.bounds.value.interned().get(0).and_then(|b| match b.skip_binders() { |
817 | _ => None, | 864 | WhereClause::Implemented(trait_ref) => Some(trait_ref), |
818 | }), | 865 | _ => None, |
866 | }) | ||
867 | } | ||
819 | _ => None, | 868 | _ => None, |
820 | } | 869 | } |
821 | } | 870 | } |
@@ -892,7 +941,7 @@ impl Ty { | |||
892 | } | 941 | } |
893 | } | 942 | } |
894 | 943 | ||
895 | pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<WhereClause>> { | 944 | pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>> { |
896 | match self.interned(&Interner) { | 945 | match self.interned(&Interner) { |
897 | TyKind::OpaqueType(opaque_ty_id, ..) => { | 946 | TyKind::OpaqueType(opaque_ty_id, ..) => { |
898 | match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) { | 947 | match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) { |
@@ -905,10 +954,13 @@ impl Ty { | |||
905 | // This is only used by type walking. | 954 | // This is only used by type walking. |
906 | // Parameters will be walked outside, and projection predicate is not used. | 955 | // Parameters will be walked outside, and projection predicate is not used. |
907 | // So just provide the Future trait. | 956 | // So just provide the Future trait. |
908 | let impl_bound = WhereClause::Implemented(TraitRef { | 957 | let impl_bound = Binders::new( |
909 | trait_id: to_chalk_trait_id(future_trait), | 958 | 0, |
910 | substitution: Substitution::empty(), | 959 | WhereClause::Implemented(TraitRef { |
911 | }); | 960 | trait_id: to_chalk_trait_id(future_trait), |
961 | substitution: Substitution::empty(), | ||
962 | }), | ||
963 | ); | ||
912 | Some(vec![impl_bound]) | 964 | Some(vec![impl_bound]) |
913 | } else { | 965 | } else { |
914 | None | 966 | None |
@@ -945,7 +997,7 @@ impl Ty { | |||
945 | .generic_predicates(id.parent) | 997 | .generic_predicates(id.parent) |
946 | .into_iter() | 998 | .into_iter() |
947 | .map(|pred| pred.clone().subst(&substs)) | 999 | .map(|pred| pred.clone().subst(&substs)) |
948 | .filter(|wc| match &wc { | 1000 | .filter(|wc| match &wc.skip_binders() { |
949 | WhereClause::Implemented(tr) => tr.self_type_parameter() == self, | 1001 | WhereClause::Implemented(tr) => tr.self_type_parameter() == self, |
950 | WhereClause::AliasEq(AliasEq { | 1002 | WhereClause::AliasEq(AliasEq { |
951 | alias: AliasTy::Projection(proj), | 1003 | alias: AliasTy::Projection(proj), |
@@ -1094,8 +1146,8 @@ impl TypeWalk for Ty { | |||
1094 | t.walk(f); | 1146 | t.walk(f); |
1095 | } | 1147 | } |
1096 | } | 1148 | } |
1097 | TyKind::Dyn(predicates) => { | 1149 | TyKind::Dyn(dyn_ty) => { |
1098 | for p in predicates.iter() { | 1150 | for p in dyn_ty.bounds.value.interned().iter() { |
1099 | p.walk(f); | 1151 | p.walk(f); |
1100 | } | 1152 | } |
1101 | } | 1153 | } |
@@ -1122,8 +1174,8 @@ impl TypeWalk for Ty { | |||
1122 | TyKind::Alias(AliasTy::Projection(p_ty)) => { | 1174 | TyKind::Alias(AliasTy::Projection(p_ty)) => { |
1123 | p_ty.substitution.walk_mut_binders(f, binders); | 1175 | p_ty.substitution.walk_mut_binders(f, binders); |
1124 | } | 1176 | } |
1125 | TyKind::Dyn(predicates) => { | 1177 | TyKind::Dyn(dyn_ty) => { |
1126 | for p in make_mut_slice(predicates) { | 1178 | for p in make_mut_slice(&mut dyn_ty.bounds.value.0) { |
1127 | p.walk_mut_binders(f, binders.shifted_in()); | 1179 | p.walk_mut_binders(f, binders.shifted_in()); |
1128 | } | 1180 | } |
1129 | } | 1181 | } |
@@ -1173,7 +1225,7 @@ pub struct ReturnTypeImplTraits { | |||
1173 | 1225 | ||
1174 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 1226 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
1175 | pub(crate) struct ReturnTypeImplTrait { | 1227 | pub(crate) struct ReturnTypeImplTrait { |
1176 | pub(crate) bounds: Binders<Vec<WhereClause>>, | 1228 | pub(crate) bounds: Binders<Vec<QuantifiedWhereClause>>, |
1177 | } | 1229 | } |
1178 | 1230 | ||
1179 | pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId { | 1231 | pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId { |
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index fd451a823..3153b5b74 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs | |||
@@ -33,9 +33,10 @@ use crate::{ | |||
33 | all_super_trait_refs, associated_type_by_name_including_super_traits, generics, | 33 | all_super_trait_refs, associated_type_by_name_including_super_traits, generics, |
34 | variant_data, | 34 | variant_data, |
35 | }, | 35 | }, |
36 | AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, FnPointer, FnSig, ImplTraitId, | 36 | AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig, |
37 | OpaqueTy, PolyFnSig, ProjectionTy, ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, | 37 | ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, |
38 | TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk, WhereClause, | 38 | ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, Ty, |
39 | TyKind, TypeWalk, WhereClause, | ||
39 | }; | 40 | }; |
40 | 41 | ||
41 | #[derive(Debug)] | 42 | #[derive(Debug)] |
@@ -188,13 +189,14 @@ impl<'a> TyLoweringContext<'a> { | |||
188 | TypeRef::DynTrait(bounds) => { | 189 | TypeRef::DynTrait(bounds) => { |
189 | let self_ty = | 190 | let self_ty = |
190 | TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); | 191 | TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); |
191 | let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { | 192 | let bounds = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { |
192 | bounds | 193 | QuantifiedWhereClauses::from_iter( |
193 | .iter() | 194 | &Interner, |
194 | .flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)) | 195 | bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)), |
195 | .collect() | 196 | ) |
196 | }); | 197 | }); |
197 | TyKind::Dyn(predicates).intern(&Interner) | 198 | let bounds = Binders::new(1, bounds); |
199 | TyKind::Dyn(DynTy { bounds }).intern(&Interner) | ||
198 | } | 200 | } |
199 | TypeRef::ImplTrait(bounds) => { | 201 | TypeRef::ImplTrait(bounds) => { |
200 | match self.impl_trait_mode { | 202 | match self.impl_trait_mode { |
@@ -376,7 +378,16 @@ impl<'a> TyLoweringContext<'a> { | |||
376 | // FIXME report error (ambiguous associated type) | 378 | // FIXME report error (ambiguous associated type) |
377 | TyKind::Unknown.intern(&Interner) | 379 | TyKind::Unknown.intern(&Interner) |
378 | } else { | 380 | } else { |
379 | TyKind::Dyn(Arc::new([WhereClause::Implemented(trait_ref)])).intern(&Interner) | 381 | let dyn_ty = DynTy { |
382 | bounds: Binders::new( | ||
383 | 1, | ||
384 | QuantifiedWhereClauses::from_iter( | ||
385 | &Interner, | ||
386 | Some(Binders::wrap_empty(WhereClause::Implemented(trait_ref))), | ||
387 | ), | ||
388 | ), | ||
389 | }; | ||
390 | TyKind::Dyn(dyn_ty).intern(&Interner) | ||
380 | }; | 391 | }; |
381 | return (ty, None); | 392 | return (ty, None); |
382 | } | 393 | } |
@@ -510,7 +521,7 @@ impl<'a> TyLoweringContext<'a> { | |||
510 | TyDefId::AdtId(it) => Some(it.into()), | 521 | TyDefId::AdtId(it) => Some(it.into()), |
511 | TyDefId::TypeAliasId(it) => Some(it.into()), | 522 | TyDefId::TypeAliasId(it) => Some(it.into()), |
512 | }; | 523 | }; |
513 | let substs = self.substs_from_path_segment(segment, generic_def, infer_args); | 524 | let substs = self.substs_from_path_segment(segment, generic_def, infer_args, None); |
514 | self.db.ty(typeable).subst(&substs) | 525 | self.db.ty(typeable).subst(&substs) |
515 | } | 526 | } |
516 | 527 | ||
@@ -547,7 +558,7 @@ impl<'a> TyLoweringContext<'a> { | |||
547 | (segment, Some(var.parent.into())) | 558 | (segment, Some(var.parent.into())) |
548 | } | 559 | } |
549 | }; | 560 | }; |
550 | self.substs_from_path_segment(segment, generic_def, infer_args) | 561 | self.substs_from_path_segment(segment, generic_def, infer_args, None) |
551 | } | 562 | } |
552 | 563 | ||
553 | fn substs_from_path_segment( | 564 | fn substs_from_path_segment( |
@@ -555,6 +566,7 @@ impl<'a> TyLoweringContext<'a> { | |||
555 | segment: PathSegment<'_>, | 566 | segment: PathSegment<'_>, |
556 | def_generic: Option<GenericDefId>, | 567 | def_generic: Option<GenericDefId>, |
557 | infer_args: bool, | 568 | infer_args: bool, |
569 | explicit_self_ty: Option<Ty>, | ||
558 | ) -> Substitution { | 570 | ) -> Substitution { |
559 | let mut substs = Vec::new(); | 571 | let mut substs = Vec::new(); |
560 | let def_generics = def_generic.map(|def| generics(self.db.upcast(), def)); | 572 | let def_generics = def_generic.map(|def| generics(self.db.upcast(), def)); |
@@ -565,11 +577,19 @@ impl<'a> TyLoweringContext<'a> { | |||
565 | 577 | ||
566 | substs.extend(iter::repeat(TyKind::Unknown.intern(&Interner)).take(parent_params)); | 578 | substs.extend(iter::repeat(TyKind::Unknown.intern(&Interner)).take(parent_params)); |
567 | 579 | ||
580 | let fill_self_params = || { | ||
581 | substs.extend( | ||
582 | explicit_self_ty | ||
583 | .into_iter() | ||
584 | .chain(iter::repeat(TyKind::Unknown.intern(&Interner))) | ||
585 | .take(self_params), | ||
586 | ) | ||
587 | }; | ||
568 | let mut had_explicit_type_args = false; | 588 | let mut had_explicit_type_args = false; |
569 | 589 | ||
570 | if let Some(generic_args) = &segment.args_and_bindings { | 590 | if let Some(generic_args) = &segment.args_and_bindings { |
571 | if !generic_args.has_self_type { | 591 | if !generic_args.has_self_type { |
572 | substs.extend(iter::repeat(TyKind::Unknown.intern(&Interner)).take(self_params)); | 592 | fill_self_params(); |
573 | } | 593 | } |
574 | let expected_num = | 594 | let expected_num = |
575 | if generic_args.has_self_type { self_params + type_params } else { type_params }; | 595 | if generic_args.has_self_type { self_params + type_params } else { type_params }; |
@@ -591,6 +611,8 @@ impl<'a> TyLoweringContext<'a> { | |||
591 | GenericArg::Lifetime(_) => {} | 611 | GenericArg::Lifetime(_) => {} |
592 | } | 612 | } |
593 | } | 613 | } |
614 | } else { | ||
615 | fill_self_params(); | ||
594 | } | 616 | } |
595 | 617 | ||
596 | // handle defaults. In expression or pattern path segments without | 618 | // handle defaults. In expression or pattern path segments without |
@@ -639,10 +661,7 @@ impl<'a> TyLoweringContext<'a> { | |||
639 | segment: PathSegment<'_>, | 661 | segment: PathSegment<'_>, |
640 | explicit_self_ty: Option<Ty>, | 662 | explicit_self_ty: Option<Ty>, |
641 | ) -> TraitRef { | 663 | ) -> TraitRef { |
642 | let mut substs = self.trait_ref_substs_from_path(segment, resolved); | 664 | let substs = self.trait_ref_substs_from_path(segment, resolved, explicit_self_ty); |
643 | if let Some(self_ty) = explicit_self_ty { | ||
644 | substs.0[0] = self_ty; | ||
645 | } | ||
646 | TraitRef { trait_id: to_chalk_trait_id(resolved), substitution: substs } | 665 | TraitRef { trait_id: to_chalk_trait_id(resolved), substitution: substs } |
647 | } | 666 | } |
648 | 667 | ||
@@ -662,15 +681,16 @@ impl<'a> TyLoweringContext<'a> { | |||
662 | &self, | 681 | &self, |
663 | segment: PathSegment<'_>, | 682 | segment: PathSegment<'_>, |
664 | resolved: TraitId, | 683 | resolved: TraitId, |
684 | explicit_self_ty: Option<Ty>, | ||
665 | ) -> Substitution { | 685 | ) -> Substitution { |
666 | self.substs_from_path_segment(segment, Some(resolved.into()), false) | 686 | self.substs_from_path_segment(segment, Some(resolved.into()), false, explicit_self_ty) |
667 | } | 687 | } |
668 | 688 | ||
669 | pub(crate) fn lower_where_predicate( | 689 | pub(crate) fn lower_where_predicate( |
670 | &'a self, | 690 | &'a self, |
671 | where_predicate: &'a WherePredicate, | 691 | where_predicate: &'a WherePredicate, |
672 | ignore_bindings: bool, | 692 | ignore_bindings: bool, |
673 | ) -> impl Iterator<Item = WhereClause> + 'a { | 693 | ) -> impl Iterator<Item = QuantifiedWhereClause> + 'a { |
674 | match where_predicate { | 694 | match where_predicate { |
675 | WherePredicate::ForLifetime { target, bound, .. } | 695 | WherePredicate::ForLifetime { target, bound, .. } |
676 | | WherePredicate::TypeBound { target, bound } => { | 696 | | WherePredicate::TypeBound { target, bound } => { |
@@ -705,12 +725,12 @@ impl<'a> TyLoweringContext<'a> { | |||
705 | bound: &'a TypeBound, | 725 | bound: &'a TypeBound, |
706 | self_ty: Ty, | 726 | self_ty: Ty, |
707 | ignore_bindings: bool, | 727 | ignore_bindings: bool, |
708 | ) -> impl Iterator<Item = WhereClause> + 'a { | 728 | ) -> impl Iterator<Item = QuantifiedWhereClause> + 'a { |
709 | let mut bindings = None; | 729 | let mut bindings = None; |
710 | let trait_ref = match bound { | 730 | let trait_ref = match bound { |
711 | TypeBound::Path(path) => { | 731 | TypeBound::Path(path) => { |
712 | bindings = self.lower_trait_ref_from_path(path, Some(self_ty)); | 732 | bindings = self.lower_trait_ref_from_path(path, Some(self_ty)); |
713 | bindings.clone().map(WhereClause::Implemented) | 733 | bindings.clone().map(WhereClause::Implemented).map(|b| Binders::wrap_empty(b)) |
714 | } | 734 | } |
715 | TypeBound::Lifetime(_) => None, | 735 | TypeBound::Lifetime(_) => None, |
716 | TypeBound::Error => None, | 736 | TypeBound::Error => None, |
@@ -727,7 +747,7 @@ impl<'a> TyLoweringContext<'a> { | |||
727 | &'a self, | 747 | &'a self, |
728 | bound: &'a TypeBound, | 748 | bound: &'a TypeBound, |
729 | trait_ref: TraitRef, | 749 | trait_ref: TraitRef, |
730 | ) -> impl Iterator<Item = WhereClause> + 'a { | 750 | ) -> impl Iterator<Item = QuantifiedWhereClause> + 'a { |
731 | let last_segment = match bound { | 751 | let last_segment = match bound { |
732 | TypeBound::Path(path) => path.segments().last(), | 752 | TypeBound::Path(path) => path.segments().last(), |
733 | TypeBound::Error | TypeBound::Lifetime(_) => None, | 753 | TypeBound::Error | TypeBound::Lifetime(_) => None, |
@@ -743,7 +763,7 @@ impl<'a> TyLoweringContext<'a> { | |||
743 | &binding.name, | 763 | &binding.name, |
744 | ); | 764 | ); |
745 | let (super_trait_ref, associated_ty) = match found { | 765 | let (super_trait_ref, associated_ty) = match found { |
746 | None => return SmallVec::<[WhereClause; 1]>::new(), | 766 | None => return SmallVec::<[QuantifiedWhereClause; 1]>::new(), |
747 | Some(t) => t, | 767 | Some(t) => t, |
748 | }; | 768 | }; |
749 | let projection_ty = ProjectionTy { | 769 | let projection_ty = ProjectionTy { |
@@ -757,7 +777,7 @@ impl<'a> TyLoweringContext<'a> { | |||
757 | let ty = self.lower_ty(type_ref); | 777 | let ty = self.lower_ty(type_ref); |
758 | let alias_eq = | 778 | let alias_eq = |
759 | AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty }; | 779 | AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty }; |
760 | preds.push(WhereClause::AliasEq(alias_eq)); | 780 | preds.push(Binders::wrap_empty(WhereClause::AliasEq(alias_eq))); |
761 | } | 781 | } |
762 | for bound in &binding.bounds { | 782 | for bound in &binding.bounds { |
763 | preds.extend(self.lower_type_bound( | 783 | preds.extend(self.lower_type_bound( |
@@ -814,7 +834,7 @@ pub fn associated_type_shorthand_candidates<R>( | |||
814 | let predicates = db.generic_predicates_for_param(param_id); | 834 | let predicates = db.generic_predicates_for_param(param_id); |
815 | let mut traits_: Vec<_> = predicates | 835 | let mut traits_: Vec<_> = predicates |
816 | .iter() | 836 | .iter() |
817 | .filter_map(|pred| match &pred.value { | 837 | .filter_map(|pred| match &pred.value.value { |
818 | WhereClause::Implemented(tr) => Some(tr.clone()), | 838 | WhereClause::Implemented(tr) => Some(tr.clone()), |
819 | _ => None, | 839 | _ => None, |
820 | }) | 840 | }) |
@@ -887,7 +907,7 @@ pub(crate) fn field_types_query( | |||
887 | pub(crate) fn generic_predicates_for_param_query( | 907 | pub(crate) fn generic_predicates_for_param_query( |
888 | db: &dyn HirDatabase, | 908 | db: &dyn HirDatabase, |
889 | param_id: TypeParamId, | 909 | param_id: TypeParamId, |
890 | ) -> Arc<[Binders<WhereClause>]> { | 910 | ) -> Arc<[Binders<QuantifiedWhereClause>]> { |
891 | let resolver = param_id.parent.resolver(db.upcast()); | 911 | let resolver = param_id.parent.resolver(db.upcast()); |
892 | let ctx = | 912 | let ctx = |
893 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | 913 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); |
@@ -915,7 +935,7 @@ pub(crate) fn generic_predicates_for_param_recover( | |||
915 | _db: &dyn HirDatabase, | 935 | _db: &dyn HirDatabase, |
916 | _cycle: &[String], | 936 | _cycle: &[String], |
917 | _param_id: &TypeParamId, | 937 | _param_id: &TypeParamId, |
918 | ) -> Arc<[Binders<WhereClause>]> { | 938 | ) -> Arc<[Binders<QuantifiedWhereClause>]> { |
919 | Arc::new([]) | 939 | Arc::new([]) |
920 | } | 940 | } |
921 | 941 | ||
@@ -930,7 +950,7 @@ pub(crate) fn trait_environment_query( | |||
930 | let mut clauses = Vec::new(); | 950 | let mut clauses = Vec::new(); |
931 | for pred in resolver.where_predicates_in_scope() { | 951 | for pred in resolver.where_predicates_in_scope() { |
932 | for pred in ctx.lower_where_predicate(pred, false) { | 952 | for pred in ctx.lower_where_predicate(pred, false) { |
933 | if let WhereClause::Implemented(tr) = &pred { | 953 | if let WhereClause::Implemented(tr) = &pred.skip_binders() { |
934 | traits_in_scope.push((tr.self_type_parameter().clone(), tr.hir_trait_id())); | 954 | traits_in_scope.push((tr.self_type_parameter().clone(), tr.hir_trait_id())); |
935 | } | 955 | } |
936 | let program_clause: chalk_ir::ProgramClause<Interner> = | 956 | let program_clause: chalk_ir::ProgramClause<Interner> = |
@@ -970,7 +990,7 @@ pub(crate) fn trait_environment_query( | |||
970 | pub(crate) fn generic_predicates_query( | 990 | pub(crate) fn generic_predicates_query( |
971 | db: &dyn HirDatabase, | 991 | db: &dyn HirDatabase, |
972 | def: GenericDefId, | 992 | def: GenericDefId, |
973 | ) -> Arc<[Binders<WhereClause>]> { | 993 | ) -> Arc<[Binders<QuantifiedWhereClause>]> { |
974 | let resolver = def.resolver(db.upcast()); | 994 | let resolver = def.resolver(db.upcast()); |
975 | let ctx = | 995 | let ctx = |
976 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | 996 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); |
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index da6bc2a4a..8e986ddde 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs | |||
@@ -6,7 +6,7 @@ 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::{cast::Cast, Mutability}; | 9 | use chalk_ir::{cast::Cast, Mutability, UniverseIndex}; |
10 | use hir_def::{ | 10 | use hir_def::{ |
11 | lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule, | 11 | lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule, |
12 | ImplId, Lookup, ModuleId, TraitId, | 12 | ImplId, Lookup, ModuleId, TraitId, |
@@ -21,8 +21,9 @@ use crate::{ | |||
21 | primitive::{self, FloatTy, IntTy, UintTy}, | 21 | primitive::{self, FloatTy, IntTy, UintTy}, |
22 | to_chalk_trait_id, | 22 | to_chalk_trait_id, |
23 | utils::all_super_traits, | 23 | utils::all_super_traits, |
24 | AdtId, Canonical, DebruijnIndex, FnPointer, FnSig, ForeignDefId, InEnvironment, Interner, | 24 | AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, FnSig, ForeignDefId, |
25 | Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk, | 25 | InEnvironment, Interner, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyKind, |
26 | TypeWalk, | ||
26 | }; | 27 | }; |
27 | 28 | ||
28 | /// This is used as a key for indexing impls. | 29 | /// This is used as a key for indexing impls. |
@@ -375,7 +376,7 @@ fn iterate_method_candidates_impl( | |||
375 | // Also note that when we've got a receiver like &S, even if the method we | 376 | // Also note that when we've got a receiver like &S, even if the method we |
376 | // find in the end takes &self, we still do the autoderef step (just as | 377 | // find in the end takes &self, we still do the autoderef step (just as |
377 | // rustc does an autoderef and then autoref again). | 378 | // rustc does an autoderef and then autoref again). |
378 | let ty = InEnvironment { value: ty.clone(), environment: env.clone() }; | 379 | let ty = InEnvironment { goal: ty.clone(), environment: env.env.clone() }; |
379 | 380 | ||
380 | // We have to be careful about the order we're looking at candidates | 381 | // We have to be careful about the order we're looking at candidates |
381 | // in here. Consider the case where we're resolving `x.clone()` | 382 | // in here. Consider the case where we're resolving `x.clone()` |
@@ -443,7 +444,7 @@ fn iterate_method_candidates_with_autoref( | |||
443 | return true; | 444 | return true; |
444 | } | 445 | } |
445 | let refed = Canonical { | 446 | let refed = Canonical { |
446 | kinds: deref_chain[0].kinds.clone(), | 447 | binders: deref_chain[0].binders.clone(), |
447 | value: TyKind::Ref(Mutability::Not, deref_chain[0].value.clone()).intern(&Interner), | 448 | value: TyKind::Ref(Mutability::Not, deref_chain[0].value.clone()).intern(&Interner), |
448 | }; | 449 | }; |
449 | if iterate_method_candidates_by_receiver( | 450 | if iterate_method_candidates_by_receiver( |
@@ -459,7 +460,7 @@ fn iterate_method_candidates_with_autoref( | |||
459 | return true; | 460 | return true; |
460 | } | 461 | } |
461 | let ref_muted = Canonical { | 462 | let ref_muted = Canonical { |
462 | kinds: deref_chain[0].kinds.clone(), | 463 | binders: deref_chain[0].binders.clone(), |
463 | value: TyKind::Ref(Mutability::Mut, deref_chain[0].value.clone()).intern(&Interner), | 464 | value: TyKind::Ref(Mutability::Mut, deref_chain[0].value.clone()).intern(&Interner), |
464 | }; | 465 | }; |
465 | if iterate_method_candidates_by_receiver( | 466 | if iterate_method_candidates_by_receiver( |
@@ -621,7 +622,7 @@ pub fn resolve_indexing_op( | |||
621 | krate: CrateId, | 622 | krate: CrateId, |
622 | index_trait: TraitId, | 623 | index_trait: TraitId, |
623 | ) -> Option<Canonical<Ty>> { | 624 | ) -> Option<Canonical<Ty>> { |
624 | let ty = InEnvironment { value: ty.clone(), environment: env.clone() }; | 625 | let ty = InEnvironment { goal: ty.clone(), environment: env.env.clone() }; |
625 | let deref_chain = autoderef_method_receiver(db, krate, ty); | 626 | let deref_chain = autoderef_method_receiver(db, krate, ty); |
626 | for ty in deref_chain { | 627 | for ty in deref_chain { |
627 | let goal = generic_implements_goal(db, env.clone(), index_trait, ty.clone()); | 628 | let goal = generic_implements_goal(db, env.clone(), index_trait, ty.clone()); |
@@ -677,19 +678,28 @@ pub(crate) fn inherent_impl_substs( | |||
677 | // we create a var for each type parameter of the impl; we need to keep in | 678 | // we create a var for each type parameter of the impl; we need to keep in |
678 | // mind here that `self_ty` might have vars of its own | 679 | // mind here that `self_ty` might have vars of its own |
679 | let vars = Substitution::build_for_def(db, impl_id) | 680 | let vars = Substitution::build_for_def(db, impl_id) |
680 | .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.kinds.len()) | 681 | .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.binders.len(&Interner)) |
681 | .build(); | 682 | .build(); |
682 | let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); | 683 | let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); |
683 | let mut kinds = self_ty.kinds.to_vec(); | 684 | let mut kinds = self_ty.binders.interned().to_vec(); |
684 | kinds.extend(iter::repeat(chalk_ir::TyVariableKind::General).take(vars.len())); | 685 | kinds.extend( |
685 | let tys = Canonical { kinds: kinds.into(), value: (self_ty_with_vars, self_ty.value.clone()) }; | 686 | iter::repeat(chalk_ir::WithKind::new( |
687 | chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), | ||
688 | UniverseIndex::ROOT, | ||
689 | )) | ||
690 | .take(vars.len()), | ||
691 | ); | ||
692 | let tys = Canonical { | ||
693 | binders: CanonicalVarKinds::from_iter(&Interner, kinds), | ||
694 | value: (self_ty_with_vars, self_ty.value.clone()), | ||
695 | }; | ||
686 | let substs = super::infer::unify(&tys); | 696 | let substs = super::infer::unify(&tys); |
687 | // We only want the substs for the vars we added, not the ones from self_ty. | 697 | // We only want the substs for the vars we added, not the ones from self_ty. |
688 | // Also, if any of the vars we added are still in there, we replace them by | 698 | // Also, if any of the vars we added are still in there, we replace them by |
689 | // Unknown. I think this can only really happen if self_ty contained | 699 | // Unknown. I think this can only really happen if self_ty contained |
690 | // Unknown, and in that case we want the result to contain Unknown in those | 700 | // Unknown, and in that case we want the result to contain Unknown in those |
691 | // places again. | 701 | // places again. |
692 | substs.map(|s| fallback_bound_vars(s.suffix(vars.len()), self_ty.kinds.len())) | 702 | substs.map(|s| fallback_bound_vars(s.suffix(vars.len()), self_ty.binders.len(&Interner))) |
693 | } | 703 | } |
694 | 704 | ||
695 | /// This replaces any 'free' Bound vars in `s` (i.e. those with indices past | 705 | /// This replaces any 'free' Bound vars in `s` (i.e. those with indices past |
@@ -768,15 +778,24 @@ fn generic_implements_goal( | |||
768 | trait_: TraitId, | 778 | trait_: TraitId, |
769 | self_ty: Canonical<Ty>, | 779 | self_ty: Canonical<Ty>, |
770 | ) -> Canonical<InEnvironment<super::DomainGoal>> { | 780 | ) -> Canonical<InEnvironment<super::DomainGoal>> { |
771 | let mut kinds = self_ty.kinds.to_vec(); | 781 | let mut kinds = self_ty.binders.interned().to_vec(); |
772 | let substs = super::Substitution::build_for_def(db, trait_) | 782 | let substs = super::Substitution::build_for_def(db, trait_) |
773 | .push(self_ty.value) | 783 | .push(self_ty.value) |
774 | .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len()) | 784 | .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len()) |
775 | .build(); | 785 | .build(); |
776 | kinds.extend(iter::repeat(chalk_ir::TyVariableKind::General).take(substs.len() - 1)); | 786 | kinds.extend( |
787 | iter::repeat(chalk_ir::WithKind::new( | ||
788 | chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), | ||
789 | UniverseIndex::ROOT, | ||
790 | )) | ||
791 | .take(substs.len() - 1), | ||
792 | ); | ||
777 | let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }; | 793 | let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }; |
778 | let obligation = trait_ref.cast(&Interner); | 794 | let obligation = trait_ref.cast(&Interner); |
779 | Canonical { kinds: kinds.into(), value: InEnvironment::new(env, obligation) } | 795 | Canonical { |
796 | binders: CanonicalVarKinds::from_iter(&Interner, kinds), | ||
797 | value: InEnvironment::new(env.env.clone(), obligation), | ||
798 | } | ||
780 | } | 799 | } |
781 | 800 | ||
782 | fn autoderef_method_receiver( | 801 | fn autoderef_method_receiver( |
@@ -789,9 +808,9 @@ fn autoderef_method_receiver( | |||
789 | if let Some(TyKind::Array(parameters)) = | 808 | if let Some(TyKind::Array(parameters)) = |
790 | deref_chain.last().map(|ty| ty.value.interned(&Interner)) | 809 | deref_chain.last().map(|ty| ty.value.interned(&Interner)) |
791 | { | 810 | { |
792 | let kinds = deref_chain.last().unwrap().kinds.clone(); | 811 | let kinds = deref_chain.last().unwrap().binders.clone(); |
793 | let unsized_ty = TyKind::Slice(parameters.clone()).intern(&Interner); | 812 | let unsized_ty = TyKind::Slice(parameters.clone()).intern(&Interner); |
794 | deref_chain.push(Canonical { value: unsized_ty, kinds }) | 813 | deref_chain.push(Canonical { value: unsized_ty, binders: kinds }) |
795 | } | 814 | } |
796 | deref_chain | 815 | deref_chain |
797 | } | 816 | } |
diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs index 69314e245..b69f86050 100644 --- a/crates/hir_ty/src/tests/regression.rs +++ b/crates/hir_ty/src/tests/regression.rs | |||
@@ -961,3 +961,16 @@ fn issue_6852() { | |||
961 | "#]], | 961 | "#]], |
962 | ); | 962 | ); |
963 | } | 963 | } |
964 | |||
965 | #[test] | ||
966 | fn param_overrides_fn() { | ||
967 | check_types( | ||
968 | r#" | ||
969 | fn example(example: i32) { | ||
970 | fn f() {} | ||
971 | example; | ||
972 | //^^^^^^^ i32 | ||
973 | } | ||
974 | "#, | ||
975 | ) | ||
976 | } | ||
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index 37cd04c6f..45a1958e3 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs | |||
@@ -3324,3 +3324,49 @@ fn f() { | |||
3324 | "#]], | 3324 | "#]], |
3325 | ) | 3325 | ) |
3326 | } | 3326 | } |
3327 | |||
3328 | #[test] | ||
3329 | fn infer_default_trait_type_parameter() { | ||
3330 | check_infer( | ||
3331 | r#" | ||
3332 | struct A; | ||
3333 | |||
3334 | trait Op<RHS=Self> { | ||
3335 | type Output; | ||
3336 | |||
3337 | fn do_op(self, rhs: RHS) -> Self::Output; | ||
3338 | } | ||
3339 | |||
3340 | impl Op for A { | ||
3341 | type Output = bool; | ||
3342 | |||
3343 | fn do_op(self, rhs: Self) -> Self::Output { | ||
3344 | true | ||
3345 | } | ||
3346 | } | ||
3347 | |||
3348 | fn test() { | ||
3349 | let x = A; | ||
3350 | let y = A; | ||
3351 | let r = x.do_op(y); | ||
3352 | } | ||
3353 | "#, | ||
3354 | expect![[r#" | ||
3355 | 63..67 'self': Self | ||
3356 | 69..72 'rhs': RHS | ||
3357 | 153..157 'self': A | ||
3358 | 159..162 'rhs': A | ||
3359 | 186..206 '{ ... }': bool | ||
3360 | 196..200 'true': bool | ||
3361 | 220..277 '{ ...(y); }': () | ||
3362 | 230..231 'x': A | ||
3363 | 234..235 'A': A | ||
3364 | 245..246 'y': A | ||
3365 | 249..250 'A': A | ||
3366 | 260..261 'r': bool | ||
3367 | 264..265 'x': A | ||
3368 | 264..274 'x.do_op(y)': bool | ||
3369 | 272..273 'y': A | ||
3370 | "#]], | ||
3371 | ) | ||
3372 | } | ||
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs index 7dadd1ffb..ccee0e5ad 100644 --- a/crates/hir_ty/src/traits.rs +++ b/crates/hir_ty/src/traits.rs | |||
@@ -1,6 +1,5 @@ | |||
1 | //! Trait solving using Chalk. | 1 | //! Trait solving using Chalk. |
2 | use std::env::var; | 2 | use std::env::var; |
3 | use std::sync::Arc; | ||
4 | 3 | ||
5 | use base_db::CrateId; | 4 | use base_db::CrateId; |
6 | use chalk_ir::cast::Cast; | 5 | use chalk_ir::cast::Cast; |
@@ -44,7 +43,7 @@ pub struct TraitEnvironment { | |||
44 | // When we're using Chalk's Ty we can make this a BTreeMap since it's Ord, | 43 | // When we're using Chalk's Ty we can make this a BTreeMap since it's Ord, |
45 | // but for now it's too annoying... | 44 | // but for now it's too annoying... |
46 | pub(crate) traits_from_clauses: Vec<(Ty, TraitId)>, | 45 | pub(crate) traits_from_clauses: Vec<(Ty, TraitId)>, |
47 | pub(crate) env: chalk_ir::Environment<Interner>, | 46 | pub env: chalk_ir::Environment<Interner>, |
48 | } | 47 | } |
49 | 48 | ||
50 | impl TraitEnvironment { | 49 | impl TraitEnvironment { |
@@ -74,13 +73,13 @@ impl Default for TraitEnvironment { | |||
74 | /// Something (usually a goal), along with an environment. | 73 | /// Something (usually a goal), along with an environment. |
75 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | 74 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] |
76 | pub struct InEnvironment<T> { | 75 | pub struct InEnvironment<T> { |
77 | pub environment: Arc<TraitEnvironment>, | 76 | pub environment: chalk_ir::Environment<Interner>, |
78 | pub value: T, | 77 | pub goal: T, |
79 | } | 78 | } |
80 | 79 | ||
81 | impl<T> InEnvironment<T> { | 80 | impl<T> InEnvironment<T> { |
82 | pub fn new(environment: Arc<TraitEnvironment>, value: T) -> InEnvironment<T> { | 81 | pub fn new(environment: chalk_ir::Environment<Interner>, value: T) -> InEnvironment<T> { |
83 | InEnvironment { environment, value } | 82 | InEnvironment { environment, goal: value } |
84 | } | 83 | } |
85 | } | 84 | } |
86 | 85 | ||
@@ -126,18 +125,18 @@ pub(crate) fn trait_solve_query( | |||
126 | krate: CrateId, | 125 | krate: CrateId, |
127 | goal: Canonical<InEnvironment<DomainGoal>>, | 126 | goal: Canonical<InEnvironment<DomainGoal>>, |
128 | ) -> Option<Solution> { | 127 | ) -> Option<Solution> { |
129 | let _p = profile::span("trait_solve_query").detail(|| match &goal.value.value { | 128 | let _p = profile::span("trait_solve_query").detail(|| match &goal.value.goal { |
130 | DomainGoal::Holds(WhereClause::Implemented(it)) => { | 129 | DomainGoal::Holds(WhereClause::Implemented(it)) => { |
131 | db.trait_data(it.hir_trait_id()).name.to_string() | 130 | db.trait_data(it.hir_trait_id()).name.to_string() |
132 | } | 131 | } |
133 | DomainGoal::Holds(WhereClause::AliasEq(_)) => "alias_eq".to_string(), | 132 | DomainGoal::Holds(WhereClause::AliasEq(_)) => "alias_eq".to_string(), |
134 | }); | 133 | }); |
135 | log::info!("trait_solve_query({})", goal.value.value.display(db)); | 134 | log::info!("trait_solve_query({})", goal.value.goal.display(db)); |
136 | 135 | ||
137 | if let DomainGoal::Holds(WhereClause::AliasEq(AliasEq { | 136 | if let DomainGoal::Holds(WhereClause::AliasEq(AliasEq { |
138 | alias: AliasTy::Projection(projection_ty), | 137 | alias: AliasTy::Projection(projection_ty), |
139 | .. | 138 | .. |
140 | })) = &goal.value.value | 139 | })) = &goal.value.goal |
141 | { | 140 | { |
142 | if let TyKind::BoundVar(_) = &projection_ty.substitution[0].interned(&Interner) { | 141 | if let TyKind::BoundVar(_) = &projection_ty.substitution[0].interned(&Interner) { |
143 | // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible | 142 | // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible |
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index 944145603..4019fdf17 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs | |||
@@ -238,7 +238,10 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
238 | }); | 238 | }); |
239 | let bound = OpaqueTyDatumBound { | 239 | let bound = OpaqueTyDatumBound { |
240 | bounds: make_binders( | 240 | bounds: make_binders( |
241 | vec![impl_bound.to_chalk(self.db), proj_bound.to_chalk(self.db)], | 241 | vec![ |
242 | wrap_in_empty_binders(impl_bound).to_chalk(self.db), | ||
243 | wrap_in_empty_binders(proj_bound).to_chalk(self.db), | ||
244 | ], | ||
242 | 1, | 245 | 1, |
243 | ), | 246 | ), |
244 | where_clauses: make_binders(vec![], 0), | 247 | where_clauses: make_binders(vec![], 0), |
@@ -397,7 +400,6 @@ pub(crate) fn associated_ty_data_query( | |||
397 | .iter() | 400 | .iter() |
398 | .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone(), false)) | 401 | .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone(), false)) |
399 | .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty)) | 402 | .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty)) |
400 | .map(|bound| make_binders(bound.shifted_in(&Interner), 0)) | ||
401 | .collect(); | 403 | .collect(); |
402 | 404 | ||
403 | let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars); | 405 | let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars); |
@@ -720,3 +722,7 @@ impl From<crate::db::InternedClosureId> for chalk_ir::ClosureId<Interner> { | |||
720 | chalk_ir::ClosureId(id.as_intern_id()) | 722 | chalk_ir::ClosureId(id.as_intern_id()) |
721 | } | 723 | } |
722 | } | 724 | } |
725 | |||
726 | fn wrap_in_empty_binders<T: crate::TypeWalk>(value: T) -> crate::Binders<T> { | ||
727 | crate::Binders::wrap_empty(value) | ||
728 | } | ||
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs index 65feb82e5..aef6b8a15 100644 --- a/crates/hir_ty/src/traits/chalk/mapping.rs +++ b/crates/hir_ty/src/traits/chalk/mapping.rs | |||
@@ -7,15 +7,14 @@ use chalk_ir::{cast::Cast, fold::shift::Shift, interner::HasInterner, LifetimeDa | |||
7 | use chalk_solve::rust_ir; | 7 | use chalk_solve::rust_ir; |
8 | 8 | ||
9 | use base_db::salsa::InternKey; | 9 | use base_db::salsa::InternKey; |
10 | use hir_def::{AssocContainerId, GenericDefId, Lookup, TypeAliasId}; | 10 | use hir_def::{GenericDefId, TypeAliasId}; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | db::HirDatabase, | 13 | db::HirDatabase, |
14 | from_assoc_type_id, | ||
15 | primitive::UintTy, | 14 | primitive::UintTy, |
16 | traits::{Canonical, DomainGoal}, | 15 | traits::{Canonical, DomainGoal}, |
17 | AliasTy, CallableDefId, FnPointer, InEnvironment, OpaqueTy, ProjectionTy, Scalar, Substitution, | 16 | AliasTy, CallableDefId, FnPointer, InEnvironment, OpaqueTy, ProjectionTy, |
18 | TraitRef, Ty, WhereClause, | 17 | QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TypeWalk, WhereClause, |
19 | }; | 18 | }; |
20 | 19 | ||
21 | use super::interner::*; | 20 | use super::interner::*; |
@@ -95,10 +94,10 @@ impl ToChalk for Ty { | |||
95 | TyKind::Placeholder(idx) => idx.to_ty::<Interner>(&Interner), | 94 | TyKind::Placeholder(idx) => idx.to_ty::<Interner>(&Interner), |
96 | TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner), | 95 | TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner), |
97 | TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"), | 96 | TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"), |
98 | TyKind::Dyn(predicates) => { | 97 | TyKind::Dyn(dyn_ty) => { |
99 | let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter( | 98 | let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter( |
100 | &Interner, | 99 | &Interner, |
101 | predicates.iter().cloned().map(|p| p.to_chalk(db)), | 100 | dyn_ty.bounds.value.interned().iter().cloned().map(|p| p.to_chalk(db)), |
102 | ); | 101 | ); |
103 | let bounded_ty = chalk_ir::DynTy { | 102 | let bounded_ty = chalk_ir::DynTy { |
104 | bounds: make_binders(where_clauses, 1), | 103 | bounds: make_binders(where_clauses, 1), |
@@ -144,13 +143,17 @@ impl ToChalk for Ty { | |||
144 | chalk_ir::TyKind::InferenceVar(_iv, _kind) => TyKind::Unknown, | 143 | chalk_ir::TyKind::InferenceVar(_iv, _kind) => TyKind::Unknown, |
145 | chalk_ir::TyKind::Dyn(where_clauses) => { | 144 | chalk_ir::TyKind::Dyn(where_clauses) => { |
146 | assert_eq!(where_clauses.bounds.binders.len(&Interner), 1); | 145 | assert_eq!(where_clauses.bounds.binders.len(&Interner), 1); |
147 | let predicates = where_clauses | 146 | let bounds = where_clauses |
148 | .bounds | 147 | .bounds |
149 | .skip_binders() | 148 | .skip_binders() |
150 | .iter(&Interner) | 149 | .iter(&Interner) |
151 | .map(|c| from_chalk(db, c.clone())) | 150 | .map(|c| from_chalk(db, c.clone())); |
152 | .collect(); | 151 | TyKind::Dyn(crate::DynTy { |
153 | TyKind::Dyn(predicates) | 152 | bounds: crate::Binders::new( |
153 | 1, | ||
154 | crate::QuantifiedWhereClauses::from_iter(&Interner, bounds), | ||
155 | ), | ||
156 | }) | ||
154 | } | 157 | } |
155 | 158 | ||
156 | chalk_ir::TyKind::Adt(adt_id, subst) => TyKind::Adt(adt_id, from_chalk(db, subst)), | 159 | chalk_ir::TyKind::Adt(adt_id, subst) => TyKind::Adt(adt_id, from_chalk(db, subst)), |
@@ -305,33 +308,22 @@ impl ToChalk for TypeAliasAsValue { | |||
305 | } | 308 | } |
306 | 309 | ||
307 | impl ToChalk for WhereClause { | 310 | impl ToChalk for WhereClause { |
308 | type Chalk = chalk_ir::QuantifiedWhereClause<Interner>; | 311 | type Chalk = chalk_ir::WhereClause<Interner>; |
309 | 312 | ||
310 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::QuantifiedWhereClause<Interner> { | 313 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::WhereClause<Interner> { |
311 | match self { | 314 | match self { |
312 | WhereClause::Implemented(trait_ref) => { | 315 | WhereClause::Implemented(trait_ref) => { |
313 | let chalk_trait_ref = trait_ref.to_chalk(db); | 316 | chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)) |
314 | let chalk_trait_ref = chalk_trait_ref.shifted_in(&Interner); | ||
315 | make_binders(chalk_ir::WhereClause::Implemented(chalk_trait_ref), 0) | ||
316 | } | 317 | } |
317 | WhereClause::AliasEq(alias_eq) => make_binders( | 318 | WhereClause::AliasEq(alias_eq) => chalk_ir::WhereClause::AliasEq(alias_eq.to_chalk(db)), |
318 | chalk_ir::WhereClause::AliasEq(alias_eq.to_chalk(db).shifted_in(&Interner)), | ||
319 | 0, | ||
320 | ), | ||
321 | } | 319 | } |
322 | } | 320 | } |
323 | 321 | ||
324 | fn from_chalk( | 322 | fn from_chalk( |
325 | db: &dyn HirDatabase, | 323 | db: &dyn HirDatabase, |
326 | where_clause: chalk_ir::QuantifiedWhereClause<Interner>, | 324 | where_clause: chalk_ir::WhereClause<Interner>, |
327 | ) -> WhereClause { | 325 | ) -> WhereClause { |
328 | // we don't produce any where clauses with binders and can't currently deal with them | 326 | match where_clause { |
329 | match where_clause | ||
330 | .skip_binders() | ||
331 | .clone() | ||
332 | .shifted_out(&Interner) | ||
333 | .expect("unexpected bound vars in where clause") | ||
334 | { | ||
335 | chalk_ir::WhereClause::Implemented(tr) => WhereClause::Implemented(from_chalk(db, tr)), | 327 | chalk_ir::WhereClause::Implemented(tr) => WhereClause::Implemented(from_chalk(db, tr)), |
336 | chalk_ir::WhereClause::AliasEq(alias_eq) => { | 328 | chalk_ir::WhereClause::AliasEq(alias_eq) => { |
337 | WhereClause::AliasEq(from_chalk(db, alias_eq)) | 329 | WhereClause::AliasEq(from_chalk(db, alias_eq)) |
@@ -447,35 +439,12 @@ where | |||
447 | type Chalk = chalk_ir::Canonical<T::Chalk>; | 439 | type Chalk = chalk_ir::Canonical<T::Chalk>; |
448 | 440 | ||
449 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> { | 441 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> { |
450 | let kinds = self.kinds.iter().map(|&tk| { | ||
451 | chalk_ir::CanonicalVarKind::new( | ||
452 | chalk_ir::VariableKind::Ty(tk), | ||
453 | chalk_ir::UniverseIndex::ROOT, | ||
454 | ) | ||
455 | }); | ||
456 | let value = self.value.to_chalk(db); | 442 | let value = self.value.to_chalk(db); |
457 | chalk_ir::Canonical { | 443 | chalk_ir::Canonical { value, binders: self.binders } |
458 | value, | ||
459 | binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds), | ||
460 | } | ||
461 | } | 444 | } |
462 | 445 | ||
463 | fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> { | 446 | fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> { |
464 | let kinds = canonical | 447 | Canonical { binders: canonical.binders, value: from_chalk(db, canonical.value) } |
465 | .binders | ||
466 | .iter(&Interner) | ||
467 | .map(|k| match k.kind { | ||
468 | chalk_ir::VariableKind::Ty(tk) => tk, | ||
469 | // HACK: Chalk can sometimes return new lifetime variables. We | ||
470 | // want to just skip them, but to not mess up the indices of | ||
471 | // other variables, we'll just create a new type variable in | ||
472 | // their place instead. This should not matter (we never see the | ||
473 | // actual *uses* of the lifetime variable). | ||
474 | chalk_ir::VariableKind::Lifetime => chalk_ir::TyVariableKind::General, | ||
475 | chalk_ir::VariableKind::Const(_) => panic!("unexpected const from Chalk"), | ||
476 | }) | ||
477 | .collect(); | ||
478 | Canonical { kinds, value: from_chalk(db, canonical.value) } | ||
479 | } | 448 | } |
480 | } | 449 | } |
481 | 450 | ||
@@ -486,10 +455,7 @@ where | |||
486 | type Chalk = chalk_ir::InEnvironment<T::Chalk>; | 455 | type Chalk = chalk_ir::InEnvironment<T::Chalk>; |
487 | 456 | ||
488 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> { | 457 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> { |
489 | chalk_ir::InEnvironment { | 458 | chalk_ir::InEnvironment { environment: self.environment, goal: self.goal.to_chalk(db) } |
490 | environment: self.environment.env.clone(), | ||
491 | goal: self.value.to_chalk(db), | ||
492 | } | ||
493 | } | 459 | } |
494 | 460 | ||
495 | fn from_chalk( | 461 | fn from_chalk( |
@@ -500,6 +466,29 @@ where | |||
500 | } | 466 | } |
501 | } | 467 | } |
502 | 468 | ||
469 | impl<T: ToChalk> ToChalk for crate::Binders<T> | ||
470 | where | ||
471 | T::Chalk: chalk_ir::interner::HasInterner<Interner = Interner>, | ||
472 | { | ||
473 | type Chalk = chalk_ir::Binders<T::Chalk>; | ||
474 | |||
475 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Binders<T::Chalk> { | ||
476 | chalk_ir::Binders::new( | ||
477 | chalk_ir::VariableKinds::from_iter( | ||
478 | &Interner, | ||
479 | std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)) | ||
480 | .take(self.num_binders), | ||
481 | ), | ||
482 | self.value.to_chalk(db), | ||
483 | ) | ||
484 | } | ||
485 | |||
486 | fn from_chalk(db: &dyn HirDatabase, binders: chalk_ir::Binders<T::Chalk>) -> crate::Binders<T> { | ||
487 | let (v, b) = binders.into_value_and_skipped_binders(); | ||
488 | crate::Binders::new(b.len(&Interner), from_chalk(db, v)) | ||
489 | } | ||
490 | } | ||
491 | |||
503 | pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> | 492 | pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> |
504 | where | 493 | where |
505 | T: HasInterner<Interner = Interner>, | 494 | T: HasInterner<Interner = Interner>, |
@@ -529,14 +518,15 @@ pub(super) fn convert_where_clauses( | |||
529 | 518 | ||
530 | pub(super) fn generic_predicate_to_inline_bound( | 519 | pub(super) fn generic_predicate_to_inline_bound( |
531 | db: &dyn HirDatabase, | 520 | db: &dyn HirDatabase, |
532 | pred: &WhereClause, | 521 | pred: &QuantifiedWhereClause, |
533 | self_ty: &Ty, | 522 | self_ty: &Ty, |
534 | ) -> Option<rust_ir::InlineBound<Interner>> { | 523 | ) -> Option<chalk_ir::Binders<rust_ir::InlineBound<Interner>>> { |
535 | // An InlineBound is like a GenericPredicate, except the self type is left out. | 524 | // An InlineBound is like a GenericPredicate, except the self type is left out. |
536 | // We don't have a special type for this, but Chalk does. | 525 | // We don't have a special type for this, but Chalk does. |
537 | match pred { | 526 | let self_ty_shifted_in = self_ty.clone().shift_bound_vars(DebruijnIndex::ONE); |
527 | match &pred.value { | ||
538 | WhereClause::Implemented(trait_ref) => { | 528 | WhereClause::Implemented(trait_ref) => { |
539 | if &trait_ref.substitution[0] != self_ty { | 529 | if trait_ref.self_type_parameter() != &self_ty_shifted_in { |
540 | // we can only convert predicates back to type bounds if they | 530 | // we can only convert predicates back to type bounds if they |
541 | // have the expected self type | 531 | // have the expected self type |
542 | return None; | 532 | return None; |
@@ -546,19 +536,13 @@ pub(super) fn generic_predicate_to_inline_bound( | |||
546 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) | 536 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) |
547 | .collect(); | 537 | .collect(); |
548 | let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self }; | 538 | let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self }; |
549 | Some(rust_ir::InlineBound::TraitBound(trait_bound)) | 539 | Some(make_binders(rust_ir::InlineBound::TraitBound(trait_bound), pred.num_binders)) |
550 | } | 540 | } |
551 | WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { | 541 | WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { |
552 | if &projection_ty.substitution[0] != self_ty { | 542 | if projection_ty.self_type_parameter() != &self_ty_shifted_in { |
553 | return None; | 543 | return None; |
554 | } | 544 | } |
555 | let trait_ = match from_assoc_type_id(projection_ty.associated_ty_id) | 545 | let trait_ = projection_ty.trait_(db); |
556 | .lookup(db.upcast()) | ||
557 | .container | ||
558 | { | ||
559 | AssocContainerId::TraitId(t) => t, | ||
560 | _ => panic!("associated type not in trait"), | ||
561 | }; | ||
562 | let args_no_self = projection_ty.substitution[1..] | 546 | let args_no_self = projection_ty.substitution[1..] |
563 | .iter() | 547 | .iter() |
564 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) | 548 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) |
@@ -569,7 +553,7 @@ pub(super) fn generic_predicate_to_inline_bound( | |||
569 | associated_ty_id: projection_ty.associated_ty_id, | 553 | associated_ty_id: projection_ty.associated_ty_id, |
570 | parameters: Vec::new(), // FIXME we don't support generic associated types yet | 554 | parameters: Vec::new(), // FIXME we don't support generic associated types yet |
571 | }; | 555 | }; |
572 | Some(rust_ir::InlineBound::AliasEqBound(alias_eq_bound)) | 556 | Some(make_binders(rust_ir::InlineBound::AliasEqBound(alias_eq_bound), pred.num_binders)) |
573 | } | 557 | } |
574 | _ => None, | 558 | _ => None, |
575 | } | 559 | } |
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs index 1ec1ecd43..19874e42b 100644 --- a/crates/hir_ty/src/utils.rs +++ b/crates/hir_ty/src/utils.rs | |||
@@ -63,7 +63,7 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr | |||
63 | db.generic_predicates_for_param(trait_self) | 63 | db.generic_predicates_for_param(trait_self) |
64 | .iter() | 64 | .iter() |
65 | .filter_map(|pred| { | 65 | .filter_map(|pred| { |
66 | pred.as_ref().filter_map(|pred| match pred { | 66 | pred.as_ref().filter_map(|pred| match pred.skip_binders() { |
67 | WhereClause::Implemented(tr) => Some(tr.clone()), | 67 | WhereClause::Implemented(tr) => Some(tr.clone()), |
68 | _ => None, | 68 | _ => None, |
69 | }) | 69 | }) |
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 662da5a96..3f73c0632 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs | |||
@@ -37,6 +37,7 @@ mod hover; | |||
37 | mod inlay_hints; | 37 | mod inlay_hints; |
38 | mod join_lines; | 38 | mod join_lines; |
39 | mod matching_brace; | 39 | mod matching_brace; |
40 | mod move_item; | ||
40 | mod parent_module; | 41 | mod parent_module; |
41 | mod references; | 42 | mod references; |
42 | mod fn_references; | 43 | mod fn_references; |
@@ -76,6 +77,7 @@ pub use crate::{ | |||
76 | hover::{HoverAction, HoverConfig, HoverGotoTypeData, HoverResult}, | 77 | hover::{HoverAction, HoverConfig, HoverGotoTypeData, HoverResult}, |
77 | inlay_hints::{InlayHint, InlayHintsConfig, InlayKind}, | 78 | inlay_hints::{InlayHint, InlayHintsConfig, InlayKind}, |
78 | markup::Markup, | 79 | markup::Markup, |
80 | move_item::Direction, | ||
79 | prime_caches::PrimeCachesProgress, | 81 | prime_caches::PrimeCachesProgress, |
80 | references::{rename::RenameError, ReferenceSearchResult}, | 82 | references::{rename::RenameError, ReferenceSearchResult}, |
81 | runnables::{Runnable, RunnableKind, TestId}, | 83 | runnables::{Runnable, RunnableKind, TestId}, |
@@ -583,6 +585,14 @@ impl Analysis { | |||
583 | self.with_db(|db| annotations::resolve_annotation(db, annotation)) | 585 | self.with_db(|db| annotations::resolve_annotation(db, annotation)) |
584 | } | 586 | } |
585 | 587 | ||
588 | pub fn move_item( | ||
589 | &self, | ||
590 | range: FileRange, | ||
591 | direction: Direction, | ||
592 | ) -> Cancelable<Option<TextEdit>> { | ||
593 | self.with_db(|db| move_item::move_item(db, range, direction)) | ||
594 | } | ||
595 | |||
586 | /// Performs an operation on that may be Canceled. | 596 | /// Performs an operation on that may be Canceled. |
587 | fn with_db<F, T>(&self, f: F) -> Cancelable<T> | 597 | fn with_db<F, T>(&self, f: F) -> Cancelable<T> |
588 | where | 598 | where |
diff --git a/crates/ide/src/move_item.rs b/crates/ide/src/move_item.rs new file mode 100644 index 000000000..48690b073 --- /dev/null +++ b/crates/ide/src/move_item.rs | |||
@@ -0,0 +1,620 @@ | |||
1 | use std::iter::once; | ||
2 | |||
3 | use hir::Semantics; | ||
4 | use ide_db::{base_db::FileRange, RootDatabase}; | ||
5 | use itertools::Itertools; | ||
6 | use syntax::{ | ||
7 | algo, ast, match_ast, AstNode, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode, TextRange, | ||
8 | }; | ||
9 | use text_edit::{TextEdit, TextEditBuilder}; | ||
10 | |||
11 | pub enum Direction { | ||
12 | Up, | ||
13 | Down, | ||
14 | } | ||
15 | |||
16 | // Feature: Move Item | ||
17 | // | ||
18 | // Move item under cursor or selection up and down. | ||
19 | // | ||
20 | // |=== | ||
21 | // | Editor | Action Name | ||
22 | // | ||
23 | // | VS Code | **Rust Analyzer: Move item up** | ||
24 | // | VS Code | **Rust Analyzer: Move item down** | ||
25 | // |=== | ||
26 | pub(crate) fn move_item( | ||
27 | db: &RootDatabase, | ||
28 | range: FileRange, | ||
29 | direction: Direction, | ||
30 | ) -> Option<TextEdit> { | ||
31 | let sema = Semantics::new(db); | ||
32 | let file = sema.parse(range.file_id); | ||
33 | |||
34 | let item = file.syntax().covering_element(range.range); | ||
35 | find_ancestors(item, direction, range.range) | ||
36 | } | ||
37 | |||
38 | fn find_ancestors(item: SyntaxElement, direction: Direction, range: TextRange) -> Option<TextEdit> { | ||
39 | let root = match item { | ||
40 | NodeOrToken::Node(node) => node, | ||
41 | NodeOrToken::Token(token) => token.parent()?, | ||
42 | }; | ||
43 | |||
44 | let movable = [ | ||
45 | SyntaxKind::ARG_LIST, | ||
46 | SyntaxKind::GENERIC_PARAM_LIST, | ||
47 | SyntaxKind::GENERIC_ARG_LIST, | ||
48 | SyntaxKind::VARIANT_LIST, | ||
49 | SyntaxKind::TYPE_BOUND_LIST, | ||
50 | SyntaxKind::MATCH_ARM, | ||
51 | SyntaxKind::PARAM, | ||
52 | SyntaxKind::LET_STMT, | ||
53 | SyntaxKind::EXPR_STMT, | ||
54 | SyntaxKind::MATCH_EXPR, | ||
55 | SyntaxKind::MACRO_CALL, | ||
56 | SyntaxKind::TYPE_ALIAS, | ||
57 | SyntaxKind::TRAIT, | ||
58 | SyntaxKind::IMPL, | ||
59 | SyntaxKind::MACRO_DEF, | ||
60 | SyntaxKind::STRUCT, | ||
61 | SyntaxKind::UNION, | ||
62 | SyntaxKind::ENUM, | ||
63 | SyntaxKind::FN, | ||
64 | SyntaxKind::MODULE, | ||
65 | SyntaxKind::USE, | ||
66 | SyntaxKind::STATIC, | ||
67 | SyntaxKind::CONST, | ||
68 | SyntaxKind::MACRO_RULES, | ||
69 | ]; | ||
70 | |||
71 | let ancestor = once(root.clone()) | ||
72 | .chain(root.ancestors()) | ||
73 | .find(|ancestor| movable.contains(&ancestor.kind()))?; | ||
74 | |||
75 | move_in_direction(&ancestor, direction, range) | ||
76 | } | ||
77 | |||
78 | fn move_in_direction( | ||
79 | node: &SyntaxNode, | ||
80 | direction: Direction, | ||
81 | range: TextRange, | ||
82 | ) -> Option<TextEdit> { | ||
83 | match_ast! { | ||
84 | match node { | ||
85 | ast::ArgList(it) => swap_sibling_in_list(it.args(), range, direction), | ||
86 | ast::GenericParamList(it) => swap_sibling_in_list(it.generic_params(), range, direction), | ||
87 | ast::GenericArgList(it) => swap_sibling_in_list(it.generic_args(), range, direction), | ||
88 | ast::VariantList(it) => swap_sibling_in_list(it.variants(), range, direction), | ||
89 | ast::TypeBoundList(it) => swap_sibling_in_list(it.bounds(), range, direction), | ||
90 | _ => Some(replace_nodes(node, &match direction { | ||
91 | Direction::Up => node.prev_sibling(), | ||
92 | Direction::Down => node.next_sibling(), | ||
93 | }?)) | ||
94 | } | ||
95 | } | ||
96 | } | ||
97 | |||
98 | fn swap_sibling_in_list<A: AstNode + Clone, I: Iterator<Item = A>>( | ||
99 | list: I, | ||
100 | range: TextRange, | ||
101 | direction: Direction, | ||
102 | ) -> Option<TextEdit> { | ||
103 | let (l, r) = list | ||
104 | .tuple_windows() | ||
105 | .filter(|(l, r)| match direction { | ||
106 | Direction::Up => r.syntax().text_range().contains_range(range), | ||
107 | Direction::Down => l.syntax().text_range().contains_range(range), | ||
108 | }) | ||
109 | .next()?; | ||
110 | |||
111 | Some(replace_nodes(l.syntax(), r.syntax())) | ||
112 | } | ||
113 | |||
114 | fn replace_nodes(first: &SyntaxNode, second: &SyntaxNode) -> TextEdit { | ||
115 | let mut edit = TextEditBuilder::default(); | ||
116 | |||
117 | algo::diff(first, second).into_text_edit(&mut edit); | ||
118 | algo::diff(second, first).into_text_edit(&mut edit); | ||
119 | |||
120 | edit.finish() | ||
121 | } | ||
122 | |||
123 | #[cfg(test)] | ||
124 | mod tests { | ||
125 | use crate::fixture; | ||
126 | use expect_test::{expect, Expect}; | ||
127 | |||
128 | use crate::Direction; | ||
129 | |||
130 | fn check(ra_fixture: &str, expect: Expect, direction: Direction) { | ||
131 | let (analysis, range) = fixture::range(ra_fixture); | ||
132 | let edit = analysis.move_item(range, direction).unwrap().unwrap_or_default(); | ||
133 | let mut file = analysis.file_text(range.file_id).unwrap().to_string(); | ||
134 | edit.apply(&mut file); | ||
135 | expect.assert_eq(&file); | ||
136 | } | ||
137 | |||
138 | #[test] | ||
139 | fn test_moves_match_arm_up() { | ||
140 | check( | ||
141 | r#" | ||
142 | fn main() { | ||
143 | match true { | ||
144 | true => { | ||
145 | println!("Hello, world"); | ||
146 | }, | ||
147 | false =>$0$0 { | ||
148 | println!("Test"); | ||
149 | } | ||
150 | }; | ||
151 | } | ||
152 | "#, | ||
153 | expect![[r#" | ||
154 | fn main() { | ||
155 | match true { | ||
156 | false => { | ||
157 | println!("Test"); | ||
158 | }, | ||
159 | true => { | ||
160 | println!("Hello, world"); | ||
161 | } | ||
162 | }; | ||
163 | } | ||
164 | "#]], | ||
165 | Direction::Up, | ||
166 | ); | ||
167 | } | ||
168 | |||
169 | #[test] | ||
170 | fn test_moves_match_arm_down() { | ||
171 | check( | ||
172 | r#" | ||
173 | fn main() { | ||
174 | match true { | ||
175 | true =>$0$0 { | ||
176 | println!("Hello, world"); | ||
177 | }, | ||
178 | false => { | ||
179 | println!("Test"); | ||
180 | } | ||
181 | }; | ||
182 | } | ||
183 | "#, | ||
184 | expect![[r#" | ||
185 | fn main() { | ||
186 | match true { | ||
187 | false => { | ||
188 | println!("Test"); | ||
189 | }, | ||
190 | true => { | ||
191 | println!("Hello, world"); | ||
192 | } | ||
193 | }; | ||
194 | } | ||
195 | "#]], | ||
196 | Direction::Down, | ||
197 | ); | ||
198 | } | ||
199 | |||
200 | #[test] | ||
201 | fn test_nowhere_to_move() { | ||
202 | check( | ||
203 | r#" | ||
204 | fn main() { | ||
205 | match true { | ||
206 | true =>$0$0 { | ||
207 | println!("Hello, world"); | ||
208 | }, | ||
209 | false => { | ||
210 | println!("Test"); | ||
211 | } | ||
212 | }; | ||
213 | } | ||
214 | "#, | ||
215 | expect![[r#" | ||
216 | fn main() { | ||
217 | match true { | ||
218 | true => { | ||
219 | println!("Hello, world"); | ||
220 | }, | ||
221 | false => { | ||
222 | println!("Test"); | ||
223 | } | ||
224 | }; | ||
225 | } | ||
226 | "#]], | ||
227 | Direction::Up, | ||
228 | ); | ||
229 | } | ||
230 | |||
231 | #[test] | ||
232 | fn test_moves_let_stmt_up() { | ||
233 | check( | ||
234 | r#" | ||
235 | fn main() { | ||
236 | let test = 123; | ||
237 | let test2$0$0 = 456; | ||
238 | } | ||
239 | "#, | ||
240 | expect![[r#" | ||
241 | fn main() { | ||
242 | let test2 = 456; | ||
243 | let test = 123; | ||
244 | } | ||
245 | "#]], | ||
246 | Direction::Up, | ||
247 | ); | ||
248 | } | ||
249 | |||
250 | #[test] | ||
251 | fn test_moves_expr_up() { | ||
252 | check( | ||
253 | r#" | ||
254 | fn main() { | ||
255 | println!("Hello, world"); | ||
256 | println!("All I want to say is...");$0$0 | ||
257 | } | ||
258 | "#, | ||
259 | expect![[r#" | ||
260 | fn main() { | ||
261 | println!("All I want to say is..."); | ||
262 | println!("Hello, world"); | ||
263 | } | ||
264 | "#]], | ||
265 | Direction::Up, | ||
266 | ); | ||
267 | } | ||
268 | |||
269 | #[test] | ||
270 | fn test_nowhere_to_move_stmt() { | ||
271 | check( | ||
272 | r#" | ||
273 | fn main() { | ||
274 | println!("All I want to say is...");$0$0 | ||
275 | println!("Hello, world"); | ||
276 | } | ||
277 | "#, | ||
278 | expect![[r#" | ||
279 | fn main() { | ||
280 | println!("All I want to say is..."); | ||
281 | println!("Hello, world"); | ||
282 | } | ||
283 | "#]], | ||
284 | Direction::Up, | ||
285 | ); | ||
286 | } | ||
287 | |||
288 | #[test] | ||
289 | fn test_move_item() { | ||
290 | check( | ||
291 | r#" | ||
292 | fn main() {} | ||
293 | |||
294 | fn foo() {}$0$0 | ||
295 | "#, | ||
296 | expect![[r#" | ||
297 | fn foo() {} | ||
298 | |||
299 | fn main() {} | ||
300 | "#]], | ||
301 | Direction::Up, | ||
302 | ); | ||
303 | } | ||
304 | |||
305 | #[test] | ||
306 | fn test_move_impl_up() { | ||
307 | check( | ||
308 | r#" | ||
309 | struct Yay; | ||
310 | |||
311 | trait Wow {} | ||
312 | |||
313 | impl Wow for Yay $0$0{} | ||
314 | "#, | ||
315 | expect![[r#" | ||
316 | struct Yay; | ||
317 | |||
318 | impl Wow for Yay {} | ||
319 | |||
320 | trait Wow {} | ||
321 | "#]], | ||
322 | Direction::Up, | ||
323 | ); | ||
324 | } | ||
325 | |||
326 | #[test] | ||
327 | fn test_move_use_up() { | ||
328 | check( | ||
329 | r#" | ||
330 | use std::vec::Vec; | ||
331 | use std::collections::HashMap$0$0; | ||
332 | "#, | ||
333 | expect![[r#" | ||
334 | use std::collections::HashMap; | ||
335 | use std::vec::Vec; | ||
336 | "#]], | ||
337 | Direction::Up, | ||
338 | ); | ||
339 | } | ||
340 | |||
341 | #[test] | ||
342 | fn test_moves_match_expr_up() { | ||
343 | check( | ||
344 | r#" | ||
345 | fn main() { | ||
346 | let test = 123; | ||
347 | |||
348 | $0match test { | ||
349 | 456 => {}, | ||
350 | _ => {} | ||
351 | };$0 | ||
352 | } | ||
353 | "#, | ||
354 | expect![[r#" | ||
355 | fn main() { | ||
356 | match test { | ||
357 | 456 => {}, | ||
358 | _ => {} | ||
359 | }; | ||
360 | |||
361 | let test = 123; | ||
362 | } | ||
363 | "#]], | ||
364 | Direction::Up, | ||
365 | ); | ||
366 | } | ||
367 | |||
368 | #[test] | ||
369 | fn test_moves_param_up() { | ||
370 | check( | ||
371 | r#" | ||
372 | fn test(one: i32, two$0$0: u32) {} | ||
373 | |||
374 | fn main() { | ||
375 | test(123, 456); | ||
376 | } | ||
377 | "#, | ||
378 | expect![[r#" | ||
379 | fn test(two: u32, one: i32) {} | ||
380 | |||
381 | fn main() { | ||
382 | test(123, 456); | ||
383 | } | ||
384 | "#]], | ||
385 | Direction::Up, | ||
386 | ); | ||
387 | } | ||
388 | |||
389 | #[test] | ||
390 | fn test_moves_arg_up() { | ||
391 | check( | ||
392 | r#" | ||
393 | fn test(one: i32, two: u32) {} | ||
394 | |||
395 | fn main() { | ||
396 | test(123, 456$0$0); | ||
397 | } | ||
398 | "#, | ||
399 | expect![[r#" | ||
400 | fn test(one: i32, two: u32) {} | ||
401 | |||
402 | fn main() { | ||
403 | test(456, 123); | ||
404 | } | ||
405 | "#]], | ||
406 | Direction::Up, | ||
407 | ); | ||
408 | } | ||
409 | |||
410 | #[test] | ||
411 | fn test_moves_arg_down() { | ||
412 | check( | ||
413 | r#" | ||
414 | fn test(one: i32, two: u32) {} | ||
415 | |||
416 | fn main() { | ||
417 | test(123$0$0, 456); | ||
418 | } | ||
419 | "#, | ||
420 | expect![[r#" | ||
421 | fn test(one: i32, two: u32) {} | ||
422 | |||
423 | fn main() { | ||
424 | test(456, 123); | ||
425 | } | ||
426 | "#]], | ||
427 | Direction::Down, | ||
428 | ); | ||
429 | } | ||
430 | |||
431 | #[test] | ||
432 | fn test_nowhere_to_move_arg() { | ||
433 | check( | ||
434 | r#" | ||
435 | fn test(one: i32, two: u32) {} | ||
436 | |||
437 | fn main() { | ||
438 | test(123$0$0, 456); | ||
439 | } | ||
440 | "#, | ||
441 | expect![[r#" | ||
442 | fn test(one: i32, two: u32) {} | ||
443 | |||
444 | fn main() { | ||
445 | test(123, 456); | ||
446 | } | ||
447 | "#]], | ||
448 | Direction::Up, | ||
449 | ); | ||
450 | } | ||
451 | |||
452 | #[test] | ||
453 | fn test_moves_generic_param_up() { | ||
454 | check( | ||
455 | r#" | ||
456 | struct Test<A, B$0$0>(A, B); | ||
457 | |||
458 | fn main() {} | ||
459 | "#, | ||
460 | expect![[r#" | ||
461 | struct Test<B, A>(A, B); | ||
462 | |||
463 | fn main() {} | ||
464 | "#]], | ||
465 | Direction::Up, | ||
466 | ); | ||
467 | } | ||
468 | |||
469 | #[test] | ||
470 | fn test_moves_generic_arg_up() { | ||
471 | check( | ||
472 | r#" | ||
473 | struct Test<A, B>(A, B); | ||
474 | |||
475 | fn main() { | ||
476 | let t = Test::<i32, &str$0$0>(123, "yay"); | ||
477 | } | ||
478 | "#, | ||
479 | expect![[r#" | ||
480 | struct Test<A, B>(A, B); | ||
481 | |||
482 | fn main() { | ||
483 | let t = Test::<&str, i32>(123, "yay"); | ||
484 | } | ||
485 | "#]], | ||
486 | Direction::Up, | ||
487 | ); | ||
488 | } | ||
489 | |||
490 | #[test] | ||
491 | fn test_moves_variant_up() { | ||
492 | check( | ||
493 | r#" | ||
494 | enum Hello { | ||
495 | One, | ||
496 | Two$0$0 | ||
497 | } | ||
498 | |||
499 | fn main() {} | ||
500 | "#, | ||
501 | expect![[r#" | ||
502 | enum Hello { | ||
503 | Two, | ||
504 | One | ||
505 | } | ||
506 | |||
507 | fn main() {} | ||
508 | "#]], | ||
509 | Direction::Up, | ||
510 | ); | ||
511 | } | ||
512 | |||
513 | #[test] | ||
514 | fn test_moves_type_bound_up() { | ||
515 | check( | ||
516 | r#" | ||
517 | trait One {} | ||
518 | |||
519 | trait Two {} | ||
520 | |||
521 | fn test<T: One + Two$0$0>(t: T) {} | ||
522 | |||
523 | fn main() {} | ||
524 | "#, | ||
525 | expect![[r#" | ||
526 | trait One {} | ||
527 | |||
528 | trait Two {} | ||
529 | |||
530 | fn test<T: Two + One>(t: T) {} | ||
531 | |||
532 | fn main() {} | ||
533 | "#]], | ||
534 | Direction::Up, | ||
535 | ); | ||
536 | } | ||
537 | |||
538 | #[test] | ||
539 | fn test_prioritizes_trait_items() { | ||
540 | check( | ||
541 | r#" | ||
542 | struct Test; | ||
543 | |||
544 | trait Yay { | ||
545 | type One; | ||
546 | |||
547 | type Two; | ||
548 | |||
549 | fn inner(); | ||
550 | } | ||
551 | |||
552 | impl Yay for Test { | ||
553 | type One = i32; | ||
554 | |||
555 | type Two = u32; | ||
556 | |||
557 | fn inner() {$0$0 | ||
558 | println!("Mmmm"); | ||
559 | } | ||
560 | } | ||
561 | "#, | ||
562 | expect![[r#" | ||
563 | struct Test; | ||
564 | |||
565 | trait Yay { | ||
566 | type One; | ||
567 | |||
568 | type Two; | ||
569 | |||
570 | fn inner(); | ||
571 | } | ||
572 | |||
573 | impl Yay for Test { | ||
574 | type One = i32; | ||
575 | |||
576 | fn inner() { | ||
577 | println!("Mmmm"); | ||
578 | } | ||
579 | |||
580 | type Two = u32; | ||
581 | } | ||
582 | "#]], | ||
583 | Direction::Up, | ||
584 | ); | ||
585 | } | ||
586 | |||
587 | #[test] | ||
588 | fn test_weird_nesting() { | ||
589 | check( | ||
590 | r#" | ||
591 | fn test() { | ||
592 | mod hello { | ||
593 | fn inner() {} | ||
594 | } | ||
595 | |||
596 | mod hi {$0$0 | ||
597 | fn inner() {} | ||
598 | } | ||
599 | } | ||
600 | "#, | ||
601 | expect![[r#" | ||
602 | fn test() { | ||
603 | mod hi { | ||
604 | fn inner() {} | ||
605 | } | ||
606 | |||
607 | mod hello { | ||
608 | fn inner() {} | ||
609 | } | ||
610 | } | ||
611 | "#]], | ||
612 | Direction::Up, | ||
613 | ); | ||
614 | } | ||
615 | |||
616 | #[test] | ||
617 | fn handles_empty_file() { | ||
618 | check(r#"$0$0"#, expect![[r#""#]], Direction::Up); | ||
619 | } | ||
620 | } | ||
diff --git a/crates/ide_assists/src/handlers/merge_imports.rs b/crates/ide_assists/src/handlers/merge_imports.rs index 7bd7e1e36..cfc472a32 100644 --- a/crates/ide_assists/src/handlers/merge_imports.rs +++ b/crates/ide_assists/src/handlers/merge_imports.rs | |||
@@ -1,8 +1,5 @@ | |||
1 | use ide_db::helpers::insert_use::{try_merge_imports, try_merge_trees, MergeBehavior}; | 1 | use ide_db::helpers::insert_use::{try_merge_imports, try_merge_trees, MergeBehavior}; |
2 | use syntax::{ | 2 | use syntax::{algo::neighbor, ast, ted, AstNode}; |
3 | algo::{neighbor, SyntaxRewriter}, | ||
4 | ast, AstNode, | ||
5 | }; | ||
6 | 3 | ||
7 | use crate::{ | 4 | use crate::{ |
8 | assist_context::{AssistContext, Assists}, | 5 | assist_context::{AssistContext, Assists}, |
@@ -24,33 +21,29 @@ use crate::{ | |||
24 | // ``` | 21 | // ``` |
25 | pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 22 | pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
26 | let tree: ast::UseTree = ctx.find_node_at_offset()?; | 23 | let tree: ast::UseTree = ctx.find_node_at_offset()?; |
27 | let mut rewriter = SyntaxRewriter::default(); | 24 | let original_parent = tree.syntax().ancestors().last()?; |
25 | |||
26 | let tree = tree.clone_for_update(); | ||
27 | let new_parent = tree.syntax().ancestors().last()?; | ||
28 | |||
28 | let mut offset = ctx.offset(); | 29 | let mut offset = ctx.offset(); |
29 | 30 | ||
31 | let mut imports = None; | ||
32 | let mut uses = None; | ||
30 | if let Some(use_item) = tree.syntax().parent().and_then(ast::Use::cast) { | 33 | if let Some(use_item) = tree.syntax().parent().and_then(ast::Use::cast) { |
31 | let (merged, to_delete) = | 34 | let (merged, to_remove) = |
32 | next_prev().filter_map(|dir| neighbor(&use_item, dir)).find_map(|use_item2| { | 35 | next_prev().filter_map(|dir| neighbor(&use_item, dir)).find_map(|use_item2| { |
33 | try_merge_imports(&use_item, &use_item2, MergeBehavior::Full).zip(Some(use_item2)) | 36 | try_merge_imports(&use_item, &use_item2, MergeBehavior::Full).zip(Some(use_item2)) |
34 | })?; | 37 | })?; |
35 | 38 | ||
36 | rewriter.replace_ast(&use_item, &merged); | 39 | imports = Some((use_item, merged, to_remove)); |
37 | rewriter += to_delete.remove(); | ||
38 | |||
39 | if to_delete.syntax().text_range().end() < offset { | ||
40 | offset -= to_delete.syntax().text_range().len(); | ||
41 | } | ||
42 | } else { | 40 | } else { |
43 | let (merged, to_delete) = | 41 | let (merged, to_remove) = |
44 | next_prev().filter_map(|dir| neighbor(&tree, dir)).find_map(|use_tree| { | 42 | next_prev().filter_map(|dir| neighbor(&tree, dir)).find_map(|use_tree| { |
45 | try_merge_trees(&tree, &use_tree, MergeBehavior::Full).zip(Some(use_tree)) | 43 | try_merge_trees(&tree, &use_tree, MergeBehavior::Full).zip(Some(use_tree)) |
46 | })?; | 44 | })?; |
47 | 45 | ||
48 | rewriter.replace_ast(&tree, &merged); | 46 | uses = Some((tree.clone(), merged, to_remove)) |
49 | rewriter += to_delete.remove(); | ||
50 | |||
51 | if to_delete.syntax().text_range().end() < offset { | ||
52 | offset -= to_delete.syntax().text_range().len(); | ||
53 | } | ||
54 | }; | 47 | }; |
55 | 48 | ||
56 | let target = tree.syntax().text_range(); | 49 | let target = tree.syntax().text_range(); |
@@ -59,7 +52,23 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext) -> Option<() | |||
59 | "Merge imports", | 52 | "Merge imports", |
60 | target, | 53 | target, |
61 | |builder| { | 54 | |builder| { |
62 | builder.rewrite(rewriter); | 55 | if let Some((to_replace, replacement, to_remove)) = imports { |
56 | if to_remove.syntax().text_range().end() < offset { | ||
57 | offset -= to_remove.syntax().text_range().len(); | ||
58 | } | ||
59 | ted::replace(to_replace.syntax().clone(), replacement.syntax().clone()); | ||
60 | to_remove.remove(); | ||
61 | } | ||
62 | |||
63 | if let Some((to_replace, replacement, to_remove)) = uses { | ||
64 | if to_remove.syntax().text_range().end() < offset { | ||
65 | offset -= to_remove.syntax().text_range().len(); | ||
66 | } | ||
67 | ted::replace(to_replace.syntax().clone(), replacement.syntax().clone()); | ||
68 | to_remove.remove() | ||
69 | } | ||
70 | |||
71 | builder.replace(original_parent.text_range(), new_parent.to_string()) | ||
63 | }, | 72 | }, |
64 | ) | 73 | ) |
65 | } | 74 | } |
diff --git a/crates/ide_assists/src/handlers/unmerge_use.rs b/crates/ide_assists/src/handlers/unmerge_use.rs index 616af7c2e..8d271e056 100644 --- a/crates/ide_assists/src/handlers/unmerge_use.rs +++ b/crates/ide_assists/src/handlers/unmerge_use.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use syntax::{ | 1 | use syntax::{ |
2 | algo::SyntaxRewriter, | 2 | ast::{self, VisibilityOwner}, |
3 | ast::{self, edit::AstNodeEdit, VisibilityOwner}, | 3 | ted::{self, Position}, |
4 | AstNode, SyntaxKind, | 4 | AstNode, SyntaxKind, |
5 | }; | 5 | }; |
6 | 6 | ||
@@ -22,7 +22,7 @@ use crate::{ | |||
22 | // use std::fmt::Display; | 22 | // use std::fmt::Display; |
23 | // ``` | 23 | // ``` |
24 | pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 24 | pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
25 | let tree: ast::UseTree = ctx.find_node_at_offset()?; | 25 | let tree: ast::UseTree = ctx.find_node_at_offset::<ast::UseTree>()?.clone_for_update(); |
26 | 26 | ||
27 | let tree_list = tree.syntax().parent().and_then(ast::UseTreeList::cast)?; | 27 | let tree_list = tree.syntax().parent().and_then(ast::UseTreeList::cast)?; |
28 | if tree_list.use_trees().count() < 2 { | 28 | if tree_list.use_trees().count() < 2 { |
@@ -33,6 +33,9 @@ pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext) -> Option<()> | |||
33 | let use_: ast::Use = tree_list.syntax().ancestors().find_map(ast::Use::cast)?; | 33 | let use_: ast::Use = tree_list.syntax().ancestors().find_map(ast::Use::cast)?; |
34 | let path = resolve_full_path(&tree)?; | 34 | let path = resolve_full_path(&tree)?; |
35 | 35 | ||
36 | let old_parent_range = use_.syntax().parent()?.text_range(); | ||
37 | let new_parent = use_.syntax().parent()?; | ||
38 | |||
36 | let target = tree.syntax().text_range(); | 39 | let target = tree.syntax().text_range(); |
37 | acc.add( | 40 | acc.add( |
38 | AssistId("unmerge_use", AssistKind::RefactorRewrite), | 41 | AssistId("unmerge_use", AssistKind::RefactorRewrite), |
@@ -47,20 +50,13 @@ pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext) -> Option<()> | |||
47 | tree.rename(), | 50 | tree.rename(), |
48 | tree.star_token().is_some(), | 51 | tree.star_token().is_some(), |
49 | ), | 52 | ), |
50 | ); | 53 | ) |
51 | 54 | .clone_for_update(); | |
52 | let mut rewriter = SyntaxRewriter::default(); | 55 | |
53 | rewriter += tree.remove(); | 56 | tree.remove(); |
54 | rewriter.insert_after(use_.syntax(), &ast::make::tokens::single_newline()); | 57 | ted::insert(Position::after(use_.syntax()), new_use.syntax()); |
55 | if let ident_level @ 1..=usize::MAX = use_.indent_level().0 as usize { | 58 | |
56 | rewriter.insert_after( | 59 | builder.replace(old_parent_range, new_parent.to_string()); |
57 | use_.syntax(), | ||
58 | &ast::make::tokens::whitespace(&" ".repeat(4 * ident_level)), | ||
59 | ); | ||
60 | } | ||
61 | rewriter.insert_after(use_.syntax(), new_use.syntax()); | ||
62 | |||
63 | builder.rewrite(rewriter); | ||
64 | }, | 60 | }, |
65 | ) | 61 | ) |
66 | } | 62 | } |
diff --git a/crates/ide_db/src/helpers/insert_use.rs b/crates/ide_db/src/helpers/insert_use.rs index 9e0cb91c3..20c195f82 100644 --- a/crates/ide_db/src/helpers/insert_use.rs +++ b/crates/ide_db/src/helpers/insert_use.rs | |||
@@ -14,10 +14,12 @@ use syntax::{ | |||
14 | AstToken, InsertPosition, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxToken, | 14 | AstToken, InsertPosition, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxToken, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | pub use hir::PrefixKind; | ||
18 | |||
17 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] | 19 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] |
18 | pub struct InsertUseConfig { | 20 | pub struct InsertUseConfig { |
19 | pub merge: Option<MergeBehavior>, | 21 | pub merge: Option<MergeBehavior>, |
20 | pub prefix_kind: hir::PrefixKind, | 22 | pub prefix_kind: PrefixKind, |
21 | pub group: bool, | 23 | pub group: bool, |
22 | } | 24 | } |
23 | 25 | ||
@@ -211,7 +213,7 @@ pub fn try_merge_imports( | |||
211 | let lhs_tree = lhs.use_tree()?; | 213 | let lhs_tree = lhs.use_tree()?; |
212 | let rhs_tree = rhs.use_tree()?; | 214 | let rhs_tree = rhs.use_tree()?; |
213 | let merged = try_merge_trees(&lhs_tree, &rhs_tree, merge_behavior)?; | 215 | let merged = try_merge_trees(&lhs_tree, &rhs_tree, merge_behavior)?; |
214 | Some(lhs.with_use_tree(merged)) | 216 | Some(lhs.with_use_tree(merged).clone_for_update()) |
215 | } | 217 | } |
216 | 218 | ||
217 | pub fn try_merge_trees( | 219 | pub fn try_merge_trees( |
@@ -232,7 +234,7 @@ pub fn try_merge_trees( | |||
232 | } else { | 234 | } else { |
233 | (lhs.split_prefix(&lhs_prefix), rhs.split_prefix(&rhs_prefix)) | 235 | (lhs.split_prefix(&lhs_prefix), rhs.split_prefix(&rhs_prefix)) |
234 | }; | 236 | }; |
235 | recursive_merge(&lhs, &rhs, merge) | 237 | recursive_merge(&lhs, &rhs, merge).map(|it| it.clone_for_update()) |
236 | } | 238 | } |
237 | 239 | ||
238 | /// Recursively "zips" together lhs and rhs. | 240 | /// Recursively "zips" together lhs and rhs. |
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 8f541976e..5c88c3a9b 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -10,10 +10,9 @@ | |||
10 | use std::{ffi::OsString, iter, path::PathBuf}; | 10 | use std::{ffi::OsString, iter, path::PathBuf}; |
11 | 11 | ||
12 | use flycheck::FlycheckConfig; | 12 | use flycheck::FlycheckConfig; |
13 | use hir::PrefixKind; | ||
14 | use ide::{AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig}; | 13 | use ide::{AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig}; |
15 | use ide_db::helpers::{ | 14 | use ide_db::helpers::{ |
16 | insert_use::{InsertUseConfig, MergeBehavior}, | 15 | insert_use::{InsertUseConfig, MergeBehavior, PrefixKind}, |
17 | SnippetCap, | 16 | SnippetCap, |
18 | }; | 17 | }; |
19 | use lsp_types::{ClientCapabilities, MarkupKind}; | 18 | use lsp_types::{ClientCapabilities, MarkupKind}; |
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index 880fea622..85e67554c 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs | |||
@@ -1427,6 +1427,25 @@ pub(crate) fn handle_open_cargo_toml( | |||
1427 | Ok(Some(res)) | 1427 | Ok(Some(res)) |
1428 | } | 1428 | } |
1429 | 1429 | ||
1430 | pub(crate) fn handle_move_item( | ||
1431 | snap: GlobalStateSnapshot, | ||
1432 | params: lsp_ext::MoveItemParams, | ||
1433 | ) -> Result<Option<lsp_types::TextDocumentEdit>> { | ||
1434 | let _p = profile::span("handle_move_item"); | ||
1435 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; | ||
1436 | let range = from_proto::file_range(&snap, params.text_document, params.range)?; | ||
1437 | |||
1438 | let direction = match params.direction { | ||
1439 | lsp_ext::MoveItemDirection::Up => ide::Direction::Up, | ||
1440 | lsp_ext::MoveItemDirection::Down => ide::Direction::Down, | ||
1441 | }; | ||
1442 | |||
1443 | match snap.analysis.move_item(range, direction)? { | ||
1444 | Some(text_edit) => Ok(Some(to_proto::text_document_edit(&snap, file_id, text_edit)?)), | ||
1445 | None => Ok(None), | ||
1446 | } | ||
1447 | } | ||
1448 | |||
1430 | fn to_command_link(command: lsp_types::Command, tooltip: String) -> lsp_ext::CommandLink { | 1449 | fn to_command_link(command: lsp_types::Command, tooltip: String) -> lsp_ext::CommandLink { |
1431 | lsp_ext::CommandLink { tooltip: Some(tooltip), command } | 1450 | lsp_ext::CommandLink { tooltip: Some(tooltip), command } |
1432 | } | 1451 | } |
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs index efcdcd1d9..0e1fec209 100644 --- a/crates/rust-analyzer/src/lsp_ext.rs +++ b/crates/rust-analyzer/src/lsp_ext.rs | |||
@@ -402,3 +402,25 @@ pub(crate) enum CodeLensResolveData { | |||
402 | pub fn supports_utf8(caps: &lsp_types::ClientCapabilities) -> bool { | 402 | pub fn supports_utf8(caps: &lsp_types::ClientCapabilities) -> bool { |
403 | caps.offset_encoding.as_deref().unwrap_or_default().iter().any(|it| it == "utf-8") | 403 | caps.offset_encoding.as_deref().unwrap_or_default().iter().any(|it| it == "utf-8") |
404 | } | 404 | } |
405 | |||
406 | pub enum MoveItem {} | ||
407 | |||
408 | impl Request for MoveItem { | ||
409 | type Params = MoveItemParams; | ||
410 | type Result = Option<lsp_types::TextDocumentEdit>; | ||
411 | const METHOD: &'static str = "experimental/moveItem"; | ||
412 | } | ||
413 | |||
414 | #[derive(Serialize, Deserialize, Debug)] | ||
415 | #[serde(rename_all = "camelCase")] | ||
416 | pub struct MoveItemParams { | ||
417 | pub direction: MoveItemDirection, | ||
418 | pub text_document: TextDocumentIdentifier, | ||
419 | pub range: Range, | ||
420 | } | ||
421 | |||
422 | #[derive(Serialize, Deserialize, Debug)] | ||
423 | pub enum MoveItemDirection { | ||
424 | Up, | ||
425 | Down, | ||
426 | } | ||
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index c63a0eaea..e88f16cc1 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -504,6 +504,7 @@ impl GlobalState { | |||
504 | .on::<lsp_ext::HoverRequest>(handlers::handle_hover) | 504 | .on::<lsp_ext::HoverRequest>(handlers::handle_hover) |
505 | .on::<lsp_ext::ExternalDocs>(handlers::handle_open_docs) | 505 | .on::<lsp_ext::ExternalDocs>(handlers::handle_open_docs) |
506 | .on::<lsp_ext::OpenCargoToml>(handlers::handle_open_cargo_toml) | 506 | .on::<lsp_ext::OpenCargoToml>(handlers::handle_open_cargo_toml) |
507 | .on::<lsp_ext::MoveItem>(handlers::handle_move_item) | ||
507 | .on::<lsp_types::request::OnTypeFormatting>(handlers::handle_on_type_formatting) | 508 | .on::<lsp_types::request::OnTypeFormatting>(handlers::handle_on_type_formatting) |
508 | .on::<lsp_types::request::DocumentSymbolRequest>(handlers::handle_document_symbol) | 509 | .on::<lsp_types::request::DocumentSymbolRequest>(handlers::handle_document_symbol) |
509 | .on::<lsp_types::request::WorkspaceSymbol>(handlers::handle_workspace_symbol) | 510 | .on::<lsp_types::request::WorkspaceSymbol>(handlers::handle_workspace_symbol) |
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index 1ddea9278..25169005f 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs | |||
@@ -658,6 +658,18 @@ pub(crate) fn goto_definition_response( | |||
658 | } | 658 | } |
659 | } | 659 | } |
660 | 660 | ||
661 | pub(crate) fn text_document_edit( | ||
662 | snap: &GlobalStateSnapshot, | ||
663 | file_id: FileId, | ||
664 | edit: TextEdit, | ||
665 | ) -> Result<lsp_types::TextDocumentEdit> { | ||
666 | let text_document = optional_versioned_text_document_identifier(snap, file_id); | ||
667 | let line_index = snap.file_line_index(file_id)?; | ||
668 | let edits = | ||
669 | edit.into_iter().map(|it| lsp_types::OneOf::Left(text_edit(&line_index, it))).collect(); | ||
670 | Ok(lsp_types::TextDocumentEdit { text_document, edits }) | ||
671 | } | ||
672 | |||
661 | pub(crate) fn snippet_text_document_edit( | 673 | pub(crate) fn snippet_text_document_edit( |
662 | snap: &GlobalStateSnapshot, | 674 | snap: &GlobalStateSnapshot, |
663 | is_snippet: bool, | 675 | is_snippet: bool, |
@@ -1073,9 +1085,11 @@ pub(crate) fn rename_error(err: RenameError) -> crate::LspError { | |||
1073 | mod tests { | 1085 | mod tests { |
1074 | use std::sync::Arc; | 1086 | use std::sync::Arc; |
1075 | 1087 | ||
1076 | use hir::PrefixKind; | ||
1077 | use ide::Analysis; | 1088 | use ide::Analysis; |
1078 | use ide_db::helpers::{insert_use::InsertUseConfig, SnippetCap}; | 1089 | use ide_db::helpers::{ |
1090 | insert_use::{InsertUseConfig, PrefixKind}, | ||
1091 | SnippetCap, | ||
1092 | }; | ||
1079 | 1093 | ||
1080 | use super::*; | 1094 | use super::*; |
1081 | 1095 | ||
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml index 74cafaa8d..0c3fec3c7 100644 --- a/crates/syntax/Cargo.toml +++ b/crates/syntax/Cargo.toml | |||
@@ -13,7 +13,7 @@ doctest = false | |||
13 | [dependencies] | 13 | [dependencies] |
14 | cov-mark = { version = "1.1", features = ["thread-local"] } | 14 | cov-mark = { version = "1.1", features = ["thread-local"] } |
15 | itertools = "0.10.0" | 15 | itertools = "0.10.0" |
16 | rowan = "0.13.0-pre.2" | 16 | rowan = "0.13.0-pre.3" |
17 | rustc_lexer = { version = "710.0.0", package = "rustc-ap-rustc_lexer" } | 17 | rustc_lexer = { version = "710.0.0", package = "rustc-ap-rustc_lexer" } |
18 | rustc-hash = "1.1.0" | 18 | rustc-hash = "1.1.0" |
19 | arrayvec = "0.5.1" | 19 | arrayvec = "0.5.1" |
diff --git a/crates/syntax/src/ast/edit.rs b/crates/syntax/src/ast/edit.rs index 347862b8a..18820786a 100644 --- a/crates/syntax/src/ast/edit.rs +++ b/crates/syntax/src/ast/edit.rs | |||
@@ -9,7 +9,7 @@ use std::{ | |||
9 | use arrayvec::ArrayVec; | 9 | use arrayvec::ArrayVec; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | algo::{self, neighbor, SyntaxRewriter}, | 12 | algo::{self, SyntaxRewriter}, |
13 | ast::{ | 13 | ast::{ |
14 | self, | 14 | self, |
15 | make::{self, tokens}, | 15 | make::{self, tokens}, |
@@ -322,27 +322,6 @@ impl ast::Use { | |||
322 | } | 322 | } |
323 | self.clone() | 323 | self.clone() |
324 | } | 324 | } |
325 | |||
326 | pub fn remove(&self) -> SyntaxRewriter<'static> { | ||
327 | let mut res = SyntaxRewriter::default(); | ||
328 | res.delete(self.syntax()); | ||
329 | let next_ws = self | ||
330 | .syntax() | ||
331 | .next_sibling_or_token() | ||
332 | .and_then(|it| it.into_token()) | ||
333 | .and_then(ast::Whitespace::cast); | ||
334 | if let Some(next_ws) = next_ws { | ||
335 | let ws_text = next_ws.syntax().text(); | ||
336 | if let Some(rest) = ws_text.strip_prefix('\n') { | ||
337 | if rest.is_empty() { | ||
338 | res.delete(next_ws.syntax()) | ||
339 | } else { | ||
340 | res.replace(next_ws.syntax(), &make::tokens::whitespace(rest)); | ||
341 | } | ||
342 | } | ||
343 | } | ||
344 | res | ||
345 | } | ||
346 | } | 325 | } |
347 | 326 | ||
348 | impl ast::UseTree { | 327 | impl ast::UseTree { |
@@ -396,22 +375,6 @@ impl ast::UseTree { | |||
396 | Some(res) | 375 | Some(res) |
397 | } | 376 | } |
398 | } | 377 | } |
399 | |||
400 | pub fn remove(&self) -> SyntaxRewriter<'static> { | ||
401 | let mut res = SyntaxRewriter::default(); | ||
402 | res.delete(self.syntax()); | ||
403 | for &dir in [Direction::Next, Direction::Prev].iter() { | ||
404 | if let Some(nb) = neighbor(self, dir) { | ||
405 | self.syntax() | ||
406 | .siblings_with_tokens(dir) | ||
407 | .skip(1) | ||
408 | .take_while(|it| it.as_node() != Some(nb.syntax())) | ||
409 | .for_each(|el| res.delete(&el)); | ||
410 | return res; | ||
411 | } | ||
412 | } | ||
413 | res | ||
414 | } | ||
415 | } | 378 | } |
416 | 379 | ||
417 | impl ast::MatchArmList { | 380 | impl ast::MatchArmList { |
@@ -592,6 +555,13 @@ impl ops::Add<u8> for IndentLevel { | |||
592 | } | 555 | } |
593 | 556 | ||
594 | impl IndentLevel { | 557 | impl IndentLevel { |
558 | pub fn from_element(element: &SyntaxElement) -> IndentLevel { | ||
559 | match element { | ||
560 | rowan::NodeOrToken::Node(it) => IndentLevel::from_node(it), | ||
561 | rowan::NodeOrToken::Token(it) => IndentLevel::from_token(it), | ||
562 | } | ||
563 | } | ||
564 | |||
595 | pub fn from_node(node: &SyntaxNode) -> IndentLevel { | 565 | pub fn from_node(node: &SyntaxNode) -> IndentLevel { |
596 | match node.first_token() { | 566 | match node.first_token() { |
597 | Some(it) => Self::from_token(&it), | 567 | Some(it) => Self::from_token(&it), |
diff --git a/crates/syntax/src/ast/edit_in_place.rs b/crates/syntax/src/ast/edit_in_place.rs index b1eed0a2c..529bd0eb1 100644 --- a/crates/syntax/src/ast/edit_in_place.rs +++ b/crates/syntax/src/ast/edit_in_place.rs | |||
@@ -2,13 +2,13 @@ | |||
2 | 2 | ||
3 | use std::iter::empty; | 3 | use std::iter::empty; |
4 | 4 | ||
5 | use ast::{edit::AstNodeEdit, make, GenericParamsOwner, WhereClause}; | ||
6 | use parser::T; | 5 | use parser::T; |
7 | 6 | ||
8 | use crate::{ | 7 | use crate::{ |
9 | ast, | 8 | algo::neighbor, |
9 | ast::{self, edit::AstNodeEdit, make, GenericParamsOwner, WhereClause}, | ||
10 | ted::{self, Position}, | 10 | ted::{self, Position}, |
11 | AstNode, Direction, | 11 | AstNode, AstToken, Direction, |
12 | }; | 12 | }; |
13 | 13 | ||
14 | use super::NameOwner; | 14 | use super::NameOwner; |
@@ -126,3 +126,41 @@ impl ast::TypeBoundList { | |||
126 | } | 126 | } |
127 | } | 127 | } |
128 | } | 128 | } |
129 | |||
130 | impl ast::UseTree { | ||
131 | pub fn remove(&self) { | ||
132 | for &dir in [Direction::Next, Direction::Prev].iter() { | ||
133 | if let Some(next_use_tree) = neighbor(self, dir) { | ||
134 | let separators = self | ||
135 | .syntax() | ||
136 | .siblings_with_tokens(dir) | ||
137 | .skip(1) | ||
138 | .take_while(|it| it.as_node() != Some(next_use_tree.syntax())); | ||
139 | ted::remove_all_iter(separators); | ||
140 | break; | ||
141 | } | ||
142 | } | ||
143 | ted::remove(self.syntax()) | ||
144 | } | ||
145 | } | ||
146 | |||
147 | impl ast::Use { | ||
148 | pub fn remove(&self) { | ||
149 | let next_ws = self | ||
150 | .syntax() | ||
151 | .next_sibling_or_token() | ||
152 | .and_then(|it| it.into_token()) | ||
153 | .and_then(ast::Whitespace::cast); | ||
154 | if let Some(next_ws) = next_ws { | ||
155 | let ws_text = next_ws.syntax().text(); | ||
156 | if let Some(rest) = ws_text.strip_prefix('\n') { | ||
157 | if rest.is_empty() { | ||
158 | ted::remove(next_ws.syntax()) | ||
159 | } else { | ||
160 | ted::replace(next_ws.syntax(), make::tokens::whitespace(rest)) | ||
161 | } | ||
162 | } | ||
163 | } | ||
164 | ted::remove(self.syntax()) | ||
165 | } | ||
166 | } | ||
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs index 7049affd9..c08f2c14f 100644 --- a/crates/syntax/src/ast/make.rs +++ b/crates/syntax/src/ast/make.rs | |||
@@ -560,7 +560,7 @@ pub mod tokens { | |||
560 | pub fn whitespace(text: &str) -> SyntaxToken { | 560 | pub fn whitespace(text: &str) -> SyntaxToken { |
561 | assert!(text.trim().is_empty()); | 561 | assert!(text.trim().is_empty()); |
562 | let sf = SourceFile::parse(text).ok().unwrap(); | 562 | let sf = SourceFile::parse(text).ok().unwrap(); |
563 | sf.syntax().first_child_or_token().unwrap().into_token().unwrap() | 563 | sf.syntax().clone_for_update().first_child_or_token().unwrap().into_token().unwrap() |
564 | } | 564 | } |
565 | 565 | ||
566 | pub fn doc_comment(text: &str) -> SyntaxToken { | 566 | pub fn doc_comment(text: &str) -> SyntaxToken { |
diff --git a/crates/syntax/src/ted.rs b/crates/syntax/src/ted.rs index be2b846b1..177d4ff67 100644 --- a/crates/syntax/src/ted.rs +++ b/crates/syntax/src/ted.rs | |||
@@ -2,11 +2,14 @@ | |||
2 | //! | 2 | //! |
3 | //! The `_raw`-suffixed functions insert elements as is, unsuffixed versions fix | 3 | //! The `_raw`-suffixed functions insert elements as is, unsuffixed versions fix |
4 | //! up elements around the edges. | 4 | //! up elements around the edges. |
5 | use std::ops::RangeInclusive; | 5 | use std::{mem, ops::RangeInclusive}; |
6 | 6 | ||
7 | use parser::T; | 7 | use parser::T; |
8 | 8 | ||
9 | use crate::{ast::make, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken}; | 9 | use crate::{ |
10 | ast::{edit::IndentLevel, make}, | ||
11 | SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, | ||
12 | }; | ||
10 | 13 | ||
11 | /// Utility trait to allow calling `ted` functions with references or owned | 14 | /// Utility trait to allow calling `ted` functions with references or owned |
12 | /// nodes. Do not use outside of this module. | 15 | /// nodes. Do not use outside of this module. |
@@ -101,12 +104,25 @@ pub fn insert_all_raw(position: Position, elements: Vec<SyntaxElement>) { | |||
101 | } | 104 | } |
102 | 105 | ||
103 | pub fn remove(elem: impl Element) { | 106 | pub fn remove(elem: impl Element) { |
104 | let elem = elem.syntax_element(); | 107 | elem.syntax_element().detach() |
105 | remove_all(elem.clone()..=elem) | ||
106 | } | 108 | } |
107 | pub fn remove_all(range: RangeInclusive<SyntaxElement>) { | 109 | pub fn remove_all(range: RangeInclusive<SyntaxElement>) { |
108 | replace_all(range, Vec::new()) | 110 | replace_all(range, Vec::new()) |
109 | } | 111 | } |
112 | pub fn remove_all_iter(range: impl IntoIterator<Item = SyntaxElement>) { | ||
113 | let mut it = range.into_iter(); | ||
114 | if let Some(mut first) = it.next() { | ||
115 | match it.last() { | ||
116 | Some(mut last) => { | ||
117 | if first.index() > last.index() { | ||
118 | mem::swap(&mut first, &mut last) | ||
119 | } | ||
120 | remove_all(first..=last) | ||
121 | } | ||
122 | None => remove(first), | ||
123 | } | ||
124 | } | ||
125 | } | ||
110 | 126 | ||
111 | pub fn replace(old: impl Element, new: impl Element) { | 127 | pub fn replace(old: impl Element, new: impl Element) { |
112 | let old = old.syntax_element(); | 128 | let old = old.syntax_element(); |
@@ -149,5 +165,9 @@ fn ws_between(left: &SyntaxElement, right: &SyntaxElement) -> Option<SyntaxToken | |||
149 | if right.kind() == T![;] || right.kind() == T![,] { | 165 | if right.kind() == T![;] || right.kind() == T![,] { |
150 | return None; | 166 | return None; |
151 | } | 167 | } |
168 | if right.kind() == SyntaxKind::USE { | ||
169 | let indent = IndentLevel::from_element(left); | ||
170 | return Some(make::tokens::whitespace(&format!("\n{}", indent))); | ||
171 | } | ||
152 | Some(make::tokens::single_space()) | 172 | Some(make::tokens::single_space()) |
153 | } | 173 | } |