aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/hir/src/display.rs2
-rw-r--r--crates/hir/src/lib.rs146
-rw-r--r--crates/hir_def/src/find_path.rs56
-rw-r--r--crates/hir_def/src/nameres.rs17
-rw-r--r--crates/hir_def/src/nameres/path_resolution.rs2
-rw-r--r--crates/hir_def/src/resolver.rs18
-rw-r--r--crates/hir_ty/src/autoderef.rs51
-rw-r--r--crates/hir_ty/src/db.rs11
-rw-r--r--crates/hir_ty/src/display.rs46
-rw-r--r--crates/hir_ty/src/infer.rs2
-rw-r--r--crates/hir_ty/src/infer/coerce.rs6
-rw-r--r--crates/hir_ty/src/infer/expr.rs21
-rw-r--r--crates/hir_ty/src/infer/unify.rs66
-rw-r--r--crates/hir_ty/src/lib.rs90
-rw-r--r--crates/hir_ty/src/lower.rs78
-rw-r--r--crates/hir_ty/src/method_resolution.rs53
-rw-r--r--crates/hir_ty/src/tests/regression.rs13
-rw-r--r--crates/hir_ty/src/tests/traits.rs46
-rw-r--r--crates/hir_ty/src/traits.rs17
-rw-r--r--crates/hir_ty/src/traits/chalk.rs10
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs124
-rw-r--r--crates/hir_ty/src/utils.rs2
-rw-r--r--crates/ide/src/lib.rs10
-rw-r--r--crates/ide/src/move_item.rs620
-rw-r--r--crates/ide_assists/src/handlers/merge_imports.rs49
-rw-r--r--crates/ide_assists/src/handlers/unmerge_use.rs30
-rw-r--r--crates/ide_db/src/helpers/insert_use.rs8
-rw-r--r--crates/rust-analyzer/src/config.rs3
-rw-r--r--crates/rust-analyzer/src/handlers.rs19
-rw-r--r--crates/rust-analyzer/src/lsp_ext.rs22
-rw-r--r--crates/rust-analyzer/src/main_loop.rs1
-rw-r--r--crates/rust-analyzer/src/to_proto.rs18
-rw-r--r--crates/syntax/Cargo.toml2
-rw-r--r--crates/syntax/src/ast/edit.rs46
-rw-r--r--crates/syntax/src/ast/edit_in_place.rs44
-rw-r--r--crates/syntax/src/ast/make.rs2
-rw-r--r--crates/syntax/src/ted.rs28
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
218impl HirDisplay for Type { 218impl 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};
63use itertools::Itertools; 63use itertools::Itertools;
64use rustc_hash::FxHashSet; 64use 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)]
1644pub struct Type { 1638pub struct Type {
1645 krate: CrateId, 1639 krate: CrateId,
1646 ty: InEnvironment<Ty>, 1640 env: Arc<TraitEnvironment>,
1641 ty: Ty,
1647} 1642}
1648 1643
1649impl Type { 1644impl 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.
19pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> { 19pub 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
24pub fn find_path_prefixed( 25pub 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
34const MAX_PATH_LEN: usize = 15; 36const 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#"
901fn main() {
902 let _ = 22_i32.as_name$0();
903}
904
905pub 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
628impl HasResolver for ModuleId { 628impl 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
23const AUTODEREF_RECURSION_LIMIT: usize = 10; 23const 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;
12use crate::{ 12use 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};
18use hir_expand::name::Name; 18use 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
3use std::{borrow::Cow, fmt}; 3use std::fmt;
4 4
5use arrayvec::ArrayVec; 5use arrayvec::ArrayVec;
6use chalk_ir::Mutability; 6use 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
26pub struct HirFormatter<'a> { 26pub struct HirFormatter<'a> {
@@ -190,6 +190,7 @@ impl DisplayTarget {
190pub enum DisplaySourceCodeError { 190pub enum DisplaySourceCodeError {
191 PathNotFound, 191 PathNotFound,
192 UnknownType, 192 UnknownType,
193 Closure,
193} 194}
194 195
195pub enum HirDisplayError { 196pub 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
662pub fn write_bounds_like_dyn_trait_with_prefix( 676pub 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
676fn write_bounds_like_dyn_trait( 690fn 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};
13use hir_expand::name::{name, Name}; 13use hir_expand::name::{name, Name};
14use stdx::always;
14use syntax::ast::RangeOp; 15use syntax::ast::RangeOp;
15 16
16use crate::{ 17use 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
3use std::borrow::Cow; 3use std::borrow::Cow;
4 4
5use chalk_ir::{FloatTy, IntTy, TyVariableKind}; 5use chalk_ir::{FloatTy, IntTy, TyVariableKind, UniverseIndex, VariableKind};
6use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; 6use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
7 7
8use super::{DomainGoal, InferenceContext}; 8use super::{DomainGoal, InferenceContext};
9use crate::{ 9use 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
14impl<'a> InferenceContext<'a> { 14impl<'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> {
147pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { 160pub(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>;
61pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; 61pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
62pub type PlaceholderIndex = chalk_ir::PlaceholderIndex; 62pub type PlaceholderIndex = chalk_ir::PlaceholderIndex;
63 63
64pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>;
65
64pub type ChalkTraitId = chalk_ir::TraitId<Interner>; 66pub 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)]
138pub struct DynTy {
139 /// The unknown self type.
140 pub bounds: Binders<QuantifiedWhereClauses>,
141}
142
135pub type FnSig = chalk_ir::FnSig<Interner>; 143pub 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
506impl<T: Clone> Binders<&T> { 529impl<T: Clone> Binders<&T> {
@@ -614,6 +637,24 @@ impl TypeWalk for WhereClause {
614 } 637 }
615} 638}
616 639
640pub type QuantifiedWhereClause = Binders<WhereClause>;
641
642#[derive(Debug, Clone, PartialEq, Eq, Hash)]
643pub struct QuantifiedWhereClauses(Arc<[QuantifiedWhereClause]>);
644
645impl 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)]
624pub struct Canonical<T> { 665pub struct Canonical<T> {
625 pub value: T, 666 pub value: T,
626 pub kinds: Arc<[TyVariableKind]>, 667 pub binders: CanonicalVarKinds,
627} 668}
628 669
629impl<T> Canonical<T> { 670impl<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)]
1175pub(crate) struct ReturnTypeImplTrait { 1227pub(crate) struct ReturnTypeImplTrait {
1176 pub(crate) bounds: Binders<Vec<WhereClause>>, 1228 pub(crate) bounds: Binders<Vec<QuantifiedWhereClause>>,
1177} 1229}
1178 1230
1179pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId { 1231pub 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(
887pub(crate) fn generic_predicates_for_param_query( 907pub(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(
970pub(crate) fn generic_predicates_query( 990pub(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
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use base_db::CrateId; 8use base_db::CrateId;
9use chalk_ir::{cast::Cast, Mutability}; 9use chalk_ir::{cast::Cast, Mutability, UniverseIndex};
10use hir_def::{ 10use hir_def::{
11 lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule, 11 lang_item::LangItemTarget, 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
782fn autoderef_method_receiver( 801fn 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]
966fn 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]
3329fn infer_default_trait_type_parameter() {
3330 check_infer(
3331 r#"
3332struct A;
3333
3334trait Op<RHS=Self> {
3335 type Output;
3336
3337 fn do_op(self, rhs: RHS) -> Self::Output;
3338}
3339
3340impl Op for A {
3341 type Output = bool;
3342
3343 fn do_op(self, rhs: Self) -> Self::Output {
3344 true
3345 }
3346}
3347
3348fn 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.
2use std::env::var; 2use std::env::var;
3use std::sync::Arc;
4 3
5use base_db::CrateId; 4use base_db::CrateId;
6use chalk_ir::cast::Cast; 5use 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
50impl TraitEnvironment { 49impl 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)]
76pub struct InEnvironment<T> { 75pub 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
81impl<T> InEnvironment<T> { 80impl<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
726fn 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
7use chalk_solve::rust_ir; 7use chalk_solve::rust_ir;
8 8
9use base_db::salsa::InternKey; 9use base_db::salsa::InternKey;
10use hir_def::{AssocContainerId, GenericDefId, Lookup, TypeAliasId}; 10use hir_def::{GenericDefId, TypeAliasId};
11 11
12use crate::{ 12use 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
21use super::interner::*; 20use 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
307impl ToChalk for WhereClause { 310impl 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
469impl<T: ToChalk> ToChalk for crate::Binders<T>
470where
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
503pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> 492pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T>
504where 493where
505 T: HasInterner<Interner = Interner>, 494 T: HasInterner<Interner = Interner>,
@@ -529,14 +518,15 @@ pub(super) fn convert_where_clauses(
529 518
530pub(super) fn generic_predicate_to_inline_bound( 519pub(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;
37mod inlay_hints; 37mod inlay_hints;
38mod join_lines; 38mod join_lines;
39mod matching_brace; 39mod matching_brace;
40mod move_item;
40mod parent_module; 41mod parent_module;
41mod references; 42mod references;
42mod fn_references; 43mod 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 @@
1use std::iter::once;
2
3use hir::Semantics;
4use ide_db::{base_db::FileRange, RootDatabase};
5use itertools::Itertools;
6use syntax::{
7 algo, ast, match_ast, AstNode, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode, TextRange,
8};
9use text_edit::{TextEdit, TextEditBuilder};
10
11pub 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// |===
26pub(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
38fn 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
78fn 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
98fn 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
114fn 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)]
124mod 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#"
142fn 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#"
154fn 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#"
173fn 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#"
185fn 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#"
204fn 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#"
216fn 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#"
235fn main() {
236 let test = 123;
237 let test2$0$0 = 456;
238}
239 "#,
240 expect![[r#"
241fn 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#"
254fn main() {
255 println!("Hello, world");
256 println!("All I want to say is...");$0$0
257}
258 "#,
259 expect![[r#"
260fn 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#"
273fn main() {
274 println!("All I want to say is...");$0$0
275 println!("Hello, world");
276}
277 "#,
278 expect![[r#"
279fn 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#"
292fn main() {}
293
294fn foo() {}$0$0
295 "#,
296 expect![[r#"
297fn foo() {}
298
299fn main() {}
300 "#]],
301 Direction::Up,
302 );
303 }
304
305 #[test]
306 fn test_move_impl_up() {
307 check(
308 r#"
309struct Yay;
310
311trait Wow {}
312
313impl Wow for Yay $0$0{}
314 "#,
315 expect![[r#"
316struct Yay;
317
318impl Wow for Yay {}
319
320trait Wow {}
321 "#]],
322 Direction::Up,
323 );
324 }
325
326 #[test]
327 fn test_move_use_up() {
328 check(
329 r#"
330use std::vec::Vec;
331use std::collections::HashMap$0$0;
332 "#,
333 expect![[r#"
334use std::collections::HashMap;
335use std::vec::Vec;
336 "#]],
337 Direction::Up,
338 );
339 }
340
341 #[test]
342 fn test_moves_match_expr_up() {
343 check(
344 r#"
345fn main() {
346 let test = 123;
347
348 $0match test {
349 456 => {},
350 _ => {}
351 };$0
352}
353 "#,
354 expect![[r#"
355fn 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#"
372fn test(one: i32, two$0$0: u32) {}
373
374fn main() {
375 test(123, 456);
376}
377 "#,
378 expect![[r#"
379fn test(two: u32, one: i32) {}
380
381fn 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#"
393fn test(one: i32, two: u32) {}
394
395fn main() {
396 test(123, 456$0$0);
397}
398 "#,
399 expect![[r#"
400fn test(one: i32, two: u32) {}
401
402fn 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#"
414fn test(one: i32, two: u32) {}
415
416fn main() {
417 test(123$0$0, 456);
418}
419 "#,
420 expect![[r#"
421fn test(one: i32, two: u32) {}
422
423fn 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#"
435fn test(one: i32, two: u32) {}
436
437fn main() {
438 test(123$0$0, 456);
439}
440 "#,
441 expect![[r#"
442fn test(one: i32, two: u32) {}
443
444fn 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#"
456struct Test<A, B$0$0>(A, B);
457
458fn main() {}
459 "#,
460 expect![[r#"
461struct Test<B, A>(A, B);
462
463fn main() {}
464 "#]],
465 Direction::Up,
466 );
467 }
468
469 #[test]
470 fn test_moves_generic_arg_up() {
471 check(
472 r#"
473struct Test<A, B>(A, B);
474
475fn main() {
476 let t = Test::<i32, &str$0$0>(123, "yay");
477}
478 "#,
479 expect![[r#"
480struct Test<A, B>(A, B);
481
482fn 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#"
494enum Hello {
495 One,
496 Two$0$0
497}
498
499fn main() {}
500 "#,
501 expect![[r#"
502enum Hello {
503 Two,
504 One
505}
506
507fn main() {}
508 "#]],
509 Direction::Up,
510 );
511 }
512
513 #[test]
514 fn test_moves_type_bound_up() {
515 check(
516 r#"
517trait One {}
518
519trait Two {}
520
521fn test<T: One + Two$0$0>(t: T) {}
522
523fn main() {}
524 "#,
525 expect![[r#"
526trait One {}
527
528trait Two {}
529
530fn test<T: Two + One>(t: T) {}
531
532fn main() {}
533 "#]],
534 Direction::Up,
535 );
536 }
537
538 #[test]
539 fn test_prioritizes_trait_items() {
540 check(
541 r#"
542struct Test;
543
544trait Yay {
545 type One;
546
547 type Two;
548
549 fn inner();
550}
551
552impl 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#"
563struct Test;
564
565trait Yay {
566 type One;
567
568 type Two;
569
570 fn inner();
571}
572
573impl 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#"
591fn test() {
592 mod hello {
593 fn inner() {}
594 }
595
596 mod hi {$0$0
597 fn inner() {}
598 }
599}
600 "#,
601 expect![[r#"
602fn 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 @@
1use ide_db::helpers::insert_use::{try_merge_imports, try_merge_trees, MergeBehavior}; 1use ide_db::helpers::insert_use::{try_merge_imports, try_merge_trees, MergeBehavior};
2use syntax::{ 2use syntax::{algo::neighbor, ast, ted, AstNode};
3 algo::{neighbor, SyntaxRewriter},
4 ast, AstNode,
5};
6 3
7use crate::{ 4use crate::{
8 assist_context::{AssistContext, Assists}, 5 assist_context::{AssistContext, Assists},
@@ -24,33 +21,29 @@ use crate::{
24// ``` 21// ```
25pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 22pub(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 @@
1use syntax::{ 1use 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// ```
24pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 24pub(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
17pub use hir::PrefixKind;
18
17#[derive(Clone, Copy, Debug, PartialEq, Eq)] 19#[derive(Clone, Copy, Debug, PartialEq, Eq)]
18pub struct InsertUseConfig { 20pub 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
217pub fn try_merge_trees( 219pub 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 @@
10use std::{ffi::OsString, iter, path::PathBuf}; 10use std::{ffi::OsString, iter, path::PathBuf};
11 11
12use flycheck::FlycheckConfig; 12use flycheck::FlycheckConfig;
13use hir::PrefixKind;
14use ide::{AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig}; 13use ide::{AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig};
15use ide_db::helpers::{ 14use ide_db::helpers::{
16 insert_use::{InsertUseConfig, MergeBehavior}, 15 insert_use::{InsertUseConfig, MergeBehavior, PrefixKind},
17 SnippetCap, 16 SnippetCap,
18}; 17};
19use lsp_types::{ClientCapabilities, MarkupKind}; 18use 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
1430pub(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, &params.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
1430fn to_command_link(command: lsp_types::Command, tooltip: String) -> lsp_ext::CommandLink { 1449fn 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 {
402pub fn supports_utf8(caps: &lsp_types::ClientCapabilities) -> bool { 402pub 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
406pub enum MoveItem {}
407
408impl 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")]
416pub struct MoveItemParams {
417 pub direction: MoveItemDirection,
418 pub text_document: TextDocumentIdentifier,
419 pub range: Range,
420}
421
422#[derive(Serialize, Deserialize, Debug)]
423pub 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
661pub(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
661pub(crate) fn snippet_text_document_edit( 673pub(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 {
1073mod tests { 1085mod 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]
14cov-mark = { version = "1.1", features = ["thread-local"] } 14cov-mark = { version = "1.1", features = ["thread-local"] }
15itertools = "0.10.0" 15itertools = "0.10.0"
16rowan = "0.13.0-pre.2" 16rowan = "0.13.0-pre.3"
17rustc_lexer = { version = "710.0.0", package = "rustc-ap-rustc_lexer" } 17rustc_lexer = { version = "710.0.0", package = "rustc-ap-rustc_lexer" }
18rustc-hash = "1.1.0" 18rustc-hash = "1.1.0"
19arrayvec = "0.5.1" 19arrayvec = "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::{
9use arrayvec::ArrayVec; 9use arrayvec::ArrayVec;
10 10
11use crate::{ 11use 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
348impl ast::UseTree { 327impl 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
417impl ast::MatchArmList { 380impl ast::MatchArmList {
@@ -592,6 +555,13 @@ impl ops::Add<u8> for IndentLevel {
592} 555}
593 556
594impl IndentLevel { 557impl 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
3use std::iter::empty; 3use std::iter::empty;
4 4
5use ast::{edit::AstNodeEdit, make, GenericParamsOwner, WhereClause};
6use parser::T; 5use parser::T;
7 6
8use crate::{ 7use 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
14use super::NameOwner; 14use super::NameOwner;
@@ -126,3 +126,41 @@ impl ast::TypeBoundList {
126 } 126 }
127 } 127 }
128} 128}
129
130impl 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
147impl 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.
5use std::ops::RangeInclusive; 5use std::{mem, ops::RangeInclusive};
6 6
7use parser::T; 7use parser::T;
8 8
9use crate::{ast::make, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken}; 9use 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
103pub fn remove(elem: impl Element) { 106pub fn remove(elem: impl Element) {
104 let elem = elem.syntax_element(); 107 elem.syntax_element().detach()
105 remove_all(elem.clone()..=elem)
106} 108}
107pub fn remove_all(range: RangeInclusive<SyntaxElement>) { 109pub fn remove_all(range: RangeInclusive<SyntaxElement>) {
108 replace_all(range, Vec::new()) 110 replace_all(range, Vec::new())
109} 111}
112pub 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
111pub fn replace(old: impl Element, new: impl Element) { 127pub 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}