aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/cfg/src/cfg_expr.rs2
-rw-r--r--crates/hir/src/lib.rs91
-rw-r--r--crates/hir_def/src/attr.rs48
-rw-r--r--crates/hir_def/src/item_tree.rs12
-rw-r--r--crates/hir_def/src/lib.rs10
-rw-r--r--crates/hir_def/src/nameres/tests/diagnostics.rs3
-rw-r--r--crates/hir_def/src/test_db.rs9
-rw-r--r--crates/hir_expand/Cargo.toml1
-rw-r--r--crates/hir_expand/src/builtin_derive.rs66
-rw-r--r--crates/hir_expand/src/builtin_macro.rs78
-rw-r--r--crates/hir_expand/src/db.rs2
-rw-r--r--crates/hir_ty/src/autoderef.rs15
-rw-r--r--crates/hir_ty/src/db.rs23
-rw-r--r--crates/hir_ty/src/diagnostics/expr.rs21
-rw-r--r--crates/hir_ty/src/diagnostics/match_check.rs8
-rw-r--r--crates/hir_ty/src/diagnostics/unsafe_check.rs6
-rw-r--r--crates/hir_ty/src/display.rs195
-rw-r--r--crates/hir_ty/src/infer.rs70
-rw-r--r--crates/hir_ty/src/infer/coerce.rs38
-rw-r--r--crates/hir_ty/src/infer/expr.rs249
-rw-r--r--crates/hir_ty/src/infer/pat.rs41
-rw-r--r--crates/hir_ty/src/infer/path.rs18
-rw-r--r--crates/hir_ty/src/infer/unify.rs111
-rw-r--r--crates/hir_ty/src/lib.rs412
-rw-r--r--crates/hir_ty/src/lower.rs710
-rw-r--r--crates/hir_ty/src/method_resolution.rs88
-rw-r--r--crates/hir_ty/src/op.rs66
-rw-r--r--crates/hir_ty/src/tests.rs10
-rw-r--r--crates/hir_ty/src/traits.rs38
-rw-r--r--crates/hir_ty/src/traits/chalk.rs85
-rw-r--r--crates/hir_ty/src/traits/chalk/interner.rs2
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs273
-rw-r--r--crates/hir_ty/src/traits/chalk/tls.rs9
-rw-r--r--crates/ide/src/lib.rs11
-rw-r--r--crates/ide/src/references/rename.rs54
-rw-r--r--crates/ide/src/runnables.rs399
-rw-r--r--crates/ide_assists/src/handlers/add_turbo_fish.rs33
-rw-r--r--crates/ide_assists/src/handlers/apply_demorgan.rs87
-rw-r--r--crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs248
-rw-r--r--crates/ide_assists/src/lib.rs2
-rw-r--r--crates/ide_assists/src/tests/generated.rs30
-rw-r--r--crates/ide_completion/src/completions/attribute.rs35
-rw-r--r--crates/ide_completion/src/completions/fn_param.rs7
-rw-r--r--crates/ide_completion/src/completions/keyword.rs44
-rw-r--r--crates/ide_completion/src/completions/mod_.rs6
-rw-r--r--crates/ide_completion/src/completions/postfix.rs7
-rw-r--r--crates/ide_completion/src/completions/record.rs15
-rw-r--r--crates/ide_completion/src/completions/snippet.rs25
-rw-r--r--crates/ide_completion/src/completions/trait_impl.rs32
-rw-r--r--crates/ide_completion/src/item.rs188
-rw-r--r--crates/ide_completion/src/lib.rs5
-rw-r--r--crates/ide_completion/src/render.rs280
-rw-r--r--crates/ide_completion/src/render/builder_ext.rs6
-rw-r--r--crates/ide_completion/src/render/const_.rs10
-rw-r--r--crates/ide_completion/src/render/enum_variant.rs21
-rw-r--r--crates/ide_completion/src/render/function.rs13
-rw-r--r--crates/ide_completion/src/render/macro_.rs26
-rw-r--r--crates/ide_completion/src/render/pattern.rs18
-rw-r--r--crates/ide_completion/src/render/type_alias.rs10
-rw-r--r--crates/ide_db/src/search.rs4
-rw-r--r--crates/mbe/src/expander.rs4
-rw-r--r--crates/mbe/src/expander/matcher.rs266
-rw-r--r--crates/mbe/src/expander/transcriber.rs19
-rw-r--r--crates/parser/src/grammar.rs2
-rw-r--r--crates/rust-analyzer/build.rs5
-rw-r--r--crates/rust-analyzer/src/bin/flags.rs3
-rw-r--r--crates/rust-analyzer/src/bin/main.rs1
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs11
-rw-r--r--crates/rust-analyzer/src/handlers.rs30
-rw-r--r--crates/rust-analyzer/src/lsp_ext.rs13
-rw-r--r--crates/rust-analyzer/src/main_loop.rs1
-rw-r--r--crates/rust-analyzer/src/to_proto.rs42
-rw-r--r--crates/syntax/src/ast/make.rs3
-rw-r--r--crates/syntax/src/parsing/text_tree_sink.rs4
-rw-r--r--crates/tt/src/lib.rs47
75 files changed, 3138 insertions, 1739 deletions
diff --git a/crates/cfg/src/cfg_expr.rs b/crates/cfg/src/cfg_expr.rs
index 42327f1e1..069fc01d0 100644
--- a/crates/cfg/src/cfg_expr.rs
+++ b/crates/cfg/src/cfg_expr.rs
@@ -49,7 +49,7 @@ impl fmt::Display for CfgAtom {
49 } 49 }
50} 50}
51 51
52#[derive(Debug, Clone, PartialEq, Eq)] 52#[derive(Debug, Clone, PartialEq, Eq, Hash)]
53pub enum CfgExpr { 53pub enum CfgExpr {
54 Invalid, 54 Invalid,
55 Atom(CfgAtom), 55 Atom(CfgAtom),
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 58adc8fd3..eb1cd66fb 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -51,11 +51,11 @@ use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind};
51use hir_ty::{ 51use hir_ty::{
52 autoderef, 52 autoderef,
53 display::{write_bounds_like_dyn_trait_with_prefix, HirDisplayError, HirFormatter}, 53 display::{write_bounds_like_dyn_trait_with_prefix, HirDisplayError, HirFormatter},
54 method_resolution, 54 method_resolution, to_assoc_type_id,
55 traits::{FnTrait, Solution, SolutionVariables}, 55 traits::{FnTrait, Solution, SolutionVariables},
56 AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate, 56 AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate,
57 InEnvironment, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, TraitEnvironment, 57 InEnvironment, Interner, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, Ty,
58 Ty, TyDefId, TyVariableKind, 58 TyDefId, TyKind, TyVariableKind,
59}; 59};
60use rustc_hash::FxHashSet; 60use rustc_hash::FxHashSet;
61use stdx::{format_to, impl_from}; 61use stdx::{format_to, impl_from};
@@ -677,7 +677,7 @@ impl_from!(Struct, Union, Enum for Adt);
677impl Adt { 677impl Adt {
678 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { 678 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
679 let subst = db.generic_defaults(self.into()); 679 let subst = db.generic_defaults(self.into());
680 subst.iter().any(|ty| &ty.value == &Ty::Unknown) 680 subst.iter().any(|ty| ty.value.is_unknown())
681 } 681 }
682 682
683 /// Turns this ADT into a type. Any type parameters of the ADT will be 683 /// Turns this ADT into a type. Any type parameters of the ADT will be
@@ -802,7 +802,7 @@ impl Function {
802 let krate = self.id.lookup(db.upcast()).container.module(db.upcast()).krate(); 802 let krate = self.id.lookup(db.upcast()).container.module(db.upcast()).krate();
803 let ret_type = &db.function_data(self.id).ret_type; 803 let ret_type = &db.function_data(self.id).ret_type;
804 let ctx = hir_ty::TyLoweringContext::new(db, &resolver); 804 let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
805 let ty = Ty::from_hir_ext(&ctx, ret_type).0; 805 let ty = ctx.lower_ty(ret_type);
806 Type::new_with_resolver_inner(db, krate, &resolver, ty) 806 Type::new_with_resolver_inner(db, krate, &resolver, ty)
807 } 807 }
808 808
@@ -817,7 +817,7 @@ impl Function {
817 let resolver = self.id.resolver(db.upcast()); 817 let resolver = self.id.resolver(db.upcast());
818 let krate = self.id.lookup(db.upcast()).container.module(db.upcast()).krate(); 818 let krate = self.id.lookup(db.upcast()).container.module(db.upcast()).krate();
819 let ctx = hir_ty::TyLoweringContext::new(db, &resolver); 819 let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
820 let environment = TraitEnvironment::lower(db, &resolver); 820 let environment = db.trait_environment(self.id.into());
821 db.function_data(self.id) 821 db.function_data(self.id)
822 .params 822 .params
823 .iter() 823 .iter()
@@ -825,7 +825,7 @@ impl Function {
825 let ty = Type { 825 let ty = Type {
826 krate, 826 krate,
827 ty: InEnvironment { 827 ty: InEnvironment {
828 value: Ty::from_hir_ext(&ctx, type_ref).0, 828 value: ctx.lower_ty(type_ref),
829 environment: environment.clone(), 829 environment: environment.clone(),
830 }, 830 },
831 }; 831 };
@@ -1012,7 +1012,7 @@ pub struct TypeAlias {
1012impl TypeAlias { 1012impl TypeAlias {
1013 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { 1013 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
1014 let subst = db.generic_defaults(self.id.into()); 1014 let subst = db.generic_defaults(self.id.into());
1015 subst.iter().any(|ty| &ty.value == &Ty::Unknown) 1015 subst.iter().any(|ty| ty.value.is_unknown())
1016 } 1016 }
1017 1017
1018 pub fn module(self, db: &dyn HirDatabase) -> Module { 1018 pub fn module(self, db: &dyn HirDatabase) -> Module {
@@ -1384,7 +1384,7 @@ impl TypeParam {
1384 pub fn ty(self, db: &dyn HirDatabase) -> Type { 1384 pub fn ty(self, db: &dyn HirDatabase) -> Type {
1385 let resolver = self.id.parent.resolver(db.upcast()); 1385 let resolver = self.id.parent.resolver(db.upcast());
1386 let krate = self.id.parent.module(db.upcast()).krate(); 1386 let krate = self.id.parent.module(db.upcast()).krate();
1387 let ty = Ty::Placeholder(self.id); 1387 let ty = TyKind::Placeholder(hir_ty::to_placeholder_idx(db, self.id)).intern(&Interner);
1388 Type::new_with_resolver_inner(db, krate, &resolver, ty) 1388 Type::new_with_resolver_inner(db, krate, &resolver, ty)
1389 } 1389 }
1390 1390
@@ -1499,7 +1499,7 @@ impl Impl {
1499 let resolver = self.id.resolver(db.upcast()); 1499 let resolver = self.id.resolver(db.upcast());
1500 let krate = self.id.lookup(db.upcast()).container.krate(); 1500 let krate = self.id.lookup(db.upcast()).container.krate();
1501 let ctx = hir_ty::TyLoweringContext::new(db, &resolver); 1501 let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
1502 let ty = Ty::from_hir(&ctx, &impl_data.target_type); 1502 let ty = ctx.lower_ty(&impl_data.target_type);
1503 Type::new_with_resolver_inner(db, krate, &resolver, ty) 1503 Type::new_with_resolver_inner(db, krate, &resolver, ty)
1504 } 1504 }
1505 1505
@@ -1563,13 +1563,15 @@ impl Type {
1563 resolver: &Resolver, 1563 resolver: &Resolver,
1564 ty: Ty, 1564 ty: Ty,
1565 ) -> Type { 1565 ) -> Type {
1566 let environment = TraitEnvironment::lower(db, &resolver); 1566 let environment =
1567 resolver.generic_def().map_or_else(Default::default, |d| db.trait_environment(d));
1567 Type { krate, ty: InEnvironment { value: ty, environment } } 1568 Type { krate, ty: InEnvironment { value: ty, environment } }
1568 } 1569 }
1569 1570
1570 fn new(db: &dyn HirDatabase, krate: CrateId, lexical_env: impl HasResolver, ty: Ty) -> Type { 1571 fn new(db: &dyn HirDatabase, krate: CrateId, lexical_env: impl HasResolver, ty: Ty) -> Type {
1571 let resolver = lexical_env.resolver(db.upcast()); 1572 let resolver = lexical_env.resolver(db.upcast());
1572 let environment = TraitEnvironment::lower(db, &resolver); 1573 let environment =
1574 resolver.generic_def().map_or_else(Default::default, |d| db.trait_environment(d));
1573 Type { krate, ty: InEnvironment { value: ty, environment } } 1575 Type { krate, ty: InEnvironment { value: ty, environment } }
1574 } 1576 }
1575 1577
@@ -1584,25 +1586,25 @@ impl Type {
1584 } 1586 }
1585 1587
1586 pub fn is_unit(&self) -> bool { 1588 pub fn is_unit(&self) -> bool {
1587 matches!(self.ty.value, Ty::Tuple(0, ..)) 1589 matches!(self.ty.value.interned(&Interner), TyKind::Tuple(0, ..))
1588 } 1590 }
1589 pub fn is_bool(&self) -> bool { 1591 pub fn is_bool(&self) -> bool {
1590 matches!(self.ty.value, Ty::Scalar(Scalar::Bool)) 1592 matches!(self.ty.value.interned(&Interner), TyKind::Scalar(Scalar::Bool))
1591 } 1593 }
1592 1594
1593 pub fn is_mutable_reference(&self) -> bool { 1595 pub fn is_mutable_reference(&self) -> bool {
1594 matches!(self.ty.value, Ty::Ref(hir_ty::Mutability::Mut, ..)) 1596 matches!(self.ty.value.interned(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..))
1595 } 1597 }
1596 1598
1597 pub fn remove_ref(&self) -> Option<Type> { 1599 pub fn remove_ref(&self) -> Option<Type> {
1598 match &self.ty.value { 1600 match &self.ty.value.interned(&Interner) {
1599 Ty::Ref(.., substs) => Some(self.derived(substs[0].clone())), 1601 TyKind::Ref(.., substs) => Some(self.derived(substs[0].clone())),
1600 _ => None, 1602 _ => None,
1601 } 1603 }
1602 } 1604 }
1603 1605
1604 pub fn is_unknown(&self) -> bool { 1606 pub fn is_unknown(&self) -> bool {
1605 matches!(self.ty.value, Ty::Unknown) 1607 self.ty.value.is_unknown()
1606 } 1608 }
1607 1609
1608 /// Checks that particular type `ty` implements `std::future::Future`. 1610 /// Checks that particular type `ty` implements `std::future::Future`.
@@ -1683,8 +1685,11 @@ impl Type {
1683 .fill(args.iter().map(|t| t.ty.value.clone())) 1685 .fill(args.iter().map(|t| t.ty.value.clone()))
1684 .build(); 1686 .build();
1685 let predicate = ProjectionPredicate { 1687 let predicate = ProjectionPredicate {
1686 projection_ty: ProjectionTy { associated_ty: alias.id, parameters: subst }, 1688 projection_ty: ProjectionTy {
1687 ty: Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)), 1689 associated_ty_id: to_assoc_type_id(alias.id),
1690 substitution: subst,
1691 },
1692 ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner),
1688 }; 1693 };
1689 let goal = Canonical { 1694 let goal = Canonical {
1690 value: InEnvironment::new( 1695 value: InEnvironment::new(
@@ -1712,26 +1717,23 @@ impl Type {
1712 } 1717 }
1713 1718
1714 pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> { 1719 pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
1715 let def = match self.ty.value { 1720 let def = self.ty.value.callable_def(db);
1716 Ty::FnDef(def, _) => Some(def),
1717 _ => None,
1718 };
1719 1721
1720 let sig = self.ty.value.callable_sig(db)?; 1722 let sig = self.ty.value.callable_sig(db)?;
1721 Some(Callable { ty: self.clone(), sig, def, is_bound_method: false }) 1723 Some(Callable { ty: self.clone(), sig, def, is_bound_method: false })
1722 } 1724 }
1723 1725
1724 pub fn is_closure(&self) -> bool { 1726 pub fn is_closure(&self) -> bool {
1725 matches!(&self.ty.value, Ty::Closure { .. }) 1727 matches!(&self.ty.value.interned(&Interner), TyKind::Closure { .. })
1726 } 1728 }
1727 1729
1728 pub fn is_fn(&self) -> bool { 1730 pub fn is_fn(&self) -> bool {
1729 matches!(&self.ty.value, Ty::FnDef(..) | Ty::Function { .. }) 1731 matches!(&self.ty.value.interned(&Interner), TyKind::FnDef(..) | TyKind::Function { .. })
1730 } 1732 }
1731 1733
1732 pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { 1734 pub fn is_packed(&self, db: &dyn HirDatabase) -> bool {
1733 let adt_id = match self.ty.value { 1735 let adt_id = match self.ty.value.interned(&Interner) {
1734 Ty::Adt(hir_ty::AdtId(adt_id), ..) => adt_id, 1736 &TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id,
1735 _ => return false, 1737 _ => return false,
1736 }; 1738 };
1737 1739
@@ -1743,24 +1745,25 @@ impl Type {
1743 } 1745 }
1744 1746
1745 pub fn is_raw_ptr(&self) -> bool { 1747 pub fn is_raw_ptr(&self) -> bool {
1746 matches!(&self.ty.value, Ty::Raw(..)) 1748 matches!(&self.ty.value.interned(&Interner), TyKind::Raw(..))
1747 } 1749 }
1748 1750
1749 pub fn contains_unknown(&self) -> bool { 1751 pub fn contains_unknown(&self) -> bool {
1750 return go(&self.ty.value); 1752 return go(&self.ty.value);
1751 1753
1752 fn go(ty: &Ty) -> bool { 1754 fn go(ty: &Ty) -> bool {
1753 match ty { 1755 if ty.is_unknown() {
1754 Ty::Unknown => true, 1756 true
1755 _ => ty.substs().map_or(false, |substs| substs.iter().any(go)), 1757 } else {
1758 ty.substs().map_or(false, |substs| substs.iter().any(go))
1756 } 1759 }
1757 } 1760 }
1758 } 1761 }
1759 1762
1760 pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> { 1763 pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> {
1761 let (variant_id, substs) = match self.ty.value { 1764 let (variant_id, substs) = match self.ty.value.interned(&Interner) {
1762 Ty::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs), 1765 &TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs),
1763 Ty::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs), 1766 &TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs),
1764 _ => return Vec::new(), 1767 _ => return Vec::new(),
1765 }; 1768 };
1766 1769
@@ -1775,7 +1778,7 @@ impl Type {
1775 } 1778 }
1776 1779
1777 pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> { 1780 pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> {
1778 if let Ty::Tuple(_, substs) = &self.ty.value { 1781 if let TyKind::Tuple(_, substs) = &self.ty.value.interned(&Interner) {
1779 substs.iter().map(|ty| self.derived(ty.clone())).collect() 1782 substs.iter().map(|ty| self.derived(ty.clone())).collect()
1780 } else { 1783 } else {
1781 Vec::new() 1784 Vec::new()
@@ -1957,33 +1960,33 @@ impl Type {
1957 1960
1958 fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) { 1961 fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
1959 let ty = type_.ty.value.strip_references(); 1962 let ty = type_.ty.value.strip_references();
1960 match ty { 1963 match ty.interned(&Interner) {
1961 Ty::Adt(..) => { 1964 TyKind::Adt(..) => {
1962 cb(type_.derived(ty.clone())); 1965 cb(type_.derived(ty.clone()));
1963 } 1966 }
1964 Ty::AssociatedType(..) => { 1967 TyKind::AssociatedType(..) => {
1965 if let Some(_) = ty.associated_type_parent_trait(db) { 1968 if let Some(_) = ty.associated_type_parent_trait(db) {
1966 cb(type_.derived(ty.clone())); 1969 cb(type_.derived(ty.clone()));
1967 } 1970 }
1968 } 1971 }
1969 Ty::OpaqueType(..) => { 1972 TyKind::OpaqueType(..) => {
1970 if let Some(bounds) = ty.impl_trait_bounds(db) { 1973 if let Some(bounds) = ty.impl_trait_bounds(db) {
1971 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); 1974 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
1972 } 1975 }
1973 } 1976 }
1974 Ty::Alias(AliasTy::Opaque(opaque_ty)) => { 1977 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
1975 if let Some(bounds) = ty.impl_trait_bounds(db) { 1978 if let Some(bounds) = ty.impl_trait_bounds(db) {
1976 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); 1979 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
1977 } 1980 }
1978 1981
1979 walk_substs(db, type_, &opaque_ty.parameters, cb); 1982 walk_substs(db, type_, &opaque_ty.substitution, cb);
1980 } 1983 }
1981 Ty::Placeholder(_) => { 1984 TyKind::Placeholder(_) => {
1982 if let Some(bounds) = ty.impl_trait_bounds(db) { 1985 if let Some(bounds) = ty.impl_trait_bounds(db) {
1983 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); 1986 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
1984 } 1987 }
1985 } 1988 }
1986 Ty::Dyn(bounds) => { 1989 TyKind::Dyn(bounds) => {
1987 walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb); 1990 walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb);
1988 } 1991 }
1989 1992
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index 97cdbbb9e..7b41b148c 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -9,6 +9,7 @@ use hir_expand::{hygiene::Hygiene, name::AsName, AstId, InFile};
9use itertools::Itertools; 9use itertools::Itertools;
10use la_arena::ArenaMap; 10use la_arena::ArenaMap;
11use mbe::ast_to_token_tree; 11use mbe::ast_to_token_tree;
12use smallvec::{smallvec, SmallVec};
12use syntax::{ 13use syntax::{
13 ast::{self, AstNode, AttrsOwner}, 14 ast::{self, AstNode, AttrsOwner},
14 match_ast, AstToken, SmolStr, SyntaxNode, 15 match_ast, AstToken, SmolStr, SyntaxNode,
@@ -134,53 +135,42 @@ impl RawAttrs {
134 let crate_graph = db.crate_graph(); 135 let crate_graph = db.crate_graph();
135 let new_attrs = self 136 let new_attrs = self
136 .iter() 137 .iter()
137 .filter_map(|attr| { 138 .flat_map(|attr| -> SmallVec<[_; 1]> {
138 let attr = attr.clone(); 139 let attr = attr.clone();
139 let is_cfg_attr = 140 let is_cfg_attr =
140 attr.path.as_ident().map_or(false, |name| *name == hir_expand::name![cfg_attr]); 141 attr.path.as_ident().map_or(false, |name| *name == hir_expand::name![cfg_attr]);
141 if !is_cfg_attr { 142 if !is_cfg_attr {
142 return Some(attr); 143 return smallvec![attr];
143 } 144 }
144 145
145 let subtree = match &attr.input { 146 let subtree = match &attr.input {
146 Some(AttrInput::TokenTree(it)) => it, 147 Some(AttrInput::TokenTree(it)) => it,
147 _ => return Some(attr), 148 _ => return smallvec![attr],
148 }; 149 };
149 150
150 // Input subtree is: `(cfg, attr)` 151 // Input subtree is: `(cfg, $(attr),+)`
151 // Split it up into a `cfg` and an `attr` subtree. 152 // Split it up into a `cfg` subtree and the `attr` subtrees.
152 // FIXME: There should be a common API for this. 153 // FIXME: There should be a common API for this.
153 let mut saw_comma = false; 154 let mut parts = subtree.token_trees.split(
154 let (mut cfg, attr): (Vec<_>, Vec<_>) = 155 |tt| matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ','),
155 subtree.clone().token_trees.into_iter().partition(|tree| { 156 );
156 if saw_comma { 157 let cfg = parts.next().unwrap();
157 return false; 158 let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() };
158 }
159
160 match tree {
161 tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => {
162 saw_comma = true;
163 }
164 _ => {}
165 }
166
167 true
168 });
169 cfg.pop(); // `,` ends up in here
170
171 let attr = Subtree { delimiter: None, token_trees: attr };
172 let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg };
173 let cfg = CfgExpr::parse(&cfg); 159 let cfg = CfgExpr::parse(&cfg);
160 let attrs = parts.filter(|a| !a.is_empty()).filter_map(|attr| {
161 let tree = Subtree { delimiter: None, token_trees: attr.to_vec() };
162 let attr = ast::Attr::parse(&format!("#[{}]", tree)).ok()?;
163 let hygiene = Hygiene::new_unhygienic(); // FIXME
164 Attr::from_src(attr, &hygiene)
165 });
174 166
175 let cfg_options = &crate_graph[krate].cfg_options; 167 let cfg_options = &crate_graph[krate].cfg_options;
176 if cfg_options.check(&cfg) == Some(false) { 168 if cfg_options.check(&cfg) == Some(false) {
177 None 169 smallvec![]
178 } else { 170 } else {
179 cov_mark::hit!(cfg_attr_active); 171 cov_mark::hit!(cfg_attr_active);
180 172
181 let attr = ast::Attr::parse(&format!("#[{}]", attr)).ok()?; 173 attrs.collect()
182 let hygiene = Hygiene::new_unhygienic(); // FIXME
183 Attr::from_src(attr, &hygiene)
184 } 174 }
185 }) 175 })
186 .collect(); 176 .collect();
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index 6bb334573..09bcb10dc 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -209,18 +209,6 @@ impl ItemTree {
209 } 209 }
210 } 210 }
211 211
212 pub fn source<S: ItemTreeNode>(&self, db: &dyn DefDatabase, of: ItemTreeId<S>) -> S::Source {
213 // This unwrap cannot fail, since it has either succeeded above, or resulted in an empty
214 // ItemTree (in which case there is no valid `FileItemTreeId` to call this method with).
215 let root =
216 db.parse_or_expand(of.file_id).expect("parse_or_expand failed on constructed ItemTree");
217
218 let id = self[of.value].ast_id();
219 let map = db.ast_id_map(of.file_id);
220 let ptr = map.get(id);
221 ptr.to_node(&root)
222 }
223
224 fn data(&self) -> &ItemTreeData { 212 fn data(&self) -> &ItemTreeData {
225 self.data.as_ref().expect("attempted to access data of empty ItemTree") 213 self.data.as_ref().expect("attempted to access data of empty ItemTree")
226 } 214 }
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs
index 6d11c5be4..c6655c5fb 100644
--- a/crates/hir_def/src/lib.rs
+++ b/crates/hir_def/src/lib.rs
@@ -341,6 +341,16 @@ pub enum DefWithBodyId {
341 341
342impl_from!(FunctionId, ConstId, StaticId for DefWithBodyId); 342impl_from!(FunctionId, ConstId, StaticId for DefWithBodyId);
343 343
344impl DefWithBodyId {
345 pub fn as_generic_def_id(self) -> Option<GenericDefId> {
346 match self {
347 DefWithBodyId::FunctionId(f) => Some(f.into()),
348 DefWithBodyId::StaticId(_) => None,
349 DefWithBodyId::ConstId(c) => Some(c.into()),
350 }
351 }
352}
353
344#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 354#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
345pub enum AssocItemId { 355pub enum AssocItemId {
346 FunctionId(FunctionId), 356 FunctionId(FunctionId),
diff --git a/crates/hir_def/src/nameres/tests/diagnostics.rs b/crates/hir_def/src/nameres/tests/diagnostics.rs
index d5ef8ceb5..1b8e885b0 100644
--- a/crates/hir_def/src/nameres/tests/diagnostics.rs
+++ b/crates/hir_def/src/nameres/tests/diagnostics.rs
@@ -149,6 +149,9 @@ fn inactive_via_cfg_attr() {
149 #[cfg_attr(not(never), cfg(not(no)))] fn f() {} 149 #[cfg_attr(not(never), cfg(not(no)))] fn f() {}
150 150
151 #[cfg_attr(never, cfg(no))] fn g() {} 151 #[cfg_attr(never, cfg(no))] fn g() {}
152
153 #[cfg_attr(not(never), inline, cfg(no))] fn h() {}
154 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: no is disabled
152 "#, 155 "#,
153 ); 156 );
154} 157}
diff --git a/crates/hir_def/src/test_db.rs b/crates/hir_def/src/test_db.rs
index eda982c85..10977761c 100644
--- a/crates/hir_def/src/test_db.rs
+++ b/crates/hir_def/src/test_db.rs
@@ -15,7 +15,7 @@ use rustc_hash::FxHashSet;
15use syntax::{algo, ast, AstNode, TextRange, TextSize}; 15use syntax::{algo, ast, AstNode, TextRange, TextSize};
16use test_utils::extract_annotations; 16use test_utils::extract_annotations;
17 17
18use crate::{db::DefDatabase, nameres::DefMap, Lookup, ModuleDefId, ModuleId}; 18use crate::{db::DefDatabase, nameres::DefMap, src::HasSource, Lookup, ModuleDefId, ModuleId};
19 19
20#[salsa::database( 20#[salsa::database(
21 base_db::SourceDatabaseExtStorage, 21 base_db::SourceDatabaseExtStorage,
@@ -115,14 +115,9 @@ impl TestDB {
115 if file_id != position.file_id.into() { 115 if file_id != position.file_id.into() {
116 continue; 116 continue;
117 } 117 }
118 let root = self.parse_or_expand(file_id).unwrap();
119 let ast_map = self.ast_id_map(file_id);
120 let item_tree = self.item_tree(file_id);
121 for decl in module.scope.declarations() { 118 for decl in module.scope.declarations() {
122 if let ModuleDefId::FunctionId(it) = decl { 119 if let ModuleDefId::FunctionId(it) = decl {
123 let ast = 120 let range = it.lookup(self).source(self).value.syntax().text_range();
124 ast_map.get(item_tree[it.lookup(self).id.value].ast_id).to_node(&root);
125 let range = ast.syntax().text_range();
126 121
127 if !range.contains(position.offset) { 122 if !range.contains(position.offset) {
128 continue; 123 continue;
diff --git a/crates/hir_expand/Cargo.toml b/crates/hir_expand/Cargo.toml
index 7bb40ba9b..f649ab925 100644
--- a/crates/hir_expand/Cargo.toml
+++ b/crates/hir_expand/Cargo.toml
@@ -25,3 +25,4 @@ mbe = { path = "../mbe", version = "0.0.0" }
25 25
26[dev-dependencies] 26[dev-dependencies]
27test_utils = { path = "../test_utils" } 27test_utils = { path = "../test_utils" }
28expect-test = "1.1"
diff --git a/crates/hir_expand/src/builtin_derive.rs b/crates/hir_expand/src/builtin_derive.rs
index b7f1aae8f..dfdb9cf59 100644
--- a/crates/hir_expand/src/builtin_derive.rs
+++ b/crates/hir_expand/src/builtin_derive.rs
@@ -267,13 +267,14 @@ fn partial_ord_expand(
267#[cfg(test)] 267#[cfg(test)]
268mod tests { 268mod tests {
269 use base_db::{fixture::WithFixture, CrateId, SourceDatabase}; 269 use base_db::{fixture::WithFixture, CrateId, SourceDatabase};
270 use expect_test::{expect, Expect};
270 use name::{known, Name}; 271 use name::{known, Name};
271 272
272 use crate::{test_db::TestDB, AstId, MacroCallId, MacroCallKind, MacroCallLoc}; 273 use crate::{test_db::TestDB, AstId, MacroCallId, MacroCallKind, MacroCallLoc};
273 274
274 use super::*; 275 use super::*;
275 276
276 fn expand_builtin_derive(s: &str, name: Name) -> String { 277 fn expand_builtin_derive(ra_fixture: &str, name: Name) -> String {
277 let expander = BuiltinDeriveExpander::find_by_name(&name).unwrap(); 278 let expander = BuiltinDeriveExpander::find_by_name(&name).unwrap();
278 let fixture = format!( 279 let fixture = format!(
279 r#"//- /main.rs crate:main deps:core 280 r#"//- /main.rs crate:main deps:core
@@ -282,7 +283,7 @@ $0
282//- /lib.rs crate:core 283//- /lib.rs crate:core
283// empty 284// empty
284"#, 285"#,
285 s 286 ra_fixture
286 ); 287 );
287 288
288 let (db, file_pos) = TestDB::with_position(&fixture); 289 let (db, file_pos) = TestDB::with_position(&fixture);
@@ -314,66 +315,57 @@ $0
314 parsed.text().to_string() 315 parsed.text().to_string()
315 } 316 }
316 317
318 fn check_derive(ra_fixture: &str, name: Name, expected: Expect) {
319 let expanded = expand_builtin_derive(ra_fixture, name);
320 expected.assert_eq(&expanded);
321 }
322
317 #[test] 323 #[test]
318 fn test_copy_expand_simple() { 324 fn test_copy_expand_simple() {
319 let expanded = expand_builtin_derive( 325 check_derive(
320 r#" 326 r#"
321 #[derive(Copy)] 327 #[derive(Copy)]
322 struct Foo; 328 struct Foo;
323"#, 329 "#,
324 known::Copy, 330 known::Copy,
331 expect![["impl< >core::marker::CopyforFoo< >{}"]],
325 ); 332 );
326
327 assert_eq!(expanded, "impl< >core::marker::CopyforFoo< >{}");
328 } 333 }
329 334
330 #[test] 335 #[test]
331 fn test_copy_expand_with_type_params() { 336 fn test_copy_expand_with_type_params() {
332 let expanded = expand_builtin_derive( 337 check_derive(
333 r#" 338 r#"
334 #[derive(Copy)] 339 #[derive(Copy)]
335 struct Foo<A, B>; 340 struct Foo<A, B>;
336"#, 341 "#,
337 known::Copy, 342 known::Copy,
338 ); 343 expect![["impl<T0:core::marker::Copy,T1:core::marker::Copy>core::marker::CopyforFoo<T0,T1>{}"]],
339
340 assert_eq!(
341 expanded,
342 "impl<T0:core::marker::Copy,T1:core::marker::Copy>core::marker::CopyforFoo<T0,T1>{}"
343 ); 344 );
344 } 345 }
345 346
346 #[test] 347 #[test]
347 fn test_copy_expand_with_lifetimes() { 348 fn test_copy_expand_with_lifetimes() {
348 let expanded = expand_builtin_derive( 349 check_derive(
349 r#" 350 r#"
350 #[derive(Copy)] 351 #[derive(Copy)]
351 struct Foo<A, B, 'a, 'b>; 352 struct Foo<A, B, 'a, 'b>;
352"#, 353 "#,
353 known::Copy, 354 known::Copy,
354 ); 355 // We currently just ignore lifetimes
355 356 expect![["impl<T0:core::marker::Copy,T1:core::marker::Copy>core::marker::CopyforFoo<T0,T1>{}"]],
356 // We currently just ignore lifetimes
357
358 assert_eq!(
359 expanded,
360 "impl<T0:core::marker::Copy,T1:core::marker::Copy>core::marker::CopyforFoo<T0,T1>{}"
361 ); 357 );
362 } 358 }
363 359
364 #[test] 360 #[test]
365 fn test_clone_expand() { 361 fn test_clone_expand() {
366 let expanded = expand_builtin_derive( 362 check_derive(
367 r#" 363 r#"
368 #[derive(Clone)] 364 #[derive(Clone)]
369 struct Foo<A, B>; 365 struct Foo<A, B>;
370"#, 366 "#,
371 known::Clone, 367 known::Clone,
372 ); 368 expect![["impl<T0:core::clone::Clone,T1:core::clone::Clone>core::clone::CloneforFoo<T0,T1>{}"]],
373
374 assert_eq!(
375 expanded,
376 "impl<T0:core::clone::Clone,T1:core::clone::Clone>core::clone::CloneforFoo<T0,T1>{}"
377 ); 369 );
378 } 370 }
379} 371}
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs
index b34f1a4f2..2a79c892b 100644
--- a/crates/hir_expand/src/builtin_macro.rs
+++ b/crates/hir_expand/src/builtin_macro.rs
@@ -491,6 +491,7 @@ mod tests {
491 MacroCallLoc, 491 MacroCallLoc,
492 }; 492 };
493 use base_db::{fixture::WithFixture, SourceDatabase}; 493 use base_db::{fixture::WithFixture, SourceDatabase};
494 use expect_test::{expect, Expect};
494 use std::sync::Arc; 495 use std::sync::Arc;
495 use syntax::ast::NameOwner; 496 use syntax::ast::NameOwner;
496 497
@@ -574,87 +575,86 @@ mod tests {
574 db.parse_or_expand(file_id).unwrap().to_string() 575 db.parse_or_expand(file_id).unwrap().to_string()
575 } 576 }
576 577
578 fn check_expansion(ra_fixture: &str, expect: Expect) {
579 let expansion = expand_builtin_macro(ra_fixture);
580 expect.assert_eq(&expansion);
581 }
582
577 #[test] 583 #[test]
578 fn test_column_expand() { 584 fn test_column_expand() {
579 let expanded = expand_builtin_macro( 585 check_expansion(
580 r#" 586 r#"
581 #[rustc_builtin_macro] 587 #[rustc_builtin_macro]
582 macro_rules! column {() => {}} 588 macro_rules! column {() => {}}
583 column!() 589 column!()
584 "#, 590 "#,
591 expect![["0"]],
585 ); 592 );
586
587 assert_eq!(expanded, "0");
588 } 593 }
589 594
590 #[test] 595 #[test]
591 fn test_line_expand() { 596 fn test_line_expand() {
592 let expanded = expand_builtin_macro( 597 check_expansion(
593 r#" 598 r#"
594 #[rustc_builtin_macro] 599 #[rustc_builtin_macro]
595 macro_rules! line {() => {}} 600 macro_rules! line {() => {}}
596 line!() 601 line!()
597 "#, 602 "#,
603 expect![["0"]],
598 ); 604 );
599
600 assert_eq!(expanded, "0");
601 } 605 }
602 606
603 #[test] 607 #[test]
604 fn test_stringify_expand() { 608 fn test_stringify_expand() {
605 let expanded = expand_builtin_macro( 609 check_expansion(
606 r#" 610 r#"
607 #[rustc_builtin_macro] 611 #[rustc_builtin_macro]
608 macro_rules! stringify {() => {}} 612 macro_rules! stringify {() => {}}
609 stringify!(a b c) 613 stringify!(a b c)
610 "#, 614 "#,
615 expect![["\"a b c\""]],
611 ); 616 );
612
613 assert_eq!(expanded, "\"a b c\"");
614 } 617 }
615 618
616 #[test] 619 #[test]
617 fn test_env_expand() { 620 fn test_env_expand() {
618 let expanded = expand_builtin_macro( 621 check_expansion(
619 r#" 622 r#"
620 #[rustc_builtin_macro] 623 #[rustc_builtin_macro]
621 macro_rules! env {() => {}} 624 macro_rules! env {() => {}}
622 env!("TEST_ENV_VAR") 625 env!("TEST_ENV_VAR")
623 "#, 626 "#,
627 expect![["\"__RA_UNIMPLEMENTED__\""]],
624 ); 628 );
625
626 assert_eq!(expanded, "\"__RA_UNIMPLEMENTED__\"");
627 } 629 }
628 630
629 #[test] 631 #[test]
630 fn test_option_env_expand() { 632 fn test_option_env_expand() {
631 let expanded = expand_builtin_macro( 633 check_expansion(
632 r#" 634 r#"
633 #[rustc_builtin_macro] 635 #[rustc_builtin_macro]
634 macro_rules! option_env {() => {}} 636 macro_rules! option_env {() => {}}
635 option_env!("TEST_ENV_VAR") 637 option_env!("TEST_ENV_VAR")
636 "#, 638 "#,
639 expect![["std::option::Option::None:: < &str>"]],
637 ); 640 );
638
639 assert_eq!(expanded, "std::option::Option::None:: < &str>");
640 } 641 }
641 642
642 #[test] 643 #[test]
643 fn test_file_expand() { 644 fn test_file_expand() {
644 let expanded = expand_builtin_macro( 645 check_expansion(
645 r#" 646 r#"
646 #[rustc_builtin_macro] 647 #[rustc_builtin_macro]
647 macro_rules! file {() => {}} 648 macro_rules! file {() => {}}
648 file!() 649 file!()
649 "#, 650 "#,
651 expect![[r#""""#]],
650 ); 652 );
651
652 assert_eq!(expanded, "\"\"");
653 } 653 }
654 654
655 #[test] 655 #[test]
656 fn test_assert_expand() { 656 fn test_assert_expand() {
657 let expanded = expand_builtin_macro( 657 check_expansion(
658 r#" 658 r#"
659 #[rustc_builtin_macro] 659 #[rustc_builtin_macro]
660 macro_rules! assert { 660 macro_rules! assert {
@@ -663,14 +663,13 @@ mod tests {
663 } 663 }
664 assert!(true, "{} {:?}", arg1(a, b, c), arg2); 664 assert!(true, "{} {:?}", arg1(a, b, c), arg2);
665 "#, 665 "#,
666 expect![["{{(&(true), &(\"{} {:?}\"), &(arg1(a,b,c)), &(arg2),);}}"]],
666 ); 667 );
667
668 assert_eq!(expanded, "{{(&(true), &(\"{} {:?}\"), &(arg1(a,b,c)), &(arg2),);}}");
669 } 668 }
670 669
671 #[test] 670 #[test]
672 fn test_compile_error_expand() { 671 fn test_compile_error_expand() {
673 let expanded = expand_builtin_macro( 672 check_expansion(
674 r#" 673 r#"
675 #[rustc_builtin_macro] 674 #[rustc_builtin_macro]
676 macro_rules! compile_error { 675 macro_rules! compile_error {
@@ -679,15 +678,14 @@ mod tests {
679 } 678 }
680 compile_error!("error!"); 679 compile_error!("error!");
681 "#, 680 "#,
681 // This expands to nothing (since it's in item position), but emits an error.
682 expect![[""]],
682 ); 683 );
683
684 // This expands to nothing (since it's in item position), but emits an error.
685 assert_eq!(expanded, "");
686 } 684 }
687 685
688 #[test] 686 #[test]
689 fn test_format_args_expand() { 687 fn test_format_args_expand() {
690 let expanded = expand_builtin_macro( 688 check_expansion(
691 r#" 689 r#"
692 #[rustc_builtin_macro] 690 #[rustc_builtin_macro]
693 macro_rules! format_args { 691 macro_rules! format_args {
@@ -696,17 +694,15 @@ mod tests {
696 } 694 }
697 format_args!("{} {:?}", arg1(a, b, c), arg2); 695 format_args!("{} {:?}", arg1(a, b, c), arg2);
698 "#, 696 "#,
699 ); 697 expect![[
700 698 r#"std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(arg1(a,b,c)),std::fmt::Display::fmt),std::fmt::ArgumentV1::new(&(arg2),std::fmt::Display::fmt),])"#
701 assert_eq!( 699 ]],
702 expanded,
703 r#"std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(arg1(a,b,c)),std::fmt::Display::fmt),std::fmt::ArgumentV1::new(&(arg2),std::fmt::Display::fmt),])"#
704 ); 700 );
705 } 701 }
706 702
707 #[test] 703 #[test]
708 fn test_format_args_expand_with_comma_exprs() { 704 fn test_format_args_expand_with_comma_exprs() {
709 let expanded = expand_builtin_macro( 705 check_expansion(
710 r#" 706 r#"
711 #[rustc_builtin_macro] 707 #[rustc_builtin_macro]
712 macro_rules! format_args { 708 macro_rules! format_args {
@@ -715,17 +711,15 @@ mod tests {
715 } 711 }
716 format_args!("{} {:?}", a::<A,B>(), b); 712 format_args!("{} {:?}", a::<A,B>(), b);
717 "#, 713 "#,
718 ); 714 expect![[
719 715 r#"std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(a::<A,B>()),std::fmt::Display::fmt),std::fmt::ArgumentV1::new(&(b),std::fmt::Display::fmt),])"#
720 assert_eq!( 716 ]],
721 expanded,
722 r#"std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(a::<A,B>()),std::fmt::Display::fmt),std::fmt::ArgumentV1::new(&(b),std::fmt::Display::fmt),])"#
723 ); 717 );
724 } 718 }
725 719
726 #[test] 720 #[test]
727 fn test_include_bytes_expand() { 721 fn test_include_bytes_expand() {
728 let expanded = expand_builtin_macro( 722 check_expansion(
729 r#" 723 r#"
730 #[rustc_builtin_macro] 724 #[rustc_builtin_macro]
731 macro_rules! include_bytes { 725 macro_rules! include_bytes {
@@ -734,21 +728,19 @@ mod tests {
734 } 728 }
735 include_bytes("foo"); 729 include_bytes("foo");
736 "#, 730 "#,
731 expect![[r#"b"""#]],
737 ); 732 );
738
739 assert_eq!(expanded, r#"b"""#);
740 } 733 }
741 734
742 #[test] 735 #[test]
743 fn test_concat_expand() { 736 fn test_concat_expand() {
744 let expanded = expand_builtin_macro( 737 check_expansion(
745 r##" 738 r##"
746 #[rustc_builtin_macro] 739 #[rustc_builtin_macro]
747 macro_rules! concat {} 740 macro_rules! concat {}
748 concat!("foo", "r", 0, r#"bar"#, false); 741 concat!("foo", "r", 0, r#"bar"#, false);
749 "##, 742 "##,
743 expect![[r#""foor0barfalse""#]],
750 ); 744 );
751
752 assert_eq!(expanded, r#""foor0barfalse""#);
753 } 745 }
754} 746}
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index cb6e23320..9086e6c17 100644
--- a/crates/hir_expand/src/db.rs
+++ b/crates/hir_expand/src/db.rs
@@ -340,6 +340,8 @@ fn parse_macro_with_arg(
340 None => return ExpandResult { value: None, err: result.err }, 340 None => return ExpandResult { value: None, err: result.err },
341 }; 341 };
342 342
343 log::debug!("expanded = {}", tt.as_debug_string());
344
343 let fragment_kind = to_fragment_kind(db, macro_call_id); 345 let fragment_kind = to_fragment_kind(db, macro_call_id);
344 346
345 let (parse, rev_token_map) = match mbe::token_tree_to_syntax_node(&tt, fragment_kind) { 347 let (parse, rev_token_map) = match mbe::token_tree_to_syntax_node(&tt, fragment_kind) {
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs
index be1fd1f13..56c6b92d4 100644
--- a/crates/hir_ty/src/autoderef.rs
+++ b/crates/hir_ty/src/autoderef.rs
@@ -12,9 +12,10 @@ use log::{info, warn};
12 12
13use crate::{ 13use crate::{
14 db::HirDatabase, 14 db::HirDatabase,
15 to_assoc_type_id,
15 traits::{InEnvironment, Solution}, 16 traits::{InEnvironment, Solution},
16 utils::generics, 17 utils::generics,
17 BoundVar, Canonical, DebruijnIndex, Obligation, Substs, TraitRef, Ty, 18 BoundVar, Canonical, DebruijnIndex, Interner, Obligation, Substs, TraitRef, Ty, TyKind,
18}; 19};
19 20
20const AUTODEREF_RECURSION_LIMIT: usize = 10; 21const AUTODEREF_RECURSION_LIMIT: usize = 10;
@@ -81,8 +82,12 @@ fn deref_by_trait(
81 82
82 // Now do the assoc type projection 83 // Now do the assoc type projection
83 let projection = super::traits::ProjectionPredicate { 84 let projection = super::traits::ProjectionPredicate {
84 ty: Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len())), 85 ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len()))
85 projection_ty: super::ProjectionTy { associated_ty: target, parameters }, 86 .intern(&Interner),
87 projection_ty: super::ProjectionTy {
88 associated_ty_id: to_assoc_type_id(target),
89 substitution: parameters,
90 },
86 }; 91 };
87 92
88 let obligation = super::Obligation::Projection(projection); 93 let obligation = super::Obligation::Projection(projection);
@@ -114,8 +119,8 @@ fn deref_by_trait(
114 // new variables in that case 119 // new variables in that case
115 120
116 for i in 1..vars.0.kinds.len() { 121 for i in 1..vars.0.kinds.len() {
117 if vars.0.value[i - 1] 122 if vars.0.value[i - 1].interned(&Interner)
118 != Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) 123 != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1))
119 { 124 {
120 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution); 125 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution);
121 return None; 126 return None;
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs
index 06714409f..74a048672 100644
--- a/crates/hir_ty/src/db.rs
+++ b/crates/hir_ty/src/db.rs
@@ -12,7 +12,7 @@ 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, GenericPredicate, InferenceResult, OpaqueTyId, PolyFnSig, 15 Binders, CallableDefId, FnDefId, GenericPredicate, ImplTraitId, InferenceResult, PolyFnSig,
16 ReturnTypeImplTraits, TraitRef, Ty, TyDefId, ValueTyDefId, 16 ReturnTypeImplTraits, TraitRef, Ty, TyDefId, ValueTyDefId,
17}; 17};
18use hir_expand::name::Name; 18use hir_expand::name::Name;
@@ -65,6 +65,9 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
65 #[salsa::invoke(crate::lower::generic_predicates_query)] 65 #[salsa::invoke(crate::lower::generic_predicates_query)]
66 fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<GenericPredicate>]>; 66 fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<GenericPredicate>]>;
67 67
68 #[salsa::invoke(crate::lower::trait_environment_query)]
69 fn trait_environment(&self, def: GenericDefId) -> Arc<crate::TraitEnvironment>;
70
68 #[salsa::invoke(crate::lower::generic_defaults_query)] 71 #[salsa::invoke(crate::lower::generic_defaults_query)]
69 fn generic_defaults(&self, def: GenericDefId) -> Arc<[Binders<Ty>]>; 72 fn generic_defaults(&self, def: GenericDefId) -> Arc<[Binders<Ty>]>;
70 73
@@ -81,11 +84,11 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
81 #[salsa::interned] 84 #[salsa::interned]
82 fn intern_callable_def(&self, callable_def: CallableDefId) -> InternedCallableDefId; 85 fn intern_callable_def(&self, callable_def: CallableDefId) -> InternedCallableDefId;
83 #[salsa::interned] 86 #[salsa::interned]
84 fn intern_type_param_id(&self, param_id: TypeParamId) -> GlobalTypeParamId; 87 fn intern_type_param_id(&self, param_id: TypeParamId) -> InternedTypeParamId;
85 #[salsa::interned] 88 #[salsa::interned]
86 fn intern_impl_trait_id(&self, id: OpaqueTyId) -> InternedOpaqueTyId; 89 fn intern_impl_trait_id(&self, id: ImplTraitId) -> InternedOpaqueTyId;
87 #[salsa::interned] 90 #[salsa::interned]
88 fn intern_closure(&self, id: (DefWithBodyId, ExprId)) -> ClosureId; 91 fn intern_closure(&self, id: (DefWithBodyId, ExprId)) -> InternedClosureId;
89 92
90 #[salsa::invoke(chalk::associated_ty_data_query)] 93 #[salsa::invoke(chalk::associated_ty_data_query)]
91 fn associated_ty_data(&self, id: chalk::AssocTypeId) -> Arc<chalk::AssociatedTyDatum>; 94 fn associated_ty_data(&self, id: chalk::AssocTypeId) -> Arc<chalk::AssociatedTyDatum>;
@@ -100,10 +103,10 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
100 fn impl_datum(&self, krate: CrateId, impl_id: chalk::ImplId) -> Arc<chalk::ImplDatum>; 103 fn impl_datum(&self, krate: CrateId, impl_id: chalk::ImplId) -> Arc<chalk::ImplDatum>;
101 104
102 #[salsa::invoke(crate::traits::chalk::fn_def_datum_query)] 105 #[salsa::invoke(crate::traits::chalk::fn_def_datum_query)]
103 fn fn_def_datum(&self, krate: CrateId, fn_def_id: chalk::FnDefId) -> Arc<chalk::FnDefDatum>; 106 fn fn_def_datum(&self, krate: CrateId, fn_def_id: FnDefId) -> Arc<chalk::FnDefDatum>;
104 107
105 #[salsa::invoke(crate::traits::chalk::fn_def_variance_query)] 108 #[salsa::invoke(crate::traits::chalk::fn_def_variance_query)]
106 fn fn_def_variance(&self, krate: CrateId, fn_def_id: chalk::FnDefId) -> chalk::Variances; 109 fn fn_def_variance(&self, krate: CrateId, fn_def_id: FnDefId) -> chalk::Variances;
107 110
108 #[salsa::invoke(crate::traits::chalk::adt_variance_query)] 111 #[salsa::invoke(crate::traits::chalk::adt_variance_query)]
109 fn adt_variance(&self, krate: CrateId, adt_id: chalk::AdtId) -> chalk::Variances; 112 fn adt_variance(&self, krate: CrateId, adt_id: chalk::AdtId) -> chalk::Variances;
@@ -149,16 +152,16 @@ fn hir_database_is_object_safe() {
149} 152}
150 153
151#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 154#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
152pub struct GlobalTypeParamId(salsa::InternId); 155pub struct InternedTypeParamId(salsa::InternId);
153impl_intern_key!(GlobalTypeParamId); 156impl_intern_key!(InternedTypeParamId);
154 157
155#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 158#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
156pub struct InternedOpaqueTyId(salsa::InternId); 159pub struct InternedOpaqueTyId(salsa::InternId);
157impl_intern_key!(InternedOpaqueTyId); 160impl_intern_key!(InternedOpaqueTyId);
158 161
159#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 162#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
160pub struct ClosureId(salsa::InternId); 163pub struct InternedClosureId(salsa::InternId);
161impl_intern_key!(ClosureId); 164impl_intern_key!(InternedClosureId);
162 165
163/// This exists just for Chalk, because Chalk just has a single `FnDefId` where 166/// This exists just for Chalk, because Chalk just has a single `FnDefId` where
164/// we have different IDs for struct and enum variant constructors. 167/// we have different IDs for struct and enum variant constructors.
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs
index 2751cd304..b2bfd68d4 100644
--- a/crates/hir_ty/src/diagnostics/expr.rs
+++ b/crates/hir_ty/src/diagnostics/expr.rs
@@ -15,7 +15,7 @@ use crate::{
15 MissingPatFields, RemoveThisSemicolon, 15 MissingPatFields, RemoveThisSemicolon,
16 }, 16 },
17 utils::variant_data, 17 utils::variant_data,
18 AdtId, InferenceResult, Ty, 18 AdtId, InferenceResult, Interner, Ty, TyKind,
19}; 19};
20 20
21pub(crate) use hir_def::{ 21pub(crate) use hir_def::{
@@ -289,11 +289,10 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
289 let (body, source_map): (Arc<Body>, Arc<BodySourceMap>) = 289 let (body, source_map): (Arc<Body>, Arc<BodySourceMap>) =
290 db.body_with_source_map(self.owner.into()); 290 db.body_with_source_map(self.owner.into());
291 291
292 let match_expr_ty = match infer.type_of_expr.get(match_expr) { 292 let match_expr_ty = if infer.type_of_expr[match_expr].is_unknown() {
293 // If we can't resolve the type of the match expression 293 return;
294 // we cannot perform exhaustiveness checks. 294 } else {
295 None | Some(Ty::Unknown) => return, 295 &infer.type_of_expr[match_expr]
296 Some(ty) => ty,
297 }; 296 };
298 297
299 let cx = MatchCheckCtx { match_expr, body, infer: infer.clone(), db }; 298 let cx = MatchCheckCtx { match_expr, body, infer: infer.clone(), db };
@@ -379,14 +378,14 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
379 _ => return, 378 _ => return,
380 }; 379 };
381 380
382 let (params, required) = match mismatch.expected { 381 let (params, required) = match mismatch.expected.interned(&Interner) {
383 Ty::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ref parameters) 382 TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ref parameters)
384 if enum_id == core_result_enum => 383 if *enum_id == core_result_enum =>
385 { 384 {
386 (parameters, "Ok".to_string()) 385 (parameters, "Ok".to_string())
387 } 386 }
388 Ty::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ref parameters) 387 TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ref parameters)
389 if enum_id == core_option_enum => 388 if *enum_id == core_option_enum =>
390 { 389 {
391 (parameters, "Some".to_string()) 390 (parameters, "Some".to_string())
392 } 391 }
diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs
index 04d39c571..5a5cdcbf3 100644
--- a/crates/hir_ty/src/diagnostics/match_check.rs
+++ b/crates/hir_ty/src/diagnostics/match_check.rs
@@ -227,7 +227,7 @@ use hir_def::{
227use la_arena::Idx; 227use la_arena::Idx;
228use smallvec::{smallvec, SmallVec}; 228use smallvec::{smallvec, SmallVec};
229 229
230use crate::{db::HirDatabase, AdtId, InferenceResult, Ty}; 230use crate::{db::HirDatabase, AdtId, InferenceResult, Interner, TyKind};
231 231
232#[derive(Debug, Clone, Copy)] 232#[derive(Debug, Clone, Copy)]
233/// Either a pattern from the source code being analyzed, represented as 233/// Either a pattern from the source code being analyzed, represented as
@@ -626,13 +626,13 @@ pub(super) fn is_useful(
626 // - enum with no variants 626 // - enum with no variants
627 // - `!` type 627 // - `!` type
628 // In those cases, no match arm is useful. 628 // In those cases, no match arm is useful.
629 match cx.infer[cx.match_expr].strip_references() { 629 match cx.infer[cx.match_expr].strip_references().interned(&Interner) {
630 Ty::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ..) => { 630 TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ..) => {
631 if cx.db.enum_data(*enum_id).variants.is_empty() { 631 if cx.db.enum_data(*enum_id).variants.is_empty() {
632 return Ok(Usefulness::NotUseful); 632 return Ok(Usefulness::NotUseful);
633 } 633 }
634 } 634 }
635 Ty::Never => return Ok(Usefulness::NotUseful), 635 TyKind::Never => return Ok(Usefulness::NotUseful),
636 _ => (), 636 _ => (),
637 } 637 }
638 638
diff --git a/crates/hir_ty/src/diagnostics/unsafe_check.rs b/crates/hir_ty/src/diagnostics/unsafe_check.rs
index e77a20fea..20bb64827 100644
--- a/crates/hir_ty/src/diagnostics/unsafe_check.rs
+++ b/crates/hir_ty/src/diagnostics/unsafe_check.rs
@@ -11,7 +11,7 @@ use hir_def::{
11}; 11};
12use hir_expand::diagnostics::DiagnosticSink; 12use hir_expand::diagnostics::DiagnosticSink;
13 13
14use crate::{db::HirDatabase, diagnostics::MissingUnsafe, InferenceResult, Ty}; 14use crate::{db::HirDatabase, diagnostics::MissingUnsafe, InferenceResult, Interner, TyKind};
15 15
16pub(super) struct UnsafeValidator<'a, 'b: 'a> { 16pub(super) struct UnsafeValidator<'a, 'b: 'a> {
17 owner: DefWithBodyId, 17 owner: DefWithBodyId,
@@ -85,7 +85,7 @@ fn walk_unsafe(
85 let expr = &body.exprs[current]; 85 let expr = &body.exprs[current];
86 match expr { 86 match expr {
87 &Expr::Call { callee, .. } => { 87 &Expr::Call { callee, .. } => {
88 if let Some(func) = infer[callee].as_fn_def() { 88 if let Some(func) = infer[callee].as_fn_def(db) {
89 if db.function_data(func).is_unsafe { 89 if db.function_data(func).is_unsafe {
90 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); 90 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
91 } 91 }
@@ -110,7 +110,7 @@ fn walk_unsafe(
110 } 110 }
111 } 111 }
112 Expr::UnaryOp { expr, op: UnaryOp::Deref } => { 112 Expr::UnaryOp { expr, op: UnaryOp::Deref } => {
113 if let Ty::Raw(..) = &infer[*expr] { 113 if let TyKind::Raw(..) = &infer[*expr].interned(&Interner) {
114 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); 114 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
115 } 115 }
116 } 116 }
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index ab51cb0a6..378c951c5 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -11,9 +11,10 @@ use hir_def::{
11use hir_expand::name::Name; 11use hir_expand::name::Name;
12 12
13use crate::{ 13use crate::{
14 db::HirDatabase, primitive, utils::generics, AdtId, AliasTy, CallableDefId, CallableSig, 14 db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive,
15 GenericPredicate, Lifetime, Obligation, OpaqueTy, OpaqueTyId, ProjectionTy, Scalar, Substs, 15 to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasTy, CallableDefId,
16 TraitRef, Ty, 16 CallableSig, GenericPredicate, ImplTraitId, Interner, Lifetime, Obligation, OpaqueTy,
17 ProjectionTy, Scalar, Substs, TraitRef, Ty, TyKind,
17}; 18};
18 19
19pub struct HirFormatter<'a> { 20pub struct HirFormatter<'a> {
@@ -244,19 +245,19 @@ impl HirDisplay for ProjectionTy {
244 } 245 }
245 246
246 let trait_ = f.db.trait_data(self.trait_(f.db)); 247 let trait_ = f.db.trait_data(self.trait_(f.db));
247 let first_parameter = self.parameters[0].into_displayable( 248 let first_parameter = self.substitution[0].into_displayable(
248 f.db, 249 f.db,
249 f.max_size, 250 f.max_size,
250 f.omit_verbose_types, 251 f.omit_verbose_types,
251 f.display_target, 252 f.display_target,
252 ); 253 );
253 write!(f, "<{} as {}", first_parameter, trait_.name)?; 254 write!(f, "<{} as {}", first_parameter, trait_.name)?;
254 if self.parameters.len() > 1 { 255 if self.substitution.len() > 1 {
255 write!(f, "<")?; 256 write!(f, "<")?;
256 f.write_joined(&self.parameters[1..], ", ")?; 257 f.write_joined(&self.substitution[1..], ", ")?;
257 write!(f, ">")?; 258 write!(f, ">")?;
258 } 259 }
259 write!(f, ">::{}", f.db.type_alias_data(self.associated_ty).name)?; 260 write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?;
260 Ok(()) 261 Ok(())
261 } 262 }
262} 263}
@@ -267,32 +268,32 @@ impl HirDisplay for Ty {
267 return write!(f, "{}", TYPE_HINT_TRUNCATION); 268 return write!(f, "{}", TYPE_HINT_TRUNCATION);
268 } 269 }
269 270
270 match self { 271 match self.interned(&Interner) {
271 Ty::Never => write!(f, "!")?, 272 TyKind::Never => write!(f, "!")?,
272 Ty::Str => write!(f, "str")?, 273 TyKind::Str => write!(f, "str")?,
273 Ty::Scalar(Scalar::Bool) => write!(f, "bool")?, 274 TyKind::Scalar(Scalar::Bool) => write!(f, "bool")?,
274 Ty::Scalar(Scalar::Char) => write!(f, "char")?, 275 TyKind::Scalar(Scalar::Char) => write!(f, "char")?,
275 &Ty::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?, 276 &TyKind::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?,
276 &Ty::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?, 277 &TyKind::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?,
277 &Ty::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?, 278 &TyKind::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?,
278 Ty::Slice(parameters) => { 279 TyKind::Slice(parameters) => {
279 let t = parameters.as_single(); 280 let t = parameters.as_single();
280 write!(f, "[")?; 281 write!(f, "[")?;
281 t.hir_fmt(f)?; 282 t.hir_fmt(f)?;
282 write!(f, "]")?; 283 write!(f, "]")?;
283 } 284 }
284 Ty::Array(parameters) => { 285 TyKind::Array(parameters) => {
285 let t = parameters.as_single(); 286 let t = parameters.as_single();
286 write!(f, "[")?; 287 write!(f, "[")?;
287 t.hir_fmt(f)?; 288 t.hir_fmt(f)?;
288 write!(f, "; _]")?; 289 write!(f, "; _]")?;
289 } 290 }
290 Ty::Raw(m, parameters) | Ty::Ref(m, parameters) => { 291 TyKind::Raw(m, parameters) | TyKind::Ref(m, parameters) => {
291 let t = parameters.as_single(); 292 let t = parameters.as_single();
292 let ty_display = 293 let ty_display =
293 t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); 294 t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target);
294 295
295 if matches!(self, Ty::Raw(..)) { 296 if matches!(self.interned(&Interner), TyKind::Raw(..)) {
296 write!( 297 write!(
297 f, 298 f,
298 "*{}", 299 "*{}",
@@ -312,22 +313,29 @@ impl HirDisplay for Ty {
312 )?; 313 )?;
313 } 314 }
314 315
316 // FIXME: all this just to decide whether to use parentheses...
315 let datas; 317 let datas;
316 let predicates = match t { 318 let predicates = match t.interned(&Interner) {
317 Ty::Dyn(predicates) if predicates.len() > 1 => { 319 TyKind::Dyn(predicates) if predicates.len() > 1 => {
318 Cow::Borrowed(predicates.as_ref()) 320 Cow::Borrowed(predicates.as_ref())
319 } 321 }
320 &Ty::Alias(AliasTy::Opaque(OpaqueTy { 322 &TyKind::Alias(AliasTy::Opaque(OpaqueTy {
321 opaque_ty_id: OpaqueTyId::ReturnTypeImplTrait(func, idx), 323 opaque_ty_id,
322 ref parameters, 324 substitution: ref parameters,
323 })) => { 325 })) => {
324 datas = 326 let impl_trait_id = f.db.lookup_intern_impl_trait_id(opaque_ty_id.into());
325 f.db.return_type_impl_traits(func).expect("impl trait id without data"); 327 if let ImplTraitId::ReturnTypeImplTrait(func, idx) = impl_trait_id {
326 let data = (*datas) 328 datas =
327 .as_ref() 329 f.db.return_type_impl_traits(func)
328 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 330 .expect("impl trait id without data");
329 let bounds = data.subst(parameters); 331 let data = (*datas)
330 Cow::Owned(bounds.value) 332 .as_ref()
333 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
334 let bounds = data.subst(parameters);
335 Cow::Owned(bounds.value)
336 } else {
337 Cow::Borrowed(&[][..])
338 }
331 } 339 }
332 _ => Cow::Borrowed(&[][..]), 340 _ => Cow::Borrowed(&[][..]),
333 }; 341 };
@@ -347,7 +355,7 @@ impl HirDisplay for Ty {
347 write!(f, "{}", ty_display)?; 355 write!(f, "{}", ty_display)?;
348 } 356 }
349 } 357 }
350 Ty::Tuple(_, substs) => { 358 TyKind::Tuple(_, substs) => {
351 if substs.len() == 1 { 359 if substs.len() == 1 {
352 write!(f, "(")?; 360 write!(f, "(")?;
353 substs[0].hir_fmt(f)?; 361 substs[0].hir_fmt(f)?;
@@ -358,12 +366,12 @@ impl HirDisplay for Ty {
358 write!(f, ")")?; 366 write!(f, ")")?;
359 } 367 }
360 } 368 }
361 Ty::Function(fn_ptr) => { 369 TyKind::Function(fn_ptr) => {
362 let sig = CallableSig::from_fn_ptr(fn_ptr); 370 let sig = CallableSig::from_fn_ptr(fn_ptr);
363 sig.hir_fmt(f)?; 371 sig.hir_fmt(f)?;
364 } 372 }
365 Ty::FnDef(def, parameters) => { 373 TyKind::FnDef(def, parameters) => {
366 let def = *def; 374 let def = from_chalk(f.db, *def);
367 let sig = f.db.callable_item_signature(def).subst(parameters); 375 let sig = f.db.callable_item_signature(def).subst(parameters);
368 match def { 376 match def {
369 CallableDefId::FunctionId(ff) => { 377 CallableDefId::FunctionId(ff) => {
@@ -401,7 +409,7 @@ impl HirDisplay for Ty {
401 write!(f, " -> {}", ret_display)?; 409 write!(f, " -> {}", ret_display)?;
402 } 410 }
403 } 411 }
404 Ty::Adt(AdtId(def_id), parameters) => { 412 TyKind::Adt(AdtId(def_id), parameters) => {
405 match f.display_target { 413 match f.display_target {
406 DisplayTarget::Diagnostics | DisplayTarget::Test => { 414 DisplayTarget::Diagnostics | DisplayTarget::Test => {
407 let name = match *def_id { 415 let name = match *def_id {
@@ -427,37 +435,39 @@ impl HirDisplay for Ty {
427 } 435 }
428 436
429 if parameters.len() > 0 { 437 if parameters.len() > 0 {
430 let parameters_to_write = 438 let parameters_to_write = if f.display_target.is_source_code()
431 if f.display_target.is_source_code() || f.omit_verbose_types() { 439 || f.omit_verbose_types()
432 match self 440 {
433 .as_generic_def() 441 match self
434 .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) 442 .as_generic_def(f.db)
435 .filter(|defaults| !defaults.is_empty()) 443 .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
436 { 444 .filter(|defaults| !defaults.is_empty())
437 None => parameters.0.as_ref(), 445 {
438 Some(default_parameters) => { 446 None => parameters.0.as_ref(),
439 let mut default_from = 0; 447 Some(default_parameters) => {
440 for (i, parameter) in parameters.iter().enumerate() { 448 let mut default_from = 0;
441 match (parameter, default_parameters.get(i)) { 449 for (i, parameter) in parameters.iter().enumerate() {
442 (&Ty::Unknown, _) | (_, None) => { 450 match (parameter.interned(&Interner), default_parameters.get(i))
451 {
452 (&TyKind::Unknown, _) | (_, None) => {
453 default_from = i + 1;
454 }
455 (_, Some(default_parameter)) => {
456 let actual_default = default_parameter
457 .clone()
458 .subst(&parameters.prefix(i));
459 if parameter != &actual_default {
443 default_from = i + 1; 460 default_from = i + 1;
444 } 461 }
445 (_, Some(default_parameter)) => {
446 let actual_default = default_parameter
447 .clone()
448 .subst(&parameters.prefix(i));
449 if parameter != &actual_default {
450 default_from = i + 1;
451 }
452 }
453 } 462 }
454 } 463 }
455 &parameters.0[0..default_from]
456 } 464 }
465 &parameters.0[0..default_from]
457 } 466 }
458 } else { 467 }
459 parameters.0.as_ref() 468 } else {
460 }; 469 parameters.0.as_ref()
470 };
461 if !parameters_to_write.is_empty() { 471 if !parameters_to_write.is_empty() {
462 write!(f, "<")?; 472 write!(f, "<")?;
463 f.write_joined(parameters_to_write, ", ")?; 473 f.write_joined(parameters_to_write, ", ")?;
@@ -465,13 +475,14 @@ impl HirDisplay for Ty {
465 } 475 }
466 } 476 }
467 } 477 }
468 Ty::AssociatedType(type_alias, parameters) => { 478 TyKind::AssociatedType(assoc_type_id, parameters) => {
479 let type_alias = from_assoc_type_id(*assoc_type_id);
469 let trait_ = match type_alias.lookup(f.db.upcast()).container { 480 let trait_ = match type_alias.lookup(f.db.upcast()).container {
470 AssocContainerId::TraitId(it) => it, 481 AssocContainerId::TraitId(it) => it,
471 _ => panic!("not an associated type"), 482 _ => panic!("not an associated type"),
472 }; 483 };
473 let trait_ = f.db.trait_data(trait_); 484 let trait_ = f.db.trait_data(trait_);
474 let type_alias_data = f.db.type_alias_data(*type_alias); 485 let type_alias_data = f.db.type_alias_data(type_alias);
475 486
476 // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) 487 // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types)
477 if f.display_target.is_test() { 488 if f.display_target.is_test() {
@@ -482,19 +493,22 @@ impl HirDisplay for Ty {
482 write!(f, ">")?; 493 write!(f, ">")?;
483 } 494 }
484 } else { 495 } else {
485 let projection_ty = 496 let projection_ty = ProjectionTy {
486 ProjectionTy { associated_ty: *type_alias, parameters: parameters.clone() }; 497 associated_ty_id: to_assoc_type_id(type_alias),
498 substitution: parameters.clone(),
499 };
487 500
488 projection_ty.hir_fmt(f)?; 501 projection_ty.hir_fmt(f)?;
489 } 502 }
490 } 503 }
491 Ty::ForeignType(type_alias) => { 504 TyKind::ForeignType(type_alias) => {
492 let type_alias = f.db.type_alias_data(*type_alias); 505 let type_alias = f.db.type_alias_data(from_foreign_def_id(*type_alias));
493 write!(f, "{}", type_alias.name)?; 506 write!(f, "{}", type_alias.name)?;
494 } 507 }
495 Ty::OpaqueType(opaque_ty_id, parameters) => { 508 TyKind::OpaqueType(opaque_ty_id, parameters) => {
496 match opaque_ty_id { 509 let impl_trait_id = f.db.lookup_intern_impl_trait_id((*opaque_ty_id).into());
497 &OpaqueTyId::ReturnTypeImplTrait(func, idx) => { 510 match impl_trait_id {
511 ImplTraitId::ReturnTypeImplTrait(func, idx) => {
498 let datas = 512 let datas =
499 f.db.return_type_impl_traits(func).expect("impl trait id without data"); 513 f.db.return_type_impl_traits(func).expect("impl trait id without data");
500 let data = (*datas) 514 let data = (*datas)
@@ -504,14 +518,14 @@ impl HirDisplay for Ty {
504 write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; 518 write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?;
505 // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution 519 // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
506 } 520 }
507 OpaqueTyId::AsyncBlockTypeImplTrait(..) => { 521 ImplTraitId::AsyncBlockTypeImplTrait(..) => {
508 write!(f, "impl Future<Output = ")?; 522 write!(f, "impl Future<Output = ")?;
509 parameters[0].hir_fmt(f)?; 523 parameters[0].hir_fmt(f)?;
510 write!(f, ">")?; 524 write!(f, ">")?;
511 } 525 }
512 } 526 }
513 } 527 }
514 Ty::Closure(.., substs) => { 528 TyKind::Closure(.., substs) => {
515 let sig = substs[0].callable_sig(f.db); 529 let sig = substs[0].callable_sig(f.db);
516 if let Some(sig) = sig { 530 if let Some(sig) = sig {
517 if sig.params().is_empty() { 531 if sig.params().is_empty() {
@@ -535,7 +549,8 @@ impl HirDisplay for Ty {
535 write!(f, "{{closure}}")?; 549 write!(f, "{{closure}}")?;
536 } 550 }
537 } 551 }
538 Ty::Placeholder(id) => { 552 TyKind::Placeholder(idx) => {
553 let id = from_placeholder_idx(f.db, *idx);
539 let generics = generics(f.db.upcast(), id.parent); 554 let generics = generics(f.db.upcast(), id.parent);
540 let param_data = &generics.params.types[id.local_id]; 555 let param_data = &generics.params.types[id.local_id];
541 match param_data.provenance { 556 match param_data.provenance {
@@ -543,8 +558,8 @@ impl HirDisplay for Ty {
543 write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? 558 write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))?
544 } 559 }
545 TypeParamProvenance::ArgumentImplTrait => { 560 TypeParamProvenance::ArgumentImplTrait => {
546 let bounds = f.db.generic_predicates_for_param(*id); 561 let bounds = f.db.generic_predicates_for_param(id);
547 let substs = Substs::type_params_for_generics(&generics); 562 let substs = Substs::type_params_for_generics(f.db, &generics);
548 write_bounds_like_dyn_trait_with_prefix( 563 write_bounds_like_dyn_trait_with_prefix(
549 "impl", 564 "impl",
550 &bounds.iter().map(|b| b.clone().subst(&substs)).collect::<Vec<_>>(), 565 &bounds.iter().map(|b| b.clone().subst(&substs)).collect::<Vec<_>>(),
@@ -553,28 +568,29 @@ impl HirDisplay for Ty {
553 } 568 }
554 } 569 }
555 } 570 }
556 Ty::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, 571 TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?,
557 Ty::Dyn(predicates) => { 572 TyKind::Dyn(predicates) => {
558 write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?; 573 write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?;
559 } 574 }
560 Ty::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?, 575 TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?,
561 Ty::Alias(AliasTy::Opaque(opaque_ty)) => { 576 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
562 match opaque_ty.opaque_ty_id { 577 let impl_trait_id = f.db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into());
563 OpaqueTyId::ReturnTypeImplTrait(func, idx) => { 578 match impl_trait_id {
579 ImplTraitId::ReturnTypeImplTrait(func, idx) => {
564 let datas = 580 let datas =
565 f.db.return_type_impl_traits(func).expect("impl trait id without data"); 581 f.db.return_type_impl_traits(func).expect("impl trait id without data");
566 let data = (*datas) 582 let data = (*datas)
567 .as_ref() 583 .as_ref()
568 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 584 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
569 let bounds = data.subst(&opaque_ty.parameters); 585 let bounds = data.subst(&opaque_ty.substitution);
570 write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; 586 write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?;
571 } 587 }
572 OpaqueTyId::AsyncBlockTypeImplTrait(..) => { 588 ImplTraitId::AsyncBlockTypeImplTrait(..) => {
573 write!(f, "{{async block}}")?; 589 write!(f, "{{async block}}")?;
574 } 590 }
575 }; 591 };
576 } 592 }
577 Ty::Unknown => { 593 TyKind::Unknown => {
578 if f.display_target.is_source_code() { 594 if f.display_target.is_source_code() {
579 return Err(HirDisplayError::DisplaySourceCodeError( 595 return Err(HirDisplayError::DisplaySourceCodeError(
580 DisplaySourceCodeError::UnknownType, 596 DisplaySourceCodeError::UnknownType,
@@ -582,7 +598,7 @@ impl HirDisplay for Ty {
582 } 598 }
583 write!(f, "{{unknown}}")?; 599 write!(f, "{{unknown}}")?;
584 } 600 }
585 Ty::InferenceVar(..) => write!(f, "_")?, 601 TyKind::InferenceVar(..) => write!(f, "_")?,
586 } 602 }
587 Ok(()) 603 Ok(())
588 } 604 }
@@ -695,7 +711,9 @@ fn write_bounds_like_dyn_trait(
695 write!(f, "<")?; 711 write!(f, "<")?;
696 angle_open = true; 712 angle_open = true;
697 } 713 }
698 let type_alias = f.db.type_alias_data(projection_pred.projection_ty.associated_ty); 714 let type_alias = f.db.type_alias_data(from_assoc_type_id(
715 projection_pred.projection_ty.associated_ty_id,
716 ));
699 write!(f, "{} = ", type_alias.name)?; 717 write!(f, "{} = ", type_alias.name)?;
700 projection_pred.ty.hir_fmt(f)?; 718 projection_pred.ty.hir_fmt(f)?;
701 } 719 }
@@ -766,7 +784,10 @@ impl HirDisplay for GenericPredicate {
766 write!( 784 write!(
767 f, 785 f,
768 ">::{} = ", 786 ">::{} = ",
769 f.db.type_alias_data(projection_pred.projection_ty.associated_ty).name, 787 f.db.type_alias_data(from_assoc_type_id(
788 projection_pred.projection_ty.associated_ty_id
789 ))
790 .name,
770 )?; 791 )?;
771 projection_pred.ty.hir_fmt(f)?; 792 projection_pred.ty.hir_fmt(f)?;
772 } 793 }
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index 4d771a91e..fbfedb4e6 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -41,7 +41,8 @@ use super::{
41 InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeWalk, 41 InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeWalk,
42}; 42};
43use crate::{ 43use crate::{
44 db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, AliasTy, 44 db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode,
45 to_assoc_type_id, AliasTy, Interner, TyKind,
45}; 46};
46 47
47pub(crate) use unify::unify; 48pub(crate) use unify::unify;
@@ -169,7 +170,7 @@ impl Index<ExprId> for InferenceResult {
169 type Output = Ty; 170 type Output = Ty;
170 171
171 fn index(&self, expr: ExprId) -> &Ty { 172 fn index(&self, expr: ExprId) -> &Ty {
172 self.type_of_expr.get(expr).unwrap_or(&Ty::Unknown) 173 self.type_of_expr.get(expr).unwrap_or(&Ty(TyKind::Unknown))
173 } 174 }
174} 175}
175 176
@@ -177,7 +178,7 @@ impl Index<PatId> for InferenceResult {
177 type Output = Ty; 178 type Output = Ty;
178 179
179 fn index(&self, pat: PatId) -> &Ty { 180 fn index(&self, pat: PatId) -> &Ty {
180 self.type_of_pat.get(pat).unwrap_or(&Ty::Unknown) 181 self.type_of_pat.get(pat).unwrap_or(&Ty(TyKind::Unknown))
181 } 182 }
182} 183}
183 184
@@ -226,8 +227,10 @@ impl<'a> InferenceContext<'a> {
226 result: InferenceResult::default(), 227 result: InferenceResult::default(),
227 table: unify::InferenceTable::new(), 228 table: unify::InferenceTable::new(),
228 obligations: Vec::default(), 229 obligations: Vec::default(),
229 return_ty: Ty::Unknown, // set in collect_fn_signature 230 return_ty: TyKind::Unknown.intern(&Interner), // set in collect_fn_signature
230 trait_env: TraitEnvironment::lower(db, &resolver), 231 trait_env: owner
232 .as_generic_def_id()
233 .map_or_else(Default::default, |d| db.trait_environment(d)),
231 db, 234 db,
232 owner, 235 owner,
233 body: db.body(owner), 236 body: db.body(owner),
@@ -237,15 +240,19 @@ impl<'a> InferenceContext<'a> {
237 } 240 }
238 } 241 }
239 242
243 fn err_ty(&self) -> Ty {
244 TyKind::Unknown.intern(&Interner)
245 }
246
240 fn resolve_all(mut self) -> InferenceResult { 247 fn resolve_all(mut self) -> InferenceResult {
241 // FIXME resolve obligations as well (use Guidance if necessary) 248 // FIXME resolve obligations as well (use Guidance if necessary)
242 let mut result = std::mem::take(&mut self.result); 249 let mut result = std::mem::take(&mut self.result);
243 for ty in result.type_of_expr.values_mut() { 250 for ty in result.type_of_expr.values_mut() {
244 let resolved = self.table.resolve_ty_completely(mem::replace(ty, Ty::Unknown)); 251 let resolved = self.table.resolve_ty_completely(ty.clone());
245 *ty = resolved; 252 *ty = resolved;
246 } 253 }
247 for ty in result.type_of_pat.values_mut() { 254 for ty in result.type_of_pat.values_mut() {
248 let resolved = self.table.resolve_ty_completely(mem::replace(ty, Ty::Unknown)); 255 let resolved = self.table.resolve_ty_completely(ty.clone());
249 *ty = resolved; 256 *ty = resolved;
250 } 257 }
251 result 258 result
@@ -287,7 +294,7 @@ impl<'a> InferenceContext<'a> {
287 // FIXME use right resolver for block 294 // FIXME use right resolver for block
288 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver) 295 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver)
289 .with_impl_trait_mode(impl_trait_mode); 296 .with_impl_trait_mode(impl_trait_mode);
290 let ty = Ty::from_hir(&ctx, type_ref); 297 let ty = ctx.lower_ty(type_ref);
291 let ty = self.insert_type_vars(ty); 298 let ty = self.insert_type_vars(ty);
292 self.normalize_associated_types_in(ty) 299 self.normalize_associated_types_in(ty)
293 } 300 }
@@ -298,8 +305,8 @@ impl<'a> InferenceContext<'a> {
298 305
299 /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. 306 /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it.
300 fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { 307 fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
301 match ty { 308 match ty.interned(&Interner) {
302 Ty::Unknown => self.table.new_type_var(), 309 TyKind::Unknown => self.table.new_type_var(),
303 _ => ty, 310 _ => ty,
304 } 311 }
305 } 312 }
@@ -377,13 +384,16 @@ impl<'a> InferenceContext<'a> {
377 let trait_ref = TraitRef { trait_, substs: substs.clone() }; 384 let trait_ref = TraitRef { trait_, substs: substs.clone() };
378 let projection = ProjectionPredicate { 385 let projection = ProjectionPredicate {
379 ty: ty.clone(), 386 ty: ty.clone(),
380 projection_ty: ProjectionTy { associated_ty: res_assoc_ty, parameters: substs }, 387 projection_ty: ProjectionTy {
388 associated_ty_id: to_assoc_type_id(res_assoc_ty),
389 substitution: substs,
390 },
381 }; 391 };
382 self.obligations.push(Obligation::Trait(trait_ref)); 392 self.obligations.push(Obligation::Trait(trait_ref));
383 self.obligations.push(Obligation::Projection(projection)); 393 self.obligations.push(Obligation::Projection(projection));
384 self.resolve_ty_as_possible(ty) 394 self.resolve_ty_as_possible(ty)
385 } 395 }
386 None => Ty::Unknown, 396 None => self.err_ty(),
387 } 397 }
388 } 398 }
389 399
@@ -395,8 +405,10 @@ impl<'a> InferenceContext<'a> {
395 /// to do it as well. 405 /// to do it as well.
396 fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { 406 fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty {
397 let ty = self.resolve_ty_as_possible(ty); 407 let ty = self.resolve_ty_as_possible(ty);
398 ty.fold(&mut |ty| match ty { 408 ty.fold(&mut |ty| match ty.interned(&Interner) {
399 Ty::Alias(AliasTy::Projection(proj_ty)) => self.normalize_projection_ty(proj_ty), 409 TyKind::Alias(AliasTy::Projection(proj_ty)) => {
410 self.normalize_projection_ty(proj_ty.clone())
411 }
400 _ => ty, 412 _ => ty,
401 }) 413 })
402 } 414 }
@@ -412,7 +424,7 @@ impl<'a> InferenceContext<'a> {
412 fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantId>) { 424 fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantId>) {
413 let path = match path { 425 let path = match path {
414 Some(path) => path, 426 Some(path) => path,
415 None => return (Ty::Unknown, None), 427 None => return (self.err_ty(), None),
416 }; 428 };
417 let resolver = &self.resolver; 429 let resolver = &self.resolver;
418 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); 430 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
@@ -421,30 +433,30 @@ impl<'a> InferenceContext<'a> {
421 let (resolution, unresolved) = 433 let (resolution, unresolved) =
422 match resolver.resolve_path_in_type_ns(self.db.upcast(), path.mod_path()) { 434 match resolver.resolve_path_in_type_ns(self.db.upcast(), path.mod_path()) {
423 Some(it) => it, 435 Some(it) => it,
424 None => return (Ty::Unknown, None), 436 None => return (self.err_ty(), None),
425 }; 437 };
426 return match resolution { 438 return match resolution {
427 TypeNs::AdtId(AdtId::StructId(strukt)) => { 439 TypeNs::AdtId(AdtId::StructId(strukt)) => {
428 let substs = Ty::substs_from_path(&ctx, path, strukt.into(), true); 440 let substs = ctx.substs_from_path(path, strukt.into(), true);
429 let ty = self.db.ty(strukt.into()); 441 let ty = self.db.ty(strukt.into());
430 let ty = self.insert_type_vars(ty.subst(&substs)); 442 let ty = self.insert_type_vars(ty.subst(&substs));
431 forbid_unresolved_segments((ty, Some(strukt.into())), unresolved) 443 forbid_unresolved_segments((ty, Some(strukt.into())), unresolved)
432 } 444 }
433 TypeNs::AdtId(AdtId::UnionId(u)) => { 445 TypeNs::AdtId(AdtId::UnionId(u)) => {
434 let substs = Ty::substs_from_path(&ctx, path, u.into(), true); 446 let substs = ctx.substs_from_path(path, u.into(), true);
435 let ty = self.db.ty(u.into()); 447 let ty = self.db.ty(u.into());
436 let ty = self.insert_type_vars(ty.subst(&substs)); 448 let ty = self.insert_type_vars(ty.subst(&substs));
437 forbid_unresolved_segments((ty, Some(u.into())), unresolved) 449 forbid_unresolved_segments((ty, Some(u.into())), unresolved)
438 } 450 }
439 TypeNs::EnumVariantId(var) => { 451 TypeNs::EnumVariantId(var) => {
440 let substs = Ty::substs_from_path(&ctx, path, var.into(), true); 452 let substs = ctx.substs_from_path(path, var.into(), true);
441 let ty = self.db.ty(var.parent.into()); 453 let ty = self.db.ty(var.parent.into());
442 let ty = self.insert_type_vars(ty.subst(&substs)); 454 let ty = self.insert_type_vars(ty.subst(&substs));
443 forbid_unresolved_segments((ty, Some(var.into())), unresolved) 455 forbid_unresolved_segments((ty, Some(var.into())), unresolved)
444 } 456 }
445 TypeNs::SelfType(impl_id) => { 457 TypeNs::SelfType(impl_id) => {
446 let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); 458 let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
447 let substs = Substs::type_params_for_generics(&generics); 459 let substs = Substs::type_params_for_generics(self.db, &generics);
448 let ty = self.db.impl_self_ty(impl_id).subst(&substs); 460 let ty = self.db.impl_self_ty(impl_id).subst(&substs);
449 match unresolved { 461 match unresolved {
450 None => { 462 None => {
@@ -462,11 +474,11 @@ impl<'a> InferenceContext<'a> {
462 } 474 }
463 } 475 }
464 // FIXME potentially resolve assoc type 476 // FIXME potentially resolve assoc type
465 (Ty::Unknown, None) 477 (self.err_ty(), None)
466 } 478 }
467 Some(_) => { 479 Some(_) => {
468 // FIXME diagnostic 480 // FIXME diagnostic
469 (Ty::Unknown, None) 481 (self.err_ty(), None)
470 } 482 }
471 } 483 }
472 } 484 }
@@ -480,15 +492,15 @@ impl<'a> InferenceContext<'a> {
480 } 492 }
481 TypeNs::AdtSelfType(_) => { 493 TypeNs::AdtSelfType(_) => {
482 // FIXME this could happen in array size expressions, once we're checking them 494 // FIXME this could happen in array size expressions, once we're checking them
483 (Ty::Unknown, None) 495 (self.err_ty(), None)
484 } 496 }
485 TypeNs::GenericParam(_) => { 497 TypeNs::GenericParam(_) => {
486 // FIXME potentially resolve assoc type 498 // FIXME potentially resolve assoc type
487 (Ty::Unknown, None) 499 (self.err_ty(), None)
488 } 500 }
489 TypeNs::AdtId(AdtId::EnumId(_)) | TypeNs::BuiltinType(_) | TypeNs::TraitId(_) => { 501 TypeNs::AdtId(AdtId::EnumId(_)) | TypeNs::BuiltinType(_) | TypeNs::TraitId(_) => {
490 // FIXME diagnostic 502 // FIXME diagnostic
491 (Ty::Unknown, None) 503 (self.err_ty(), None)
492 } 504 }
493 }; 505 };
494 506
@@ -500,7 +512,7 @@ impl<'a> InferenceContext<'a> {
500 result 512 result
501 } else { 513 } else {
502 // FIXME diagnostic 514 // FIXME diagnostic
503 (Ty::Unknown, None) 515 (TyKind::Unknown.intern(&Interner), None)
504 } 516 }
505 } 517 }
506 518
@@ -529,7 +541,7 @@ impl<'a> InferenceContext<'a> {
529 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver) 541 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver)
530 .with_impl_trait_mode(ImplTraitLoweringMode::Param); 542 .with_impl_trait_mode(ImplTraitLoweringMode::Param);
531 let param_tys = 543 let param_tys =
532 data.params.iter().map(|type_ref| Ty::from_hir(&ctx, type_ref)).collect::<Vec<_>>(); 544 data.params.iter().map(|type_ref| ctx.lower_ty(type_ref)).collect::<Vec<_>>();
533 for (ty, pat) in param_tys.into_iter().zip(body.params.iter()) { 545 for (ty, pat) in param_tys.into_iter().zip(body.params.iter()) {
534 let ty = self.insert_type_vars(ty); 546 let ty = self.insert_type_vars(ty);
535 let ty = self.normalize_associated_types_in(ty); 547 let ty = self.normalize_associated_types_in(ty);
@@ -711,12 +723,12 @@ impl Expectation {
711 723
712 /// This expresses no expectation on the type. 724 /// This expresses no expectation on the type.
713 fn none() -> Self { 725 fn none() -> Self {
714 Expectation { ty: Ty::Unknown, rvalue_hint: false } 726 Expectation { ty: TyKind::Unknown.intern(&Interner), rvalue_hint: false }
715 } 727 }
716 728
717 fn coercion_target(&self) -> &Ty { 729 fn coercion_target(&self) -> &Ty {
718 if self.rvalue_hint { 730 if self.rvalue_hint {
719 &Ty::Unknown 731 &Ty(TyKind::Unknown)
720 } else { 732 } else {
721 &self.ty 733 &self.ty
722 } 734 }
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs
index 7e8846f27..36670043a 100644
--- a/crates/hir_ty/src/infer/coerce.rs
+++ b/crates/hir_ty/src/infer/coerce.rs
@@ -7,7 +7,7 @@
7use chalk_ir::{Mutability, TyVariableKind}; 7use chalk_ir::{Mutability, TyVariableKind};
8use hir_def::lang_item::LangItemTarget; 8use hir_def::lang_item::LangItemTarget;
9 9
10use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty}; 10use crate::{autoderef, traits::Solution, Interner, Obligation, Substs, TraitRef, Ty, TyKind};
11 11
12use super::{InEnvironment, InferenceContext}; 12use super::{InEnvironment, InferenceContext};
13 13
@@ -33,7 +33,9 @@ impl<'a> InferenceContext<'a> {
33 } else if self.coerce(ty2, ty1) { 33 } else if self.coerce(ty2, ty1) {
34 ty1.clone() 34 ty1.clone()
35 } else { 35 } else {
36 if let (Ty::FnDef(..), Ty::FnDef(..)) = (ty1, ty2) { 36 if let (TyKind::FnDef(..), TyKind::FnDef(..)) =
37 (ty1.interned(&Interner), ty2.interned(&Interner))
38 {
37 cov_mark::hit!(coerce_fn_reification); 39 cov_mark::hit!(coerce_fn_reification);
38 // Special case: two function types. Try to coerce both to 40 // Special case: two function types. Try to coerce both to
39 // pointers to have a chance at getting a match. See 41 // pointers to have a chance at getting a match. See
@@ -51,13 +53,13 @@ impl<'a> InferenceContext<'a> {
51 } 53 }
52 54
53 fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool { 55 fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool {
54 match (&from_ty, to_ty) { 56 match (from_ty.interned(&Interner), to_ty.interned(&Interner)) {
55 // Never type will make type variable to fallback to Never Type instead of Unknown. 57 // Never type will make type variable to fallback to Never Type instead of Unknown.
56 (Ty::Never, Ty::InferenceVar(tv, TyVariableKind::General)) => { 58 (TyKind::Never, TyKind::InferenceVar(tv, TyVariableKind::General)) => {
57 self.table.type_variable_table.set_diverging(*tv, true); 59 self.table.type_variable_table.set_diverging(*tv, true);
58 return true; 60 return true;
59 } 61 }
60 (Ty::Never, _) => return true, 62 (TyKind::Never, _) => return true,
61 63
62 // Trivial cases, this should go after `never` check to 64 // Trivial cases, this should go after `never` check to
63 // avoid infer result type to be never 65 // avoid infer result type to be never
@@ -69,33 +71,33 @@ impl<'a> InferenceContext<'a> {
69 } 71 }
70 72
71 // Pointer weakening and function to pointer 73 // Pointer weakening and function to pointer
72 match (&mut from_ty, to_ty) { 74 match (&mut from_ty.0, to_ty.interned(&Interner)) {
73 // `*mut T` -> `*const T` 75 // `*mut T` -> `*const T`
74 // `&mut T` -> `&T` 76 // `&mut T` -> `&T`
75 (Ty::Raw(m1, ..), Ty::Raw(m2 @ Mutability::Not, ..)) 77 (TyKind::Raw(m1, ..), TyKind::Raw(m2 @ Mutability::Not, ..))
76 | (Ty::Ref(m1, ..), Ty::Ref(m2 @ Mutability::Not, ..)) => { 78 | (TyKind::Ref(m1, ..), TyKind::Ref(m2 @ Mutability::Not, ..)) => {
77 *m1 = *m2; 79 *m1 = *m2;
78 } 80 }
79 // `&T` -> `*const T` 81 // `&T` -> `*const T`
80 // `&mut T` -> `*mut T`/`*const T` 82 // `&mut T` -> `*mut T`/`*const T`
81 (Ty::Ref(.., substs), &Ty::Raw(m2 @ Mutability::Not, ..)) 83 (TyKind::Ref(.., substs), &TyKind::Raw(m2 @ Mutability::Not, ..))
82 | (Ty::Ref(Mutability::Mut, substs), &Ty::Raw(m2, ..)) => { 84 | (TyKind::Ref(Mutability::Mut, substs), &TyKind::Raw(m2, ..)) => {
83 from_ty = Ty::Raw(m2, substs.clone()); 85 from_ty = TyKind::Raw(m2, substs.clone()).intern(&Interner);
84 } 86 }
85 87
86 // Illegal mutability conversion 88 // Illegal mutability conversion
87 (Ty::Raw(Mutability::Not, ..), Ty::Raw(Mutability::Mut, ..)) 89 (TyKind::Raw(Mutability::Not, ..), TyKind::Raw(Mutability::Mut, ..))
88 | (Ty::Ref(Mutability::Not, ..), Ty::Ref(Mutability::Mut, ..)) => return false, 90 | (TyKind::Ref(Mutability::Not, ..), TyKind::Ref(Mutability::Mut, ..)) => return false,
89 91
90 // `{function_type}` -> `fn()` 92 // `{function_type}` -> `fn()`
91 (Ty::FnDef(..), Ty::Function { .. }) => match from_ty.callable_sig(self.db) { 93 (TyKind::FnDef(..), TyKind::Function { .. }) => match from_ty.callable_sig(self.db) {
92 None => return false, 94 None => return false,
93 Some(sig) => { 95 Some(sig) => {
94 from_ty = Ty::fn_ptr(sig); 96 from_ty = Ty::fn_ptr(sig);
95 } 97 }
96 }, 98 },
97 99
98 (Ty::Closure(.., substs), Ty::Function { .. }) => { 100 (TyKind::Closure(.., substs), TyKind::Function { .. }) => {
99 from_ty = substs[0].clone(); 101 from_ty = substs[0].clone();
100 } 102 }
101 103
@@ -107,9 +109,11 @@ impl<'a> InferenceContext<'a> {
107 } 109 }
108 110
109 // Auto Deref if cannot coerce 111 // Auto Deref if cannot coerce
110 match (&from_ty, to_ty) { 112 match (from_ty.interned(&Interner), to_ty.interned(&Interner)) {
111 // FIXME: DerefMut 113 // FIXME: DerefMut
112 (Ty::Ref(_, st1), Ty::Ref(_, st2)) => self.unify_autoderef_behind_ref(&st1[0], &st2[0]), 114 (TyKind::Ref(_, st1), TyKind::Ref(_, st2)) => {
115 self.unify_autoderef_behind_ref(&st1[0], &st2[0])
116 }
113 117
114 // Otherwise, normal unify 118 // Otherwise, normal unify
115 _ => self.unify(&from_ty, to_ty), 119 _ => self.unify(&from_ty, to_ty),
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index 262177ffb..55163c963 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -18,10 +18,11 @@ use crate::{
18 lower::lower_to_chalk_mutability, 18 lower::lower_to_chalk_mutability,
19 method_resolution, op, 19 method_resolution, op,
20 primitive::{self, UintTy}, 20 primitive::{self, UintTy},
21 traits::{FnTrait, InEnvironment}, 21 to_assoc_type_id,
22 traits::{chalk::from_chalk, FnTrait, InEnvironment},
22 utils::{generics, variant_data, Generics}, 23 utils::{generics, variant_data, Generics},
23 AdtId, Binders, CallableDefId, FnPointer, FnSig, Obligation, OpaqueTyId, Rawness, Scalar, 24 AdtId, Binders, CallableDefId, FnPointer, FnSig, Interner, Obligation, Rawness, Scalar, Substs,
24 Substs, TraitRef, Ty, 25 TraitRef, Ty, TyKind,
25}; 26};
26 27
27use super::{ 28use super::{
@@ -57,7 +58,7 @@ impl<'a> InferenceContext<'a> {
57 // Return actual type when type mismatch. 58 // Return actual type when type mismatch.
58 // This is needed for diagnostic when return type mismatch. 59 // This is needed for diagnostic when return type mismatch.
59 ty 60 ty
60 } else if expected.coercion_target() == &Ty::Unknown { 61 } else if expected.coercion_target().is_unknown() {
61 ty 62 ty
62 } else { 63 } else {
63 expected.ty.clone() 64 expected.ty.clone()
@@ -84,7 +85,7 @@ impl<'a> InferenceContext<'a> {
84 arg_tys.push(arg); 85 arg_tys.push(arg);
85 } 86 }
86 let parameters = param_builder.build(); 87 let parameters = param_builder.build();
87 let arg_ty = Ty::Tuple(num_args, parameters); 88 let arg_ty = TyKind::Tuple(num_args, parameters).intern(&Interner);
88 let substs = 89 let substs =
89 Substs::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); 90 Substs::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build();
90 91
@@ -97,8 +98,10 @@ impl<'a> InferenceContext<'a> {
97 }); 98 });
98 if self.db.trait_solve(krate, goal.value).is_some() { 99 if self.db.trait_solve(krate, goal.value).is_some() {
99 self.obligations.push(implements_fn_trait); 100 self.obligations.push(implements_fn_trait);
100 let output_proj_ty = 101 let output_proj_ty = crate::ProjectionTy {
101 crate::ProjectionTy { associated_ty: output_assoc_type, parameters: substs }; 102 associated_ty_id: to_assoc_type_id(output_assoc_type),
103 substitution: substs,
104 };
102 let return_ty = self.normalize_projection_ty(output_proj_ty); 105 let return_ty = self.normalize_projection_ty(output_proj_ty);
103 Some((arg_tys, return_ty)) 106 Some((arg_tys, return_ty))
104 } else { 107 } else {
@@ -116,10 +119,13 @@ impl<'a> InferenceContext<'a> {
116 fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { 119 fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
117 let body = Arc::clone(&self.body); // avoid borrow checker problem 120 let body = Arc::clone(&self.body); // avoid borrow checker problem
118 let ty = match &body[tgt_expr] { 121 let ty = match &body[tgt_expr] {
119 Expr::Missing => Ty::Unknown, 122 Expr::Missing => self.err_ty(),
120 Expr::If { condition, then_branch, else_branch } => { 123 Expr::If { condition, then_branch, else_branch } => {
121 // if let is desugared to match, so this is always simple if 124 // if let is desugared to match, so this is always simple if
122 self.infer_expr(*condition, &Expectation::has_type(Ty::Scalar(Scalar::Bool))); 125 self.infer_expr(
126 *condition,
127 &Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(&Interner)),
128 );
123 129
124 let condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); 130 let condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
125 let mut both_arms_diverge = Diverges::Always; 131 let mut both_arms_diverge = Diverges::Always;
@@ -167,14 +173,15 @@ impl<'a> InferenceContext<'a> {
167 Expr::TryBlock { body } => { 173 Expr::TryBlock { body } => {
168 let _inner = self.infer_expr(*body, expected); 174 let _inner = self.infer_expr(*body, expected);
169 // FIXME should be std::result::Result<{inner}, _> 175 // FIXME should be std::result::Result<{inner}, _>
170 Ty::Unknown 176 self.err_ty()
171 } 177 }
172 Expr::Async { body } => { 178 Expr::Async { body } => {
173 // Use the first type parameter as the output type of future. 179 // Use the first type parameter as the output type of future.
174 // existenail type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType> 180 // existenail type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType>
175 let inner_ty = self.infer_expr(*body, &Expectation::none()); 181 let inner_ty = self.infer_expr(*body, &Expectation::none());
176 let opaque_ty_id = OpaqueTyId::AsyncBlockTypeImplTrait(self.owner, *body); 182 let impl_trait_id = crate::ImplTraitId::AsyncBlockTypeImplTrait(self.owner, *body);
177 Ty::OpaqueType(opaque_ty_id, Substs::single(inner_ty)) 183 let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
184 TyKind::OpaqueType(opaque_ty_id, Substs::single(inner_ty)).intern(&Interner)
178 } 185 }
179 Expr::Loop { body, label } => { 186 Expr::Loop { body, label } => {
180 self.breakables.push(BreakableContext { 187 self.breakables.push(BreakableContext {
@@ -192,17 +199,20 @@ impl<'a> InferenceContext<'a> {
192 if ctxt.may_break { 199 if ctxt.may_break {
193 ctxt.break_ty 200 ctxt.break_ty
194 } else { 201 } else {
195 Ty::Never 202 TyKind::Never.intern(&Interner)
196 } 203 }
197 } 204 }
198 Expr::While { condition, body, label } => { 205 Expr::While { condition, body, label } => {
199 self.breakables.push(BreakableContext { 206 self.breakables.push(BreakableContext {
200 may_break: false, 207 may_break: false,
201 break_ty: Ty::Unknown, 208 break_ty: self.err_ty(),
202 label: label.map(|label| self.body[label].name.clone()), 209 label: label.map(|label| self.body[label].name.clone()),
203 }); 210 });
204 // while let is desugared to a match loop, so this is always simple while 211 // while let is desugared to a match loop, so this is always simple while
205 self.infer_expr(*condition, &Expectation::has_type(Ty::Scalar(Scalar::Bool))); 212 self.infer_expr(
213 *condition,
214 &Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(&Interner)),
215 );
206 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 216 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
207 let _ctxt = self.breakables.pop().expect("breakable stack broken"); 217 let _ctxt = self.breakables.pop().expect("breakable stack broken");
208 // the body may not run, so it diverging doesn't mean we diverge 218 // the body may not run, so it diverging doesn't mean we diverge
@@ -214,7 +224,7 @@ impl<'a> InferenceContext<'a> {
214 224
215 self.breakables.push(BreakableContext { 225 self.breakables.push(BreakableContext {
216 may_break: false, 226 may_break: false,
217 break_ty: Ty::Unknown, 227 break_ty: self.err_ty(),
218 label: label.map(|label| self.body[label].name.clone()), 228 label: label.map(|label| self.body[label].name.clone()),
219 }); 229 });
220 let pat_ty = 230 let pat_ty =
@@ -249,12 +259,15 @@ impl<'a> InferenceContext<'a> {
249 None => self.table.new_type_var(), 259 None => self.table.new_type_var(),
250 }; 260 };
251 sig_tys.push(ret_ty.clone()); 261 sig_tys.push(ret_ty.clone());
252 let sig_ty = Ty::Function(FnPointer { 262 let sig_ty = TyKind::Function(FnPointer {
253 num_args: sig_tys.len() - 1, 263 num_args: sig_tys.len() - 1,
254 sig: FnSig { variadic: false }, 264 sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false },
255 substs: Substs(sig_tys.clone().into()), 265 substs: Substs(sig_tys.clone().into()),
256 }); 266 })
257 let closure_ty = Ty::Closure(self.owner, tgt_expr, Substs::single(sig_ty)); 267 .intern(&Interner);
268 let closure_id = self.db.intern_closure((self.owner, tgt_expr)).into();
269 let closure_ty =
270 TyKind::Closure(closure_id, Substs::single(sig_ty)).intern(&Interner);
258 271
259 // Eagerly try to relate the closure type with the expected 272 // Eagerly try to relate the closure type with the expected
260 // type, otherwise we often won't have enough information to 273 // type, otherwise we often won't have enough information to
@@ -295,7 +308,7 @@ impl<'a> InferenceContext<'a> {
295 args.len(), 308 args.len(),
296 ) 309 )
297 }) 310 })
298 .unwrap_or((Vec::new(), Ty::Unknown)); 311 .unwrap_or((Vec::new(), self.err_ty()));
299 self.register_obligations_for_call(&callee_ty); 312 self.register_obligations_for_call(&callee_ty);
300 self.check_call_arguments(args, &param_tys); 313 self.check_call_arguments(args, &param_tys);
301 self.normalize_associated_types_in(ret_ty) 314 self.normalize_associated_types_in(ret_ty)
@@ -305,8 +318,11 @@ impl<'a> InferenceContext<'a> {
305 Expr::Match { expr, arms } => { 318 Expr::Match { expr, arms } => {
306 let input_ty = self.infer_expr(*expr, &Expectation::none()); 319 let input_ty = self.infer_expr(*expr, &Expectation::none());
307 320
308 let mut result_ty = 321 let mut result_ty = if arms.is_empty() {
309 if arms.is_empty() { Ty::Never } else { self.table.new_type_var() }; 322 TyKind::Never.intern(&Interner)
323 } else {
324 self.table.new_type_var()
325 };
310 326
311 let matchee_diverges = self.diverges; 327 let matchee_diverges = self.diverges;
312 let mut all_arms_diverge = Diverges::Always; 328 let mut all_arms_diverge = Diverges::Always;
@@ -317,7 +333,7 @@ impl<'a> InferenceContext<'a> {
317 if let Some(guard_expr) = arm.guard { 333 if let Some(guard_expr) = arm.guard {
318 self.infer_expr( 334 self.infer_expr(
319 guard_expr, 335 guard_expr,
320 &Expectation::has_type(Ty::Scalar(Scalar::Bool)), 336 &Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(&Interner)),
321 ); 337 );
322 } 338 }
323 339
@@ -333,9 +349,9 @@ impl<'a> InferenceContext<'a> {
333 Expr::Path(p) => { 349 Expr::Path(p) => {
334 // FIXME this could be more efficient... 350 // FIXME this could be more efficient...
335 let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); 351 let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr);
336 self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown) 352 self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(self.err_ty())
337 } 353 }
338 Expr::Continue { .. } => Ty::Never, 354 Expr::Continue { .. } => TyKind::Never.intern(&Interner),
339 Expr::Break { expr, label } => { 355 Expr::Break { expr, label } => {
340 let val_ty = if let Some(expr) = expr { 356 let val_ty = if let Some(expr) = expr {
341 self.infer_expr(*expr, &Expectation::none()) 357 self.infer_expr(*expr, &Expectation::none())
@@ -347,7 +363,7 @@ impl<'a> InferenceContext<'a> {
347 if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) { 363 if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) {
348 ctxt.break_ty.clone() 364 ctxt.break_ty.clone()
349 } else { 365 } else {
350 Ty::Unknown 366 self.err_ty()
351 }; 367 };
352 368
353 let merged_type = self.coerce_merge_branch(&last_ty, &val_ty); 369 let merged_type = self.coerce_merge_branch(&last_ty, &val_ty);
@@ -360,7 +376,7 @@ impl<'a> InferenceContext<'a> {
360 expr: tgt_expr, 376 expr: tgt_expr,
361 }); 377 });
362 } 378 }
363 Ty::Never 379 TyKind::Never.intern(&Interner)
364 } 380 }
365 Expr::Return { expr } => { 381 Expr::Return { expr } => {
366 if let Some(expr) = expr { 382 if let Some(expr) = expr {
@@ -369,14 +385,14 @@ impl<'a> InferenceContext<'a> {
369 let unit = Ty::unit(); 385 let unit = Ty::unit();
370 self.coerce(&unit, &self.return_ty.clone()); 386 self.coerce(&unit, &self.return_ty.clone());
371 } 387 }
372 Ty::Never 388 TyKind::Never.intern(&Interner)
373 } 389 }
374 Expr::Yield { expr } => { 390 Expr::Yield { expr } => {
375 // FIXME: track yield type for coercion 391 // FIXME: track yield type for coercion
376 if let Some(expr) = expr { 392 if let Some(expr) = expr {
377 self.infer_expr(*expr, &Expectation::none()); 393 self.infer_expr(*expr, &Expectation::none());
378 } 394 }
379 Ty::Never 395 TyKind::Never.intern(&Interner)
380 } 396 }
381 Expr::RecordLit { path, fields, spread } => { 397 Expr::RecordLit { path, fields, spread } => {
382 let (ty, def_id) = self.resolve_variant(path.as_ref()); 398 let (ty, def_id) = self.resolve_variant(path.as_ref());
@@ -404,8 +420,9 @@ impl<'a> InferenceContext<'a> {
404 if let Some(field_def) = field_def { 420 if let Some(field_def) = field_def {
405 self.result.record_field_resolutions.insert(field.expr, field_def); 421 self.result.record_field_resolutions.insert(field.expr, field_def);
406 } 422 }
407 let field_ty = field_def 423 let field_ty = field_def.map_or(self.err_ty(), |it| {
408 .map_or(Ty::Unknown, |it| field_types[it.local_id].clone().subst(&substs)); 424 field_types[it.local_id].clone().subst(&substs)
425 });
409 self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty)); 426 self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty));
410 } 427 }
411 if let Some(expr) = spread { 428 if let Some(expr) = spread {
@@ -424,27 +441,33 @@ impl<'a> InferenceContext<'a> {
424 environment: self.trait_env.clone(), 441 environment: self.trait_env.clone(),
425 }, 442 },
426 ) 443 )
427 .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) { 444 .find_map(|derefed_ty| {
428 Ty::Tuple(_, substs) => { 445 match canonicalized.decanonicalize_ty(derefed_ty.value).interned(&Interner) {
429 name.as_tuple_index().and_then(|idx| substs.0.get(idx).cloned()) 446 TyKind::Tuple(_, substs) => {
430 } 447 name.as_tuple_index().and_then(|idx| substs.0.get(idx).cloned())
431 Ty::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { 448 }
432 self.db.struct_data(s).variant_data.field(name).map(|local_id| { 449 TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => {
433 let field = FieldId { parent: s.into(), local_id }; 450 self.db.struct_data(*s).variant_data.field(name).map(|local_id| {
434 self.write_field_resolution(tgt_expr, field); 451 let field = FieldId { parent: (*s).into(), local_id };
435 self.db.field_types(s.into())[field.local_id].clone().subst(&parameters) 452 self.write_field_resolution(tgt_expr, field);
436 }) 453 self.db.field_types((*s).into())[field.local_id]
437 } 454 .clone()
438 Ty::Adt(AdtId(hir_def::AdtId::UnionId(u)), parameters) => { 455 .subst(&parameters)
439 self.db.union_data(u).variant_data.field(name).map(|local_id| { 456 })
440 let field = FieldId { parent: u.into(), local_id }; 457 }
441 self.write_field_resolution(tgt_expr, field); 458 TyKind::Adt(AdtId(hir_def::AdtId::UnionId(u)), parameters) => {
442 self.db.field_types(u.into())[field.local_id].clone().subst(&parameters) 459 self.db.union_data(*u).variant_data.field(name).map(|local_id| {
443 }) 460 let field = FieldId { parent: (*u).into(), local_id };
461 self.write_field_resolution(tgt_expr, field);
462 self.db.field_types((*u).into())[field.local_id]
463 .clone()
464 .subst(&parameters)
465 })
466 }
467 _ => None,
444 } 468 }
445 _ => None,
446 }) 469 })
447 .unwrap_or(Ty::Unknown); 470 .unwrap_or(self.err_ty());
448 let ty = self.insert_type_vars(ty); 471 let ty = self.insert_type_vars(ty);
449 self.normalize_associated_types_in(ty) 472 self.normalize_associated_types_in(ty)
450 } 473 }
@@ -481,9 +504,10 @@ impl<'a> InferenceContext<'a> {
481 }; 504 };
482 let inner_ty = self.infer_expr_inner(*expr, &expectation); 505 let inner_ty = self.infer_expr_inner(*expr, &expectation);
483 match rawness { 506 match rawness {
484 Rawness::RawPtr => Ty::Raw(mutability, Substs::single(inner_ty)), 507 Rawness::RawPtr => TyKind::Raw(mutability, Substs::single(inner_ty)),
485 Rawness::Ref => Ty::Ref(mutability, Substs::single(inner_ty)), 508 Rawness::Ref => TyKind::Ref(mutability, Substs::single(inner_ty)),
486 } 509 }
510 .intern(&Interner)
487 } 511 }
488 Expr::Box { expr } => { 512 Expr::Box { expr } => {
489 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); 513 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
@@ -499,7 +523,7 @@ impl<'a> InferenceContext<'a> {
499 sb = sb.fill(repeat_with(|| self.table.new_type_var())); 523 sb = sb.fill(repeat_with(|| self.table.new_type_var()));
500 Ty::adt_ty(box_, sb.build()) 524 Ty::adt_ty(box_, sb.build())
501 } else { 525 } else {
502 Ty::Unknown 526 self.err_ty()
503 } 527 }
504 } 528 }
505 Expr::UnaryOp { expr, op } => { 529 Expr::UnaryOp { expr, op } => {
@@ -519,31 +543,31 @@ impl<'a> InferenceContext<'a> {
519 Some(derefed_ty) => { 543 Some(derefed_ty) => {
520 canonicalized.decanonicalize_ty(derefed_ty.value) 544 canonicalized.decanonicalize_ty(derefed_ty.value)
521 } 545 }
522 None => Ty::Unknown, 546 None => self.err_ty(),
523 } 547 }
524 } 548 }
525 None => Ty::Unknown, 549 None => self.err_ty(),
526 }, 550 },
527 UnaryOp::Neg => { 551 UnaryOp::Neg => {
528 match &inner_ty { 552 match inner_ty.interned(&Interner) {
529 // Fast path for builtins 553 // Fast path for builtins
530 Ty::Scalar(Scalar::Int(_)) 554 TyKind::Scalar(Scalar::Int(_))
531 | Ty::Scalar(Scalar::Uint(_)) 555 | TyKind::Scalar(Scalar::Uint(_))
532 | Ty::Scalar(Scalar::Float(_)) 556 | TyKind::Scalar(Scalar::Float(_))
533 | Ty::InferenceVar(_, TyVariableKind::Integer) 557 | TyKind::InferenceVar(_, TyVariableKind::Integer)
534 | Ty::InferenceVar(_, TyVariableKind::Float) => inner_ty, 558 | TyKind::InferenceVar(_, TyVariableKind::Float) => inner_ty,
535 // Otherwise we resolve via the std::ops::Neg trait 559 // Otherwise we resolve via the std::ops::Neg trait
536 _ => self 560 _ => self
537 .resolve_associated_type(inner_ty, self.resolve_ops_neg_output()), 561 .resolve_associated_type(inner_ty, self.resolve_ops_neg_output()),
538 } 562 }
539 } 563 }
540 UnaryOp::Not => { 564 UnaryOp::Not => {
541 match &inner_ty { 565 match inner_ty.interned(&Interner) {
542 // Fast path for builtins 566 // Fast path for builtins
543 Ty::Scalar(Scalar::Bool) 567 TyKind::Scalar(Scalar::Bool)
544 | Ty::Scalar(Scalar::Int(_)) 568 | TyKind::Scalar(Scalar::Int(_))
545 | Ty::Scalar(Scalar::Uint(_)) 569 | TyKind::Scalar(Scalar::Uint(_))
546 | Ty::InferenceVar(_, TyVariableKind::Integer) => inner_ty, 570 | TyKind::InferenceVar(_, TyVariableKind::Integer) => inner_ty,
547 // Otherwise we resolve via the std::ops::Not trait 571 // Otherwise we resolve via the std::ops::Not trait
548 _ => self 572 _ => self
549 .resolve_associated_type(inner_ty, self.resolve_ops_not_output()), 573 .resolve_associated_type(inner_ty, self.resolve_ops_not_output()),
@@ -554,7 +578,9 @@ impl<'a> InferenceContext<'a> {
554 Expr::BinaryOp { lhs, rhs, op } => match op { 578 Expr::BinaryOp { lhs, rhs, op } => match op {
555 Some(op) => { 579 Some(op) => {
556 let lhs_expectation = match op { 580 let lhs_expectation = match op {
557 BinaryOp::LogicOp(..) => Expectation::has_type(Ty::Scalar(Scalar::Bool)), 581 BinaryOp::LogicOp(..) => {
582 Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(&Interner))
583 }
558 _ => Expectation::none(), 584 _ => Expectation::none(),
559 }; 585 };
560 let lhs_ty = self.infer_expr(*lhs, &lhs_expectation); 586 let lhs_ty = self.infer_expr(*lhs, &lhs_expectation);
@@ -563,7 +589,7 @@ impl<'a> InferenceContext<'a> {
563 589
564 let ret = op::binary_op_return_ty(*op, lhs_ty.clone(), rhs_ty.clone()); 590 let ret = op::binary_op_return_ty(*op, lhs_ty.clone(), rhs_ty.clone());
565 591
566 if ret == Ty::Unknown { 592 if ret.is_unknown() {
567 cov_mark::hit!(infer_expr_inner_binary_operator_overload); 593 cov_mark::hit!(infer_expr_inner_binary_operator_overload);
568 594
569 self.resolve_associated_type_with_params( 595 self.resolve_associated_type_with_params(
@@ -575,7 +601,7 @@ impl<'a> InferenceContext<'a> {
575 ret 601 ret
576 } 602 }
577 } 603 }
578 _ => Ty::Unknown, 604 _ => self.err_ty(),
579 }, 605 },
580 Expr::Range { lhs, rhs, range_type } => { 606 Expr::Range { lhs, rhs, range_type } => {
581 let lhs_ty = lhs.map(|e| self.infer_expr_inner(e, &Expectation::none())); 607 let lhs_ty = lhs.map(|e| self.infer_expr_inner(e, &Expectation::none()));
@@ -586,33 +612,33 @@ impl<'a> InferenceContext<'a> {
586 match (range_type, lhs_ty, rhs_ty) { 612 match (range_type, lhs_ty, rhs_ty) {
587 (RangeOp::Exclusive, None, None) => match self.resolve_range_full() { 613 (RangeOp::Exclusive, None, None) => match self.resolve_range_full() {
588 Some(adt) => Ty::adt_ty(adt, Substs::empty()), 614 Some(adt) => Ty::adt_ty(adt, Substs::empty()),
589 None => Ty::Unknown, 615 None => self.err_ty(),
590 }, 616 },
591 (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() { 617 (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() {
592 Some(adt) => Ty::adt_ty(adt, Substs::single(ty)), 618 Some(adt) => Ty::adt_ty(adt, Substs::single(ty)),
593 None => Ty::Unknown, 619 None => self.err_ty(),
594 }, 620 },
595 (RangeOp::Inclusive, None, Some(ty)) => { 621 (RangeOp::Inclusive, None, Some(ty)) => {
596 match self.resolve_range_to_inclusive() { 622 match self.resolve_range_to_inclusive() {
597 Some(adt) => Ty::adt_ty(adt, Substs::single(ty)), 623 Some(adt) => Ty::adt_ty(adt, Substs::single(ty)),
598 None => Ty::Unknown, 624 None => self.err_ty(),
599 } 625 }
600 } 626 }
601 (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() { 627 (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() {
602 Some(adt) => Ty::adt_ty(adt, Substs::single(ty)), 628 Some(adt) => Ty::adt_ty(adt, Substs::single(ty)),
603 None => Ty::Unknown, 629 None => self.err_ty(),
604 }, 630 },
605 (RangeOp::Inclusive, Some(_), Some(ty)) => { 631 (RangeOp::Inclusive, Some(_), Some(ty)) => {
606 match self.resolve_range_inclusive() { 632 match self.resolve_range_inclusive() {
607 Some(adt) => Ty::adt_ty(adt, Substs::single(ty)), 633 Some(adt) => Ty::adt_ty(adt, Substs::single(ty)),
608 None => Ty::Unknown, 634 None => self.err_ty(),
609 } 635 }
610 } 636 }
611 (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() { 637 (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() {
612 Some(adt) => Ty::adt_ty(adt, Substs::single(ty)), 638 Some(adt) => Ty::adt_ty(adt, Substs::single(ty)),
613 None => Ty::Unknown, 639 None => self.err_ty(),
614 }, 640 },
615 (RangeOp::Inclusive, _, None) => Ty::Unknown, 641 (RangeOp::Inclusive, _, None) => self.err_ty(),
616 } 642 }
617 } 643 }
618 Expr::Index { base, index } => { 644 Expr::Index { base, index } => {
@@ -631,19 +657,19 @@ impl<'a> InferenceContext<'a> {
631 index_trait, 657 index_trait,
632 ); 658 );
633 let self_ty = 659 let self_ty =
634 self_ty.map_or(Ty::Unknown, |t| canonicalized.decanonicalize_ty(t.value)); 660 self_ty.map_or(self.err_ty(), |t| canonicalized.decanonicalize_ty(t.value));
635 self.resolve_associated_type_with_params( 661 self.resolve_associated_type_with_params(
636 self_ty, 662 self_ty,
637 self.resolve_ops_index_output(), 663 self.resolve_ops_index_output(),
638 &[index_ty], 664 &[index_ty],
639 ) 665 )
640 } else { 666 } else {
641 Ty::Unknown 667 self.err_ty()
642 } 668 }
643 } 669 }
644 Expr::Tuple { exprs } => { 670 Expr::Tuple { exprs } => {
645 let mut tys = match &expected.ty { 671 let mut tys = match expected.ty.interned(&Interner) {
646 Ty::Tuple(_, substs) => substs 672 TyKind::Tuple(_, substs) => substs
647 .iter() 673 .iter()
648 .cloned() 674 .cloned()
649 .chain(repeat_with(|| self.table.new_type_var())) 675 .chain(repeat_with(|| self.table.new_type_var()))
@@ -656,11 +682,11 @@ impl<'a> InferenceContext<'a> {
656 self.infer_expr_coerce(*expr, &Expectation::has_type(ty.clone())); 682 self.infer_expr_coerce(*expr, &Expectation::has_type(ty.clone()));
657 } 683 }
658 684
659 Ty::Tuple(tys.len(), Substs(tys.into())) 685 TyKind::Tuple(tys.len(), Substs(tys.into())).intern(&Interner)
660 } 686 }
661 Expr::Array(array) => { 687 Expr::Array(array) => {
662 let elem_ty = match &expected.ty { 688 let elem_ty = match expected.ty.interned(&Interner) {
663 Ty::Array(st) | Ty::Slice(st) => st.as_single().clone(), 689 TyKind::Array(st) | TyKind::Slice(st) => st.as_single().clone(),
664 _ => self.table.new_type_var(), 690 _ => self.table.new_type_var(),
665 }; 691 };
666 692
@@ -677,43 +703,51 @@ impl<'a> InferenceContext<'a> {
677 ); 703 );
678 self.infer_expr( 704 self.infer_expr(
679 *repeat, 705 *repeat,
680 &Expectation::has_type(Ty::Scalar(Scalar::Uint(UintTy::Usize))), 706 &Expectation::has_type(
707 TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner),
708 ),
681 ); 709 );
682 } 710 }
683 } 711 }
684 712
685 Ty::Array(Substs::single(elem_ty)) 713 TyKind::Array(Substs::single(elem_ty)).intern(&Interner)
686 } 714 }
687 Expr::Literal(lit) => match lit { 715 Expr::Literal(lit) => match lit {
688 Literal::Bool(..) => Ty::Scalar(Scalar::Bool), 716 Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
689 Literal::String(..) => Ty::Ref(Mutability::Not, Substs::single(Ty::Str)), 717 Literal::String(..) => {
718 TyKind::Ref(Mutability::Not, Substs::single(TyKind::Str.intern(&Interner)))
719 .intern(&Interner)
720 }
690 Literal::ByteString(..) => { 721 Literal::ByteString(..) => {
691 let byte_type = Ty::Scalar(Scalar::Uint(UintTy::U8)); 722 let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner);
692 let array_type = Ty::Array(Substs::single(byte_type)); 723 let array_type = TyKind::Array(Substs::single(byte_type)).intern(&Interner);
693 Ty::Ref(Mutability::Not, Substs::single(array_type)) 724 TyKind::Ref(Mutability::Not, Substs::single(array_type)).intern(&Interner)
694 } 725 }
695 Literal::Char(..) => Ty::Scalar(Scalar::Char), 726 Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner),
696 Literal::Int(_v, ty) => match ty { 727 Literal::Int(_v, ty) => match ty {
697 Some(int_ty) => { 728 Some(int_ty) => {
698 Ty::Scalar(Scalar::Int(primitive::int_ty_from_builtin(*int_ty))) 729 TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(*int_ty)))
730 .intern(&Interner)
699 } 731 }
700 None => self.table.new_integer_var(), 732 None => self.table.new_integer_var(),
701 }, 733 },
702 Literal::Uint(_v, ty) => match ty { 734 Literal::Uint(_v, ty) => match ty {
703 Some(int_ty) => { 735 Some(int_ty) => {
704 Ty::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(*int_ty))) 736 TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(*int_ty)))
737 .intern(&Interner)
705 } 738 }
706 None => self.table.new_integer_var(), 739 None => self.table.new_integer_var(),
707 }, 740 },
708 Literal::Float(_v, ty) => match ty { 741 Literal::Float(_v, ty) => match ty {
709 Some(float_ty) => { 742 Some(float_ty) => {
710 Ty::Scalar(Scalar::Float(primitive::float_ty_from_builtin(*float_ty))) 743 TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(*float_ty)))
744 .intern(&Interner)
711 } 745 }
712 None => self.table.new_float_var(), 746 None => self.table.new_float_var(),
713 }, 747 },
714 }, 748 },
715 }; 749 };
716 // use a new type variable if we got Ty::Unknown here 750 // use a new type variable if we got unknown here
717 let ty = self.insert_type_vars_shallow(ty); 751 let ty = self.insert_type_vars_shallow(ty);
718 let ty = self.resolve_ty_as_possible(ty); 752 let ty = self.resolve_ty_as_possible(ty);
719 self.write_expr_ty(tgt_expr, ty.clone()); 753 self.write_expr_ty(tgt_expr, ty.clone());
@@ -730,7 +764,7 @@ impl<'a> InferenceContext<'a> {
730 match stmt { 764 match stmt {
731 Statement::Let { pat, type_ref, initializer } => { 765 Statement::Let { pat, type_ref, initializer } => {
732 let decl_ty = 766 let decl_ty =
733 type_ref.as_ref().map(|tr| self.make_ty(tr)).unwrap_or(Ty::Unknown); 767 type_ref.as_ref().map(|tr| self.make_ty(tr)).unwrap_or(self.err_ty());
734 768
735 // Always use the declared type when specified 769 // Always use the declared type when specified
736 let mut ty = decl_ty.clone(); 770 let mut ty = decl_ty.clone();
@@ -738,7 +772,7 @@ impl<'a> InferenceContext<'a> {
738 if let Some(expr) = initializer { 772 if let Some(expr) = initializer {
739 let actual_ty = 773 let actual_ty =
740 self.infer_expr_coerce(*expr, &Expectation::has_type(decl_ty.clone())); 774 self.infer_expr_coerce(*expr, &Expectation::has_type(decl_ty.clone()));
741 if decl_ty == Ty::Unknown { 775 if decl_ty.is_unknown() {
742 ty = actual_ty; 776 ty = actual_ty;
743 } 777 }
744 } 778 }
@@ -802,7 +836,7 @@ impl<'a> InferenceContext<'a> {
802 self.write_method_resolution(tgt_expr, func); 836 self.write_method_resolution(tgt_expr, func);
803 (ty, self.db.value_ty(func.into()), Some(generics(self.db.upcast(), func.into()))) 837 (ty, self.db.value_ty(func.into()), Some(generics(self.db.upcast(), func.into())))
804 } 838 }
805 None => (receiver_ty, Binders::new(0, Ty::Unknown), None), 839 None => (receiver_ty, Binders::new(0, self.err_ty()), None),
806 }; 840 };
807 let substs = self.substs_for_method_call(def_generics, generic_args, &derefed_receiver_ty); 841 let substs = self.substs_for_method_call(def_generics, generic_args, &derefed_receiver_ty);
808 let method_ty = method_ty.subst(&substs); 842 let method_ty = method_ty.subst(&substs);
@@ -813,15 +847,17 @@ impl<'a> InferenceContext<'a> {
813 if !sig.params().is_empty() { 847 if !sig.params().is_empty() {
814 (sig.params()[0].clone(), sig.params()[1..].to_vec(), sig.ret().clone()) 848 (sig.params()[0].clone(), sig.params()[1..].to_vec(), sig.ret().clone())
815 } else { 849 } else {
816 (Ty::Unknown, Vec::new(), sig.ret().clone()) 850 (self.err_ty(), Vec::new(), sig.ret().clone())
817 } 851 }
818 } 852 }
819 None => (Ty::Unknown, Vec::new(), Ty::Unknown), 853 None => (self.err_ty(), Vec::new(), self.err_ty()),
820 }; 854 };
821 // Apply autoref so the below unification works correctly 855 // Apply autoref so the below unification works correctly
822 // FIXME: return correct autorefs from lookup_method 856 // FIXME: return correct autorefs from lookup_method
823 let actual_receiver_ty = match expected_receiver_ty.as_reference() { 857 let actual_receiver_ty = match expected_receiver_ty.as_reference() {
824 Some((_, mutability)) => Ty::Ref(mutability, Substs::single(derefed_receiver_ty)), 858 Some((_, mutability)) => {
859 TyKind::Ref(mutability, Substs::single(derefed_receiver_ty)).intern(&Interner)
860 }
825 _ => derefed_receiver_ty, 861 _ => derefed_receiver_ty,
826 }; 862 };
827 self.unify(&expected_receiver_ty, &actual_receiver_ty); 863 self.unify(&expected_receiver_ty, &actual_receiver_ty);
@@ -837,7 +873,7 @@ impl<'a> InferenceContext<'a> {
837 // that we have more information about the types of arguments when we 873 // that we have more information about the types of arguments when we
838 // type-check the functions. This isn't really the right way to do this. 874 // type-check the functions. This isn't really the right way to do this.
839 for &check_closures in &[false, true] { 875 for &check_closures in &[false, true] {
840 let param_iter = param_tys.iter().cloned().chain(repeat(Ty::Unknown)); 876 let param_iter = param_tys.iter().cloned().chain(repeat(self.err_ty()));
841 for (&arg, param_ty) in args.iter().zip(param_iter) { 877 for (&arg, param_ty) in args.iter().zip(param_iter) {
842 let is_closure = matches!(&self.body[arg], Expr::Lambda { .. }); 878 let is_closure = matches!(&self.body[arg], Expr::Lambda { .. });
843 if is_closure != check_closures { 879 if is_closure != check_closures {
@@ -867,7 +903,7 @@ impl<'a> InferenceContext<'a> {
867 if param.provenance == hir_def::generics::TypeParamProvenance::TraitSelf { 903 if param.provenance == hir_def::generics::TypeParamProvenance::TraitSelf {
868 substs.push(receiver_ty.clone()); 904 substs.push(receiver_ty.clone());
869 } else { 905 } else {
870 substs.push(Ty::Unknown); 906 substs.push(self.err_ty());
871 } 907 }
872 } 908 }
873 } 909 }
@@ -891,14 +927,15 @@ impl<'a> InferenceContext<'a> {
891 }; 927 };
892 let supplied_params = substs.len(); 928 let supplied_params = substs.len();
893 for _ in supplied_params..total_len { 929 for _ in supplied_params..total_len {
894 substs.push(Ty::Unknown); 930 substs.push(self.err_ty());
895 } 931 }
896 assert_eq!(substs.len(), total_len); 932 assert_eq!(substs.len(), total_len);
897 Substs(substs.into()) 933 Substs(substs.into())
898 } 934 }
899 935
900 fn register_obligations_for_call(&mut self, callable_ty: &Ty) { 936 fn register_obligations_for_call(&mut self, callable_ty: &Ty) {
901 if let &Ty::FnDef(def, ref parameters) = callable_ty { 937 if let TyKind::FnDef(fn_def, parameters) = callable_ty.interned(&Interner) {
938 let def: CallableDefId = from_chalk(self.db, *fn_def);
902 let generic_predicates = self.db.generic_predicates(def.into()); 939 let generic_predicates = self.db.generic_predicates(def.into());
903 for predicate in generic_predicates.iter() { 940 for predicate in generic_predicates.iter() {
904 let predicate = predicate.clone().subst(parameters); 941 let predicate = predicate.clone().subst(parameters);
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index a0ac8d80f..a16755cda 100644
--- a/crates/hir_ty/src/infer/pat.rs
+++ b/crates/hir_ty/src/infer/pat.rs
@@ -12,7 +12,7 @@ use hir_def::{
12use hir_expand::name::Name; 12use hir_expand::name::Name;
13 13
14use super::{BindingMode, Expectation, InferenceContext}; 14use super::{BindingMode, Expectation, InferenceContext};
15use crate::{lower::lower_to_chalk_mutability, utils::variant_data, Substs, Ty}; 15use crate::{lower::lower_to_chalk_mutability, utils::variant_data, Interner, Substs, Ty, TyKind};
16 16
17impl<'a> InferenceContext<'a> { 17impl<'a> InferenceContext<'a> {
18 fn infer_tuple_struct_pat( 18 fn infer_tuple_struct_pat(
@@ -46,7 +46,7 @@ impl<'a> InferenceContext<'a> {
46 let expected_ty = var_data 46 let expected_ty = var_data
47 .as_ref() 47 .as_ref()
48 .and_then(|d| d.field(&Name::new_tuple_field(i))) 48 .and_then(|d| d.field(&Name::new_tuple_field(i)))
49 .map_or(Ty::Unknown, |field| field_tys[field].clone().subst(&substs)); 49 .map_or(self.err_ty(), |field| field_tys[field].clone().subst(&substs));
50 let expected_ty = self.normalize_associated_types_in(expected_ty); 50 let expected_ty = self.normalize_associated_types_in(expected_ty);
51 self.infer_pat(subpat, &expected_ty, default_bm); 51 self.infer_pat(subpat, &expected_ty, default_bm);
52 } 52 }
@@ -80,8 +80,8 @@ impl<'a> InferenceContext<'a> {
80 self.result.record_pat_field_resolutions.insert(subpat.pat, field_def); 80 self.result.record_pat_field_resolutions.insert(subpat.pat, field_def);
81 } 81 }
82 82
83 let expected_ty = 83 let expected_ty = matching_field
84 matching_field.map_or(Ty::Unknown, |field| field_tys[field].clone().subst(&substs)); 84 .map_or(self.err_ty(), |field| field_tys[field].clone().subst(&substs));
85 let expected_ty = self.normalize_associated_types_in(expected_ty); 85 let expected_ty = self.normalize_associated_types_in(expected_ty);
86 self.infer_pat(subpat.pat, &expected_ty, default_bm); 86 self.infer_pat(subpat.pat, &expected_ty, default_bm);
87 } 87 }
@@ -129,7 +129,8 @@ impl<'a> InferenceContext<'a> {
129 None => (&args[..], &[][..]), 129 None => (&args[..], &[][..]),
130 }; 130 };
131 let n_uncovered_patterns = expectations.len().saturating_sub(args.len()); 131 let n_uncovered_patterns = expectations.len().saturating_sub(args.len());
132 let mut expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown)); 132 let err_ty = self.err_ty();
133 let mut expectations_iter = expectations.iter().chain(repeat(&err_ty));
133 let mut infer_pat = |(&pat, ty)| self.infer_pat(pat, ty, default_bm); 134 let mut infer_pat = |(&pat, ty)| self.infer_pat(pat, ty, default_bm);
134 135
135 let mut inner_tys = Vec::with_capacity(n_uncovered_patterns + args.len()); 136 let mut inner_tys = Vec::with_capacity(n_uncovered_patterns + args.len());
@@ -137,7 +138,7 @@ impl<'a> InferenceContext<'a> {
137 inner_tys.extend(expectations_iter.by_ref().take(n_uncovered_patterns).cloned()); 138 inner_tys.extend(expectations_iter.by_ref().take(n_uncovered_patterns).cloned());
138 inner_tys.extend(post.iter().zip(expectations_iter).map(infer_pat)); 139 inner_tys.extend(post.iter().zip(expectations_iter).map(infer_pat));
139 140
140 Ty::Tuple(inner_tys.len(), Substs(inner_tys.into())) 141 TyKind::Tuple(inner_tys.len(), Substs(inner_tys.into())).intern(&Interner)
141 } 142 }
142 Pat::Or(ref pats) => { 143 Pat::Or(ref pats) => {
143 if let Some((first_pat, rest)) = pats.split_first() { 144 if let Some((first_pat, rest)) = pats.split_first() {
@@ -147,7 +148,7 @@ impl<'a> InferenceContext<'a> {
147 } 148 }
148 ty 149 ty
149 } else { 150 } else {
150 Ty::Unknown 151 self.err_ty()
151 } 152 }
152 } 153 }
153 Pat::Ref { pat, mutability } => { 154 Pat::Ref { pat, mutability } => {
@@ -159,10 +160,10 @@ impl<'a> InferenceContext<'a> {
159 } 160 }
160 inner_ty 161 inner_ty
161 } 162 }
162 _ => &Ty::Unknown, 163 _ => &Ty(TyKind::Unknown),
163 }; 164 };
164 let subty = self.infer_pat(*pat, expectation, default_bm); 165 let subty = self.infer_pat(*pat, expectation, default_bm);
165 Ty::Ref(mutability, Substs::single(subty)) 166 TyKind::Ref(mutability, Substs::single(subty)).intern(&Interner)
166 } 167 }
167 Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat( 168 Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat(
168 p.as_ref(), 169 p.as_ref(),
@@ -178,7 +179,7 @@ impl<'a> InferenceContext<'a> {
178 Pat::Path(path) => { 179 Pat::Path(path) => {
179 // FIXME use correct resolver for the surrounding expression 180 // FIXME use correct resolver for the surrounding expression
180 let resolver = self.resolver.clone(); 181 let resolver = self.resolver.clone();
181 self.infer_path(&resolver, &path, pat.into()).unwrap_or(Ty::Unknown) 182 self.infer_path(&resolver, &path, pat.into()).unwrap_or(self.err_ty())
182 } 183 }
183 Pat::Bind { mode, name: _, subpat } => { 184 Pat::Bind { mode, name: _, subpat } => {
184 let mode = if mode == &BindingAnnotation::Unannotated { 185 let mode = if mode == &BindingAnnotation::Unannotated {
@@ -195,7 +196,7 @@ impl<'a> InferenceContext<'a> {
195 196
196 let bound_ty = match mode { 197 let bound_ty = match mode {
197 BindingMode::Ref(mutability) => { 198 BindingMode::Ref(mutability) => {
198 Ty::Ref(mutability, Substs::single(inner_ty.clone())) 199 TyKind::Ref(mutability, Substs::single(inner_ty.clone())).intern(&Interner)
199 } 200 }
200 BindingMode::Move => inner_ty.clone(), 201 BindingMode::Move => inner_ty.clone(),
201 }; 202 };
@@ -204,17 +205,17 @@ impl<'a> InferenceContext<'a> {
204 return inner_ty; 205 return inner_ty;
205 } 206 }
206 Pat::Slice { prefix, slice, suffix } => { 207 Pat::Slice { prefix, slice, suffix } => {
207 let (container_ty, elem_ty): (fn(_) -> _, _) = match &expected { 208 let (container_ty, elem_ty): (fn(_) -> _, _) = match expected.interned(&Interner) {
208 Ty::Array(st) => (Ty::Array, st.as_single().clone()), 209 TyKind::Array(st) => (TyKind::Array, st.as_single().clone()),
209 Ty::Slice(st) => (Ty::Slice, st.as_single().clone()), 210 TyKind::Slice(st) => (TyKind::Slice, st.as_single().clone()),
210 _ => (Ty::Slice, Ty::Unknown), 211 _ => (TyKind::Slice, self.err_ty()),
211 }; 212 };
212 213
213 for pat_id in prefix.iter().chain(suffix) { 214 for pat_id in prefix.iter().chain(suffix) {
214 self.infer_pat(*pat_id, &elem_ty, default_bm); 215 self.infer_pat(*pat_id, &elem_ty, default_bm);
215 } 216 }
216 217
217 let pat_ty = container_ty(Substs::single(elem_ty)); 218 let pat_ty = container_ty(Substs::single(elem_ty)).intern(&Interner);
218 if let Some(slice_pat_id) = slice { 219 if let Some(slice_pat_id) = slice {
219 self.infer_pat(*slice_pat_id, &pat_ty, default_bm); 220 self.infer_pat(*slice_pat_id, &pat_ty, default_bm);
220 } 221 }
@@ -232,20 +233,20 @@ impl<'a> InferenceContext<'a> {
232 Some(box_adt) => { 233 Some(box_adt) => {
233 let inner_expected = match expected.as_adt() { 234 let inner_expected = match expected.as_adt() {
234 Some((adt, substs)) if adt == box_adt => substs.as_single(), 235 Some((adt, substs)) if adt == box_adt => substs.as_single(),
235 _ => &Ty::Unknown, 236 _ => &Ty(TyKind::Unknown),
236 }; 237 };
237 238
238 let inner_ty = self.infer_pat(*inner, inner_expected, default_bm); 239 let inner_ty = self.infer_pat(*inner, inner_expected, default_bm);
239 Ty::adt_ty(box_adt, Substs::single(inner_ty)) 240 Ty::adt_ty(box_adt, Substs::single(inner_ty))
240 } 241 }
241 None => Ty::Unknown, 242 None => self.err_ty(),
242 }, 243 },
243 Pat::ConstBlock(expr) => { 244 Pat::ConstBlock(expr) => {
244 self.infer_expr(*expr, &Expectation::has_type(expected.clone())) 245 self.infer_expr(*expr, &Expectation::has_type(expected.clone()))
245 } 246 }
246 Pat::Missing => Ty::Unknown, 247 Pat::Missing => self.err_ty(),
247 }; 248 };
248 // use a new type variable if we got Ty::Unknown here 249 // use a new type variable if we got error type here
249 let ty = self.insert_type_vars_shallow(ty); 250 let ty = self.insert_type_vars_shallow(ty);
250 if !self.unify(&ty, expected) { 251 if !self.unify(&ty, expected) {
251 // FIXME record mismatch, we need to change the type of self.type_mismatches for that 252 // FIXME record mismatch, we need to change the type of self.type_mismatches for that
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs
index ae3554bac..af108fb6c 100644
--- a/crates/hir_ty/src/infer/path.rs
+++ b/crates/hir_ty/src/infer/path.rs
@@ -9,7 +9,7 @@ use hir_def::{
9}; 9};
10use hir_expand::name::Name; 10use hir_expand::name::Name;
11 11
12use crate::{method_resolution, Substs, Ty, ValueTyDefId}; 12use crate::{method_resolution, Interner, Substs, Ty, TyKind, ValueTyDefId};
13 13
14use super::{ExprOrPatId, InferenceContext, TraitRef}; 14use super::{ExprOrPatId, InferenceContext, TraitRef};
15 15
@@ -40,7 +40,7 @@ impl<'a> InferenceContext<'a> {
40 let ty = self.make_ty(type_ref); 40 let ty = self.make_ty(type_ref);
41 let remaining_segments_for_ty = path.segments().take(path.segments().len() - 1); 41 let remaining_segments_for_ty = path.segments().take(path.segments().len() - 1);
42 let ctx = crate::lower::TyLoweringContext::new(self.db, &resolver); 42 let ctx = crate::lower::TyLoweringContext::new(self.db, &resolver);
43 let (ty, _) = Ty::from_type_relative_path(&ctx, ty, None, remaining_segments_for_ty); 43 let (ty, _) = ctx.lower_ty_relative_path(ty, None, remaining_segments_for_ty);
44 self.resolve_ty_assoc_item( 44 self.resolve_ty_assoc_item(
45 ty, 45 ty,
46 &path.segments().last().expect("path had at least one segment").name, 46 &path.segments().last().expect("path had at least one segment").name,
@@ -79,7 +79,7 @@ impl<'a> InferenceContext<'a> {
79 } 79 }
80 ValueNs::ImplSelf(impl_id) => { 80 ValueNs::ImplSelf(impl_id) => {
81 let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); 81 let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
82 let substs = Substs::type_params_for_generics(&generics); 82 let substs = Substs::type_params_for_generics(self.db, &generics);
83 let ty = self.db.impl_self_ty(impl_id).subst(&substs); 83 let ty = self.db.impl_self_ty(impl_id).subst(&substs);
84 if let Some((AdtId::StructId(struct_id), substs)) = ty.as_adt() { 84 if let Some((AdtId::StructId(struct_id), substs)) = ty.as_adt() {
85 let ty = self.db.value_ty(struct_id.into()).subst(&substs); 85 let ty = self.db.value_ty(struct_id.into()).subst(&substs);
@@ -96,7 +96,7 @@ impl<'a> InferenceContext<'a> {
96 // self_subst is just for the parent 96 // self_subst is just for the parent
97 let parent_substs = self_subst.unwrap_or_else(Substs::empty); 97 let parent_substs = self_subst.unwrap_or_else(Substs::empty);
98 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); 98 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
99 let substs = Ty::substs_from_path(&ctx, path, typable, true); 99 let substs = ctx.substs_from_path(path, typable, true);
100 let full_substs = Substs::builder(substs.len()) 100 let full_substs = Substs::builder(substs.len())
101 .use_parent_substs(&parent_substs) 101 .use_parent_substs(&parent_substs)
102 .fill(substs.0[parent_substs.len()..].iter().cloned()) 102 .fill(substs.0[parent_substs.len()..].iter().cloned())
@@ -126,7 +126,8 @@ impl<'a> InferenceContext<'a> {
126 let segment = 126 let segment =
127 remaining_segments.last().expect("there should be at least one segment here"); 127 remaining_segments.last().expect("there should be at least one segment here");
128 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); 128 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
129 let trait_ref = TraitRef::from_resolved_path(&ctx, trait_, resolved_segment, None); 129 let trait_ref =
130 ctx.lower_trait_ref_from_resolved_path(trait_, resolved_segment, None);
130 self.resolve_trait_assoc_item(trait_ref, segment, id) 131 self.resolve_trait_assoc_item(trait_ref, segment, id)
131 } 132 }
132 (def, _) => { 133 (def, _) => {
@@ -137,14 +138,13 @@ impl<'a> InferenceContext<'a> {
137 let remaining_segments_for_ty = 138 let remaining_segments_for_ty =
138 remaining_segments.take(remaining_segments.len() - 1); 139 remaining_segments.take(remaining_segments.len() - 1);
139 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); 140 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
140 let (ty, _) = Ty::from_partly_resolved_hir_path( 141 let (ty, _) = ctx.lower_partly_resolved_path(
141 &ctx,
142 def, 142 def,
143 resolved_segment, 143 resolved_segment,
144 remaining_segments_for_ty, 144 remaining_segments_for_ty,
145 true, 145 true,
146 ); 146 );
147 if let Ty::Unknown = ty { 147 if let TyKind::Unknown = ty.interned(&Interner) {
148 return None; 148 return None;
149 } 149 }
150 150
@@ -209,7 +209,7 @@ impl<'a> InferenceContext<'a> {
209 name: &Name, 209 name: &Name,
210 id: ExprOrPatId, 210 id: ExprOrPatId,
211 ) -> Option<(ValueNs, Option<Substs>)> { 211 ) -> Option<(ValueNs, Option<Substs>)> {
212 if let Ty::Unknown = ty { 212 if let TyKind::Unknown = ty.interned(&Interner) {
213 return None; 213 return None;
214 } 214 }
215 215
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs
index 54fcfed10..ebc612ca9 100644
--- a/crates/hir_ty/src/infer/unify.rs
+++ b/crates/hir_ty/src/infer/unify.rs
@@ -7,8 +7,8 @@ use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
7 7
8use super::{InferenceContext, Obligation}; 8use super::{InferenceContext, Obligation};
9use crate::{ 9use crate::{
10 BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferenceVar, Scalar, 10 BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferenceVar, Interner,
11 Substs, Ty, TypeWalk, 11 Scalar, Substs, Ty, TyKind, TypeWalk,
12}; 12};
13 13
14impl<'a> InferenceContext<'a> { 14impl<'a> InferenceContext<'a> {
@@ -49,8 +49,8 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
49 49
50 fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: DebruijnIndex) -> T { 50 fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: DebruijnIndex) -> T {
51 t.fold_binders( 51 t.fold_binders(
52 &mut |ty, binders| match ty { 52 &mut |ty, binders| match ty.interned(&Interner) {
53 Ty::InferenceVar(var, kind) => { 53 &TyKind::InferenceVar(var, kind) => {
54 let inner = var.to_inner(); 54 let inner = var.to_inner();
55 if self.var_stack.contains(&inner) { 55 if self.var_stack.contains(&inner) {
56 // recursive type 56 // recursive type
@@ -66,7 +66,7 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
66 } else { 66 } else {
67 let root = self.ctx.table.var_unification_table.find(inner); 67 let root = self.ctx.table.var_unification_table.find(inner);
68 let position = self.add(InferenceVar::from_inner(root), kind); 68 let position = self.add(InferenceVar::from_inner(root), kind);
69 Ty::BoundVar(BoundVar::new(binders, position)) 69 TyKind::BoundVar(BoundVar::new(binders, position)).intern(&Interner)
70 } 70 }
71 } 71 }
72 _ => ty, 72 _ => ty,
@@ -108,10 +108,10 @@ impl<T> Canonicalized<T> {
108 pub(super) fn decanonicalize_ty(&self, mut ty: Ty) -> Ty { 108 pub(super) fn decanonicalize_ty(&self, mut ty: Ty) -> Ty {
109 ty.walk_mut_binders( 109 ty.walk_mut_binders(
110 &mut |ty, binders| { 110 &mut |ty, binders| {
111 if let &mut Ty::BoundVar(bound) = ty { 111 if let &mut TyKind::BoundVar(bound) = &mut ty.0 {
112 if bound.debruijn >= binders { 112 if bound.debruijn >= binders {
113 let (v, k) = self.free_vars[bound.index]; 113 let (v, k) = self.free_vars[bound.index];
114 *ty = Ty::InferenceVar(v, k); 114 *ty = TyKind::InferenceVar(v, k).intern(&Interner);
115 } 115 }
116 } 116 }
117 }, 117 },
@@ -142,7 +142,7 @@ impl<T> Canonicalized<T> {
142 // eagerly replace projections in the type; we may be getting types 142 // eagerly replace projections in the type; we may be getting types
143 // e.g. from where clauses where this hasn't happened yet 143 // e.g. from where clauses where this hasn't happened yet
144 let ty = ctx.normalize_associated_types_in(ty.clone().subst_bound_vars(&new_vars)); 144 let ty = ctx.normalize_associated_types_in(ty.clone().subst_bound_vars(&new_vars));
145 ctx.table.unify(&Ty::InferenceVar(v, k), &ty); 145 ctx.table.unify(&TyKind::InferenceVar(v, k).intern(&Interner), &ty);
146 } 146 }
147 } 147 }
148} 148}
@@ -166,7 +166,10 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substs> {
166 // (kind of hacky) 166 // (kind of hacky)
167 for (i, var) in vars.iter().enumerate() { 167 for (i, var) in vars.iter().enumerate() {
168 if &*table.resolve_ty_shallow(var) == var { 168 if &*table.resolve_ty_shallow(var) == var {
169 table.unify(var, &Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i))); 169 table.unify(
170 var,
171 &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i)).intern(&Interner),
172 );
170 } 173 }
171 } 174 }
172 Some( 175 Some(
@@ -196,11 +199,12 @@ impl TypeVariableTable {
196 199
197 fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty { 200 fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty {
198 match kind { 201 match kind {
199 _ if self.inner[iv.to_inner().0 as usize].diverging => Ty::Never, 202 _ if self.inner[iv.to_inner().0 as usize].diverging => TyKind::Never,
200 TyVariableKind::General => Ty::Unknown, 203 TyVariableKind::General => TyKind::Unknown,
201 TyVariableKind::Integer => Ty::Scalar(Scalar::Int(IntTy::I32)), 204 TyVariableKind::Integer => TyKind::Scalar(Scalar::Int(IntTy::I32)),
202 TyVariableKind::Float => Ty::Scalar(Scalar::Float(FloatTy::F64)), 205 TyVariableKind::Float => TyKind::Scalar(Scalar::Float(FloatTy::F64)),
203 } 206 }
207 .intern(&Interner)
204 } 208 }
205} 209}
206 210
@@ -227,7 +231,7 @@ impl InferenceTable {
227 self.type_variable_table.push(TypeVariableData { diverging }); 231 self.type_variable_table.push(TypeVariableData { diverging });
228 let key = self.var_unification_table.new_key(TypeVarValue::Unknown); 232 let key = self.var_unification_table.new_key(TypeVarValue::Unknown);
229 assert_eq!(key.0 as usize, self.type_variable_table.inner.len() - 1); 233 assert_eq!(key.0 as usize, self.type_variable_table.inner.len() - 1);
230 Ty::InferenceVar(InferenceVar::from_inner(key), kind) 234 TyKind::InferenceVar(InferenceVar::from_inner(key), kind).intern(&Interner)
231 } 235 }
232 236
233 pub(crate) fn new_type_var(&mut self) -> Ty { 237 pub(crate) fn new_type_var(&mut self) -> Ty {
@@ -290,12 +294,12 @@ impl InferenceTable {
290 } 294 }
291 295
292 pub(super) fn unify_inner_trivial(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool { 296 pub(super) fn unify_inner_trivial(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool {
293 match (ty1, ty2) { 297 match (ty1.interned(&Interner), ty2.interned(&Interner)) {
294 (Ty::Unknown, _) | (_, Ty::Unknown) => true, 298 (TyKind::Unknown, _) | (_, TyKind::Unknown) => true,
295 299
296 (Ty::Placeholder(p1), Ty::Placeholder(p2)) if *p1 == *p2 => true, 300 (TyKind::Placeholder(p1), TyKind::Placeholder(p2)) if *p1 == *p2 => true,
297 301
298 (Ty::Dyn(dyn1), Ty::Dyn(dyn2)) if dyn1.len() == dyn2.len() => { 302 (TyKind::Dyn(dyn1), TyKind::Dyn(dyn2)) if dyn1.len() == dyn2.len() => {
299 for (pred1, pred2) in dyn1.iter().zip(dyn2.iter()) { 303 for (pred1, pred2) in dyn1.iter().zip(dyn2.iter()) {
300 if !self.unify_preds(pred1, pred2, depth + 1) { 304 if !self.unify_preds(pred1, pred2, depth + 1) {
301 return false; 305 return false;
@@ -305,16 +309,16 @@ impl InferenceTable {
305 } 309 }
306 310
307 ( 311 (
308 Ty::InferenceVar(tv1, TyVariableKind::General), 312 TyKind::InferenceVar(tv1, TyVariableKind::General),
309 Ty::InferenceVar(tv2, TyVariableKind::General), 313 TyKind::InferenceVar(tv2, TyVariableKind::General),
310 ) 314 )
311 | ( 315 | (
312 Ty::InferenceVar(tv1, TyVariableKind::Integer), 316 TyKind::InferenceVar(tv1, TyVariableKind::Integer),
313 Ty::InferenceVar(tv2, TyVariableKind::Integer), 317 TyKind::InferenceVar(tv2, TyVariableKind::Integer),
314 ) 318 )
315 | ( 319 | (
316 Ty::InferenceVar(tv1, TyVariableKind::Float), 320 TyKind::InferenceVar(tv1, TyVariableKind::Float),
317 Ty::InferenceVar(tv2, TyVariableKind::Float), 321 TyKind::InferenceVar(tv2, TyVariableKind::Float),
318 ) if self.type_variable_table.is_diverging(*tv1) 322 ) if self.type_variable_table.is_diverging(*tv1)
319 == self.type_variable_table.is_diverging(*tv2) => 323 == self.type_variable_table.is_diverging(*tv2) =>
320 { 324 {
@@ -326,24 +330,37 @@ impl InferenceTable {
326 // The order of MaybeNeverTypeVar matters here. 330 // The order of MaybeNeverTypeVar matters here.
327 // Unifying MaybeNeverTypeVar and TypeVar will let the latter become MaybeNeverTypeVar. 331 // Unifying MaybeNeverTypeVar and TypeVar will let the latter become MaybeNeverTypeVar.
328 // Unifying MaybeNeverTypeVar and other concrete type will let the former become it. 332 // Unifying MaybeNeverTypeVar and other concrete type will let the former become it.
329 (Ty::InferenceVar(tv, TyVariableKind::General), other) 333 (TyKind::InferenceVar(tv, TyVariableKind::General), other)
330 | (other, Ty::InferenceVar(tv, TyVariableKind::General)) 334 | (other, TyKind::InferenceVar(tv, TyVariableKind::General))
331 | (Ty::InferenceVar(tv, TyVariableKind::Integer), other @ Ty::Scalar(Scalar::Int(_)))
332 | (other @ Ty::Scalar(Scalar::Int(_)), Ty::InferenceVar(tv, TyVariableKind::Integer))
333 | ( 335 | (
334 Ty::InferenceVar(tv, TyVariableKind::Integer), 336 TyKind::InferenceVar(tv, TyVariableKind::Integer),
335 other @ Ty::Scalar(Scalar::Uint(_)), 337 other @ TyKind::Scalar(Scalar::Int(_)),
336 ) 338 )
337 | ( 339 | (
338 other @ Ty::Scalar(Scalar::Uint(_)), 340 other @ TyKind::Scalar(Scalar::Int(_)),
339 Ty::InferenceVar(tv, TyVariableKind::Integer), 341 TyKind::InferenceVar(tv, TyVariableKind::Integer),
340 ) 342 )
341 | (Ty::InferenceVar(tv, TyVariableKind::Float), other @ Ty::Scalar(Scalar::Float(_))) 343 | (
342 | (other @ Ty::Scalar(Scalar::Float(_)), Ty::InferenceVar(tv, TyVariableKind::Float)) => 344 TyKind::InferenceVar(tv, TyVariableKind::Integer),
343 { 345 other @ TyKind::Scalar(Scalar::Uint(_)),
346 )
347 | (
348 other @ TyKind::Scalar(Scalar::Uint(_)),
349 TyKind::InferenceVar(tv, TyVariableKind::Integer),
350 )
351 | (
352 TyKind::InferenceVar(tv, TyVariableKind::Float),
353 other @ TyKind::Scalar(Scalar::Float(_)),
354 )
355 | (
356 other @ TyKind::Scalar(Scalar::Float(_)),
357 TyKind::InferenceVar(tv, TyVariableKind::Float),
358 ) => {
344 // the type var is unknown since we tried to resolve it 359 // the type var is unknown since we tried to resolve it
345 self.var_unification_table 360 self.var_unification_table.union_value(
346 .union_value(tv.to_inner(), TypeVarValue::Known(other.clone())); 361 tv.to_inner(),
362 TypeVarValue::Known(other.clone().intern(&Interner)),
363 );
347 true 364 true
348 } 365 }
349 366
@@ -364,11 +381,11 @@ impl InferenceTable {
364 self.unify_substs(&tr1.substs, &tr2.substs, depth + 1) 381 self.unify_substs(&tr1.substs, &tr2.substs, depth + 1)
365 } 382 }
366 (GenericPredicate::Projection(proj1), GenericPredicate::Projection(proj2)) 383 (GenericPredicate::Projection(proj1), GenericPredicate::Projection(proj2))
367 if proj1.projection_ty.associated_ty == proj2.projection_ty.associated_ty => 384 if proj1.projection_ty.associated_ty_id == proj2.projection_ty.associated_ty_id =>
368 { 385 {
369 self.unify_substs( 386 self.unify_substs(
370 &proj1.projection_ty.parameters, 387 &proj1.projection_ty.substitution,
371 &proj2.projection_ty.parameters, 388 &proj2.projection_ty.substitution,
372 depth + 1, 389 depth + 1,
373 ) && self.unify_inner(&proj1.ty, &proj2.ty, depth + 1) 390 ) && self.unify_inner(&proj1.ty, &proj2.ty, depth + 1)
374 } 391 }
@@ -387,8 +404,8 @@ impl InferenceTable {
387 if i > 0 { 404 if i > 0 {
388 cov_mark::hit!(type_var_resolves_to_int_var); 405 cov_mark::hit!(type_var_resolves_to_int_var);
389 } 406 }
390 match &*ty { 407 match &ty.0 {
391 Ty::InferenceVar(tv, _) => { 408 TyKind::InferenceVar(tv, _) => {
392 let inner = tv.to_inner(); 409 let inner = tv.to_inner();
393 match self.var_unification_table.inlined_probe_value(inner).known() { 410 match self.var_unification_table.inlined_probe_value(inner).known() {
394 Some(known_ty) => { 411 Some(known_ty) => {
@@ -410,8 +427,8 @@ impl InferenceTable {
410 /// be resolved as far as possible, i.e. contain no type variables with 427 /// be resolved as far as possible, i.e. contain no type variables with
411 /// known type. 428 /// known type.
412 fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { 429 fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
413 ty.fold(&mut |ty| match ty { 430 ty.fold(&mut |ty| match ty.interned(&Interner) {
414 Ty::InferenceVar(tv, kind) => { 431 &TyKind::InferenceVar(tv, kind) => {
415 let inner = tv.to_inner(); 432 let inner = tv.to_inner();
416 if tv_stack.contains(&inner) { 433 if tv_stack.contains(&inner) {
417 cov_mark::hit!(type_var_cycles_resolve_as_possible); 434 cov_mark::hit!(type_var_cycles_resolve_as_possible);
@@ -435,10 +452,10 @@ impl InferenceTable {
435 } 452 }
436 453
437 /// Resolves the type completely; type variables without known type are 454 /// Resolves the type completely; type variables without known type are
438 /// replaced by Ty::Unknown. 455 /// replaced by TyKind::Unknown.
439 fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { 456 fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
440 ty.fold(&mut |ty| match ty { 457 ty.fold(&mut |ty| match ty.interned(&Interner) {
441 Ty::InferenceVar(tv, kind) => { 458 &TyKind::InferenceVar(tv, kind) => {
442 let inner = tv.to_inner(); 459 let inner = tv.to_inner();
443 if tv_stack.contains(&inner) { 460 if tv_stack.contains(&inner) {
444 cov_mark::hit!(type_var_cycles_resolve_completely); 461 cov_mark::hit!(type_var_cycles_resolve_completely);
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index e77f24e4e..484652073 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -27,9 +27,8 @@ use std::{iter, mem, ops::Deref, sync::Arc};
27 27
28use base_db::salsa; 28use base_db::salsa;
29use hir_def::{ 29use hir_def::{
30 builtin_type::BuiltinType, expr::ExprId, type_ref::Rawness, AssocContainerId, DefWithBodyId, 30 builtin_type::BuiltinType, expr::ExprId, type_ref::Rawness, AssocContainerId, FunctionId,
31 FunctionId, GenericDefId, HasModule, LifetimeParamId, Lookup, TraitId, TypeAliasId, 31 GenericDefId, HasModule, LifetimeParamId, Lookup, TraitId, TypeAliasId, TypeParamId,
32 TypeParamId,
33}; 32};
34use itertools::Itertools; 33use itertools::Itertools;
35 34
@@ -47,9 +46,16 @@ pub use lower::{
47}; 46};
48pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; 47pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment};
49 48
50pub use chalk_ir::{AdtId, BoundVar, DebruijnIndex, Mutability, Scalar, TyVariableKind}; 49pub use chalk_ir::{AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind};
51 50
52pub(crate) use crate::traits::chalk::Interner; 51pub use crate::traits::chalk::Interner;
52
53pub type ForeignDefId = chalk_ir::ForeignDefId<Interner>;
54pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>;
55pub type FnDefId = chalk_ir::FnDefId<Interner>;
56pub type ClosureId = chalk_ir::ClosureId<Interner>;
57pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
58pub type PlaceholderIndex = chalk_ir::PlaceholderIndex;
53 59
54#[derive(Clone, PartialEq, Eq, Debug, Hash)] 60#[derive(Clone, PartialEq, Eq, Debug, Hash)]
55pub enum Lifetime { 61pub enum Lifetime {
@@ -60,7 +66,7 @@ pub enum Lifetime {
60#[derive(Clone, PartialEq, Eq, Debug, Hash)] 66#[derive(Clone, PartialEq, Eq, Debug, Hash)]
61pub struct OpaqueTy { 67pub struct OpaqueTy {
62 pub opaque_ty_id: OpaqueTyId, 68 pub opaque_ty_id: OpaqueTyId,
63 pub parameters: Substs, 69 pub substitution: Substs,
64} 70}
65 71
66/// A "projection" type corresponds to an (unnormalized) 72/// A "projection" type corresponds to an (unnormalized)
@@ -68,17 +74,17 @@ pub struct OpaqueTy {
68/// trait and all its parameters are fully known. 74/// trait and all its parameters are fully known.
69#[derive(Clone, PartialEq, Eq, Debug, Hash)] 75#[derive(Clone, PartialEq, Eq, Debug, Hash)]
70pub struct ProjectionTy { 76pub struct ProjectionTy {
71 pub associated_ty: TypeAliasId, 77 pub associated_ty_id: AssocTypeId,
72 pub parameters: Substs, 78 pub substitution: Substs,
73} 79}
74 80
75impl ProjectionTy { 81impl ProjectionTy {
76 pub fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef { 82 pub fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef {
77 TraitRef { trait_: self.trait_(db), substs: self.parameters.clone() } 83 TraitRef { trait_: self.trait_(db), substs: self.substitution.clone() }
78 } 84 }
79 85
80 fn trait_(&self, db: &dyn HirDatabase) -> TraitId { 86 fn trait_(&self, db: &dyn HirDatabase) -> TraitId {
81 match self.associated_ty.lookup(db.upcast()).container { 87 match from_assoc_type_id(self.associated_ty_id).lookup(db.upcast()).container {
82 AssocContainerId::TraitId(it) => it, 88 AssocContainerId::TraitId(it) => it,
83 _ => panic!("projection ty without parent trait"), 89 _ => panic!("projection ty without parent trait"),
84 } 90 }
@@ -87,7 +93,7 @@ impl ProjectionTy {
87 93
88impl TypeWalk for ProjectionTy { 94impl TypeWalk for ProjectionTy {
89 fn walk(&self, f: &mut impl FnMut(&Ty)) { 95 fn walk(&self, f: &mut impl FnMut(&Ty)) {
90 self.parameters.walk(f); 96 self.substitution.walk(f);
91 } 97 }
92 98
93 fn walk_mut_binders( 99 fn walk_mut_binders(
@@ -95,14 +101,11 @@ impl TypeWalk for ProjectionTy {
95 f: &mut impl FnMut(&mut Ty, DebruijnIndex), 101 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
96 binders: DebruijnIndex, 102 binders: DebruijnIndex,
97 ) { 103 ) {
98 self.parameters.walk_mut_binders(f, binders); 104 self.substitution.walk_mut_binders(f, binders);
99 } 105 }
100} 106}
101 107
102#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] 108pub type FnSig = chalk_ir::FnSig<Interner>;
103pub struct FnSig {
104 pub variadic: bool,
105}
106 109
107#[derive(Clone, PartialEq, Eq, Debug, Hash)] 110#[derive(Clone, PartialEq, Eq, Debug, Hash)]
108pub struct FnPointer { 111pub struct FnPointer {
@@ -131,7 +134,7 @@ pub enum AliasTy {
131/// 134///
132/// This should be cheap to clone. 135/// This should be cheap to clone.
133#[derive(Clone, PartialEq, Eq, Debug, Hash)] 136#[derive(Clone, PartialEq, Eq, Debug, Hash)]
134pub enum Ty { 137pub enum TyKind {
135 /// Structures, enumerations and unions. 138 /// Structures, enumerations and unions.
136 Adt(AdtId<Interner>, Substs), 139 Adt(AdtId<Interner>, Substs),
137 140
@@ -139,7 +142,7 @@ pub enum Ty {
139 /// when we have tried to normalize a projection like `T::Item` but 142 /// when we have tried to normalize a projection like `T::Item` but
140 /// couldn't find a better representation. In that case, we generate 143 /// couldn't find a better representation. In that case, we generate
141 /// an **application type** like `(Iterator::Item)<T>`. 144 /// an **application type** like `(Iterator::Item)<T>`.
142 AssociatedType(TypeAliasId, Substs), 145 AssociatedType(AssocTypeId, Substs),
143 146
144 /// a scalar type like `bool` or `u32` 147 /// a scalar type like `bool` or `u32`
145 Scalar(Scalar), 148 Scalar(Scalar),
@@ -179,7 +182,7 @@ pub enum Ty {
179 /// fn foo() -> i32 { 1 } 182 /// fn foo() -> i32 { 1 }
180 /// let bar = foo; // bar: fn() -> i32 {foo} 183 /// let bar = foo; // bar: fn() -> i32 {foo}
181 /// ``` 184 /// ```
182 FnDef(CallableDefId, Substs), 185 FnDef(FnDefId, Substs),
183 186
184 /// The pointee of a string slice. Written as `str`. 187 /// The pointee of a string slice. Written as `str`.
185 Str, 188 Str,
@@ -191,10 +194,10 @@ pub enum Ty {
191 /// 194 ///
192 /// The closure signature is stored in a `FnPtr` type in the first type 195 /// The closure signature is stored in a `FnPtr` type in the first type
193 /// parameter. 196 /// parameter.
194 Closure(DefWithBodyId, ExprId, Substs), 197 Closure(ClosureId, Substs),
195 198
196 /// Represents a foreign type declared in external blocks. 199 /// Represents a foreign type declared in external blocks.
197 ForeignType(TypeAliasId), 200 ForeignType(ForeignDefId),
198 201
199 /// A pointer to a function. Written as `fn() -> i32`. 202 /// A pointer to a function. Written as `fn() -> i32`.
200 /// 203 ///
@@ -216,7 +219,7 @@ pub enum Ty {
216 /// {}` when we're type-checking the body of that function. In this 219 /// {}` when we're type-checking the body of that function. In this
217 /// situation, we know this stands for *some* type, but don't know the exact 220 /// situation, we know this stands for *some* type, but don't know the exact
218 /// type. 221 /// type.
219 Placeholder(TypeParamId), 222 Placeholder(PlaceholderIndex),
220 223
221 /// A bound type variable. This is used in various places: when representing 224 /// A bound type variable. This is used in various places: when representing
222 /// some polymorphic type like the type of function `fn f<T>`, the type 225 /// some polymorphic type like the type of function `fn f<T>`, the type
@@ -244,6 +247,21 @@ pub enum Ty {
244 Unknown, 247 Unknown,
245} 248}
246 249
250#[derive(Clone, PartialEq, Eq, Debug, Hash)]
251pub struct Ty(TyKind);
252
253impl TyKind {
254 pub fn intern(self, _interner: &Interner) -> Ty {
255 Ty(self)
256 }
257}
258
259impl Ty {
260 pub fn interned(&self, _interner: &Interner) -> &TyKind {
261 &self.0
262 }
263}
264
247/// A list of substitutions for generic parameters. 265/// A list of substitutions for generic parameters.
248#[derive(Clone, PartialEq, Eq, Debug, Hash)] 266#[derive(Clone, PartialEq, Eq, Debug, Hash)]
249pub struct Substs(Arc<[Ty]>); 267pub struct Substs(Arc<[Ty]>);
@@ -291,14 +309,22 @@ impl Substs {
291 } 309 }
292 310
293 /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). 311 /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`).
294 pub(crate) fn type_params_for_generics(generic_params: &Generics) -> Substs { 312 pub(crate) fn type_params_for_generics(
295 Substs(generic_params.iter().map(|(id, _)| Ty::Placeholder(id)).collect()) 313 db: &dyn HirDatabase,
314 generic_params: &Generics,
315 ) -> Substs {
316 Substs(
317 generic_params
318 .iter()
319 .map(|(id, _)| TyKind::Placeholder(to_placeholder_idx(db, id)).intern(&Interner))
320 .collect(),
321 )
296 } 322 }
297 323
298 /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). 324 /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`).
299 pub fn type_params(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> Substs { 325 pub fn type_params(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> Substs {
300 let params = generics(db.upcast(), def.into()); 326 let params = generics(db.upcast(), def.into());
301 Substs::type_params_for_generics(&params) 327 Substs::type_params_for_generics(db, &params)
302 } 328 }
303 329
304 /// Return Substs that replace each parameter by a bound variable. 330 /// Return Substs that replace each parameter by a bound variable.
@@ -307,7 +333,7 @@ impl Substs {
307 generic_params 333 generic_params
308 .iter() 334 .iter()
309 .enumerate() 335 .enumerate()
310 .map(|(idx, _)| Ty::BoundVar(BoundVar::new(debruijn, idx))) 336 .map(|(idx, _)| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner))
311 .collect(), 337 .collect(),
312 ) 338 )
313 } 339 }
@@ -355,11 +381,14 @@ impl SubstsBuilder {
355 } 381 }
356 382
357 pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self { 383 pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self {
358 self.fill((starting_from..).map(|idx| Ty::BoundVar(BoundVar::new(debruijn, idx)))) 384 self.fill(
385 (starting_from..)
386 .map(|idx| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)),
387 )
359 } 388 }
360 389
361 pub fn fill_with_unknown(self) -> Self { 390 pub fn fill_with_unknown(self) -> Self {
362 self.fill(iter::repeat(Ty::Unknown)) 391 self.fill(iter::repeat(TyKind::Unknown.intern(&Interner)))
363 } 392 }
364 393
365 pub fn fill(mut self, filler: impl Iterator<Item = Ty>) -> Self { 394 pub fn fill(mut self, filler: impl Iterator<Item = Ty>) -> Self {
@@ -601,45 +630,52 @@ impl TypeWalk for CallableSig {
601 630
602impl Ty { 631impl Ty {
603 pub fn unit() -> Self { 632 pub fn unit() -> Self {
604 Ty::Tuple(0, Substs::empty()) 633 TyKind::Tuple(0, Substs::empty()).intern(&Interner)
605 } 634 }
606 635
607 pub fn adt_ty(adt: hir_def::AdtId, substs: Substs) -> Ty { 636 pub fn adt_ty(adt: hir_def::AdtId, substs: Substs) -> Ty {
608 Ty::Adt(AdtId(adt), substs) 637 TyKind::Adt(AdtId(adt), substs).intern(&Interner)
609 } 638 }
610 639
611 pub fn fn_ptr(sig: CallableSig) -> Self { 640 pub fn fn_ptr(sig: CallableSig) -> Self {
612 Ty::Function(FnPointer { 641 TyKind::Function(FnPointer {
613 num_args: sig.params().len(), 642 num_args: sig.params().len(),
614 sig: FnSig { variadic: sig.is_varargs }, 643 sig: FnSig { abi: (), safety: Safety::Safe, variadic: sig.is_varargs },
615 substs: Substs(sig.params_and_return), 644 substs: Substs(sig.params_and_return),
616 }) 645 })
646 .intern(&Interner)
617 } 647 }
618 648
619 pub fn builtin(builtin: BuiltinType) -> Self { 649 pub fn builtin(builtin: BuiltinType) -> Self {
620 match builtin { 650 match builtin {
621 BuiltinType::Char => Ty::Scalar(Scalar::Char), 651 BuiltinType::Char => TyKind::Scalar(Scalar::Char).intern(&Interner),
622 BuiltinType::Bool => Ty::Scalar(Scalar::Bool), 652 BuiltinType::Bool => TyKind::Scalar(Scalar::Bool).intern(&Interner),
623 BuiltinType::Str => Ty::Str, 653 BuiltinType::Str => TyKind::Str.intern(&Interner),
624 BuiltinType::Int(t) => Ty::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))), 654 BuiltinType::Int(t) => {
625 BuiltinType::Uint(t) => Ty::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))), 655 TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))).intern(&Interner)
626 BuiltinType::Float(t) => Ty::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))), 656 }
657 BuiltinType::Uint(t) => {
658 TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))).intern(&Interner)
659 }
660 BuiltinType::Float(t) => {
661 TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))).intern(&Interner)
662 }
627 } 663 }
628 } 664 }
629 665
630 pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { 666 pub fn as_reference(&self) -> Option<(&Ty, Mutability)> {
631 match self { 667 match self.interned(&Interner) {
632 Ty::Ref(mutability, parameters) => Some((parameters.as_single(), *mutability)), 668 TyKind::Ref(mutability, parameters) => Some((parameters.as_single(), *mutability)),
633 _ => None, 669 _ => None,
634 } 670 }
635 } 671 }
636 672
637 pub fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> { 673 pub fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> {
638 match self { 674 match self.interned(&Interner) {
639 Ty::Ref(mutability, parameters) => { 675 TyKind::Ref(mutability, parameters) => {
640 Some((parameters.as_single(), Rawness::Ref, *mutability)) 676 Some((parameters.as_single(), Rawness::Ref, *mutability))
641 } 677 }
642 Ty::Raw(mutability, parameters) => { 678 TyKind::Raw(mutability, parameters) => {
643 Some((parameters.as_single(), Rawness::RawPtr, *mutability)) 679 Some((parameters.as_single(), Rawness::RawPtr, *mutability))
644 } 680 }
645 _ => None, 681 _ => None,
@@ -649,7 +685,7 @@ impl Ty {
649 pub fn strip_references(&self) -> &Ty { 685 pub fn strip_references(&self) -> &Ty {
650 let mut t: &Ty = self; 686 let mut t: &Ty = self;
651 687
652 while let Ty::Ref(_mutability, parameters) = t { 688 while let TyKind::Ref(_mutability, parameters) = t.interned(&Interner) {
653 t = parameters.as_single(); 689 t = parameters.as_single();
654 } 690 }
655 691
@@ -657,65 +693,71 @@ impl Ty {
657 } 693 }
658 694
659 pub fn as_adt(&self) -> Option<(hir_def::AdtId, &Substs)> { 695 pub fn as_adt(&self) -> Option<(hir_def::AdtId, &Substs)> {
660 match self { 696 match self.interned(&Interner) {
661 Ty::Adt(AdtId(adt), parameters) => Some((*adt, parameters)), 697 TyKind::Adt(AdtId(adt), parameters) => Some((*adt, parameters)),
662 _ => None, 698 _ => None,
663 } 699 }
664 } 700 }
665 701
666 pub fn as_tuple(&self) -> Option<&Substs> { 702 pub fn as_tuple(&self) -> Option<&Substs> {
667 match self { 703 match self.interned(&Interner) {
668 Ty::Tuple(_, substs) => Some(substs), 704 TyKind::Tuple(_, substs) => Some(substs),
669 _ => None, 705 _ => None,
670 } 706 }
671 } 707 }
672 708
673 pub fn as_generic_def(&self) -> Option<GenericDefId> { 709 pub fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId> {
674 match *self { 710 match *self.interned(&Interner) {
675 Ty::Adt(AdtId(adt), ..) => Some(adt.into()), 711 TyKind::Adt(AdtId(adt), ..) => Some(adt.into()),
676 Ty::FnDef(callable, ..) => Some(callable.into()), 712 TyKind::FnDef(callable, ..) => {
677 Ty::AssociatedType(type_alias, ..) => Some(type_alias.into()), 713 Some(db.lookup_intern_callable_def(callable.into()).into())
678 Ty::ForeignType(type_alias, ..) => Some(type_alias.into()), 714 }
715 TyKind::AssociatedType(type_alias, ..) => Some(from_assoc_type_id(type_alias).into()),
716 TyKind::ForeignType(type_alias, ..) => Some(from_foreign_def_id(type_alias).into()),
679 _ => None, 717 _ => None,
680 } 718 }
681 } 719 }
682 720
683 pub fn is_never(&self) -> bool { 721 pub fn is_never(&self) -> bool {
684 matches!(self, Ty::Never) 722 matches!(self.interned(&Interner), TyKind::Never)
685 } 723 }
686 724
687 pub fn is_unknown(&self) -> bool { 725 pub fn is_unknown(&self) -> bool {
688 matches!(self, Ty::Unknown) 726 matches!(self.interned(&Interner), TyKind::Unknown)
689 } 727 }
690 728
691 pub fn equals_ctor(&self, other: &Ty) -> bool { 729 pub fn equals_ctor(&self, other: &Ty) -> bool {
692 match (self, other) { 730 match (self.interned(&Interner), other.interned(&Interner)) {
693 (Ty::Adt(adt, ..), Ty::Adt(adt2, ..)) => adt == adt2, 731 (TyKind::Adt(adt, ..), TyKind::Adt(adt2, ..)) => adt == adt2,
694 (Ty::Slice(_), Ty::Slice(_)) | (Ty::Array(_), Ty::Array(_)) => true, 732 (TyKind::Slice(_), TyKind::Slice(_)) | (TyKind::Array(_), TyKind::Array(_)) => true,
695 (Ty::FnDef(def_id, ..), Ty::FnDef(def_id2, ..)) => def_id == def_id2, 733 (TyKind::FnDef(def_id, ..), TyKind::FnDef(def_id2, ..)) => def_id == def_id2,
696 (Ty::OpaqueType(ty_id, ..), Ty::OpaqueType(ty_id2, ..)) => ty_id == ty_id2, 734 (TyKind::OpaqueType(ty_id, ..), TyKind::OpaqueType(ty_id2, ..)) => ty_id == ty_id2,
697 (Ty::AssociatedType(ty_id, ..), Ty::AssociatedType(ty_id2, ..)) 735 (TyKind::AssociatedType(ty_id, ..), TyKind::AssociatedType(ty_id2, ..)) => {
698 | (Ty::ForeignType(ty_id, ..), Ty::ForeignType(ty_id2, ..)) => ty_id == ty_id2, 736 ty_id == ty_id2
699 (Ty::Closure(def, expr, _), Ty::Closure(def2, expr2, _)) => { 737 }
700 expr == expr2 && def == def2 738 (TyKind::ForeignType(ty_id, ..), TyKind::ForeignType(ty_id2, ..)) => ty_id == ty_id2,
739 (TyKind::Closure(id1, _), TyKind::Closure(id2, _)) => id1 == id2,
740 (TyKind::Ref(mutability, ..), TyKind::Ref(mutability2, ..))
741 | (TyKind::Raw(mutability, ..), TyKind::Raw(mutability2, ..)) => {
742 mutability == mutability2
701 } 743 }
702 (Ty::Ref(mutability, ..), Ty::Ref(mutability2, ..))
703 | (Ty::Raw(mutability, ..), Ty::Raw(mutability2, ..)) => mutability == mutability2,
704 ( 744 (
705 Ty::Function(FnPointer { num_args, sig, .. }), 745 TyKind::Function(FnPointer { num_args, sig, .. }),
706 Ty::Function(FnPointer { num_args: num_args2, sig: sig2, .. }), 746 TyKind::Function(FnPointer { num_args: num_args2, sig: sig2, .. }),
707 ) => num_args == num_args2 && sig == sig2, 747 ) => num_args == num_args2 && sig == sig2,
708 (Ty::Tuple(cardinality, _), Ty::Tuple(cardinality2, _)) => cardinality == cardinality2, 748 (TyKind::Tuple(cardinality, _), TyKind::Tuple(cardinality2, _)) => {
709 (Ty::Str, Ty::Str) | (Ty::Never, Ty::Never) => true, 749 cardinality == cardinality2
710 (Ty::Scalar(scalar), Ty::Scalar(scalar2)) => scalar == scalar2, 750 }
751 (TyKind::Str, TyKind::Str) | (TyKind::Never, TyKind::Never) => true,
752 (TyKind::Scalar(scalar), TyKind::Scalar(scalar2)) => scalar == scalar2,
711 _ => false, 753 _ => false,
712 } 754 }
713 } 755 }
714 756
715 /// If this is a `dyn Trait` type, this returns the `Trait` part. 757 /// If this is a `dyn Trait` type, this returns the `Trait` part.
716 pub fn dyn_trait_ref(&self) -> Option<&TraitRef> { 758 pub fn dyn_trait_ref(&self) -> Option<&TraitRef> {
717 match self { 759 match self.interned(&Interner) {
718 Ty::Dyn(bounds) => bounds.get(0).and_then(|b| match b { 760 TyKind::Dyn(bounds) => bounds.get(0).and_then(|b| match b {
719 GenericPredicate::Implemented(trait_ref) => Some(trait_ref), 761 GenericPredicate::Implemented(trait_ref) => Some(trait_ref),
720 _ => None, 762 _ => None,
721 }), 763 }),
@@ -729,28 +771,37 @@ impl Ty {
729 } 771 }
730 772
731 fn builtin_deref(&self) -> Option<Ty> { 773 fn builtin_deref(&self) -> Option<Ty> {
732 match self { 774 match self.interned(&Interner) {
733 Ty::Ref(.., parameters) => Some(Ty::clone(parameters.as_single())), 775 TyKind::Ref(.., parameters) => Some(Ty::clone(parameters.as_single())),
734 Ty::Raw(.., parameters) => Some(Ty::clone(parameters.as_single())), 776 TyKind::Raw(.., parameters) => Some(Ty::clone(parameters.as_single())),
735 _ => None, 777 _ => None,
736 } 778 }
737 } 779 }
738 780
739 pub fn as_fn_def(&self) -> Option<FunctionId> { 781 pub fn callable_def(&self, db: &dyn HirDatabase) -> Option<CallableDefId> {
740 match self { 782 match self.interned(&Interner) {
741 &Ty::FnDef(CallableDefId::FunctionId(func), ..) => Some(func), 783 &TyKind::FnDef(def, ..) => Some(db.lookup_intern_callable_def(def.into())),
742 _ => None, 784 _ => None,
743 } 785 }
744 } 786 }
745 787
788 pub fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId> {
789 if let Some(CallableDefId::FunctionId(func)) = self.callable_def(db) {
790 Some(func)
791 } else {
792 None
793 }
794 }
795
746 pub fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig> { 796 pub fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig> {
747 match self { 797 match self.interned(&Interner) {
748 Ty::Function(fn_ptr) => Some(CallableSig::from_fn_ptr(fn_ptr)), 798 TyKind::Function(fn_ptr) => Some(CallableSig::from_fn_ptr(fn_ptr)),
749 Ty::FnDef(def, parameters) => { 799 TyKind::FnDef(def, parameters) => {
750 let sig = db.callable_item_signature(*def); 800 let callable_def = db.lookup_intern_callable_def((*def).into());
801 let sig = db.callable_item_signature(callable_def);
751 Some(sig.subst(&parameters)) 802 Some(sig.subst(&parameters))
752 } 803 }
753 Ty::Closure(.., substs) => { 804 TyKind::Closure(.., substs) => {
754 let sig_param = &substs[0]; 805 let sig_param = &substs[0];
755 sig_param.callable_sig(db) 806 sig_param.callable_sig(db)
756 } 807 }
@@ -763,18 +814,18 @@ impl Ty {
763 /// `self` is `Option<_>` and the substs contain `u32`, we'll have 814 /// `self` is `Option<_>` and the substs contain `u32`, we'll have
764 /// `Option<u32>` afterwards.) 815 /// `Option<u32>` afterwards.)
765 pub fn apply_substs(mut self, new_substs: Substs) -> Ty { 816 pub fn apply_substs(mut self, new_substs: Substs) -> Ty {
766 match &mut self { 817 match &mut self.0 {
767 Ty::Adt(_, substs) 818 TyKind::Adt(_, substs)
768 | Ty::Slice(substs) 819 | TyKind::Slice(substs)
769 | Ty::Array(substs) 820 | TyKind::Array(substs)
770 | Ty::Raw(_, substs) 821 | TyKind::Raw(_, substs)
771 | Ty::Ref(_, substs) 822 | TyKind::Ref(_, substs)
772 | Ty::FnDef(_, substs) 823 | TyKind::FnDef(_, substs)
773 | Ty::Function(FnPointer { substs, .. }) 824 | TyKind::Function(FnPointer { substs, .. })
774 | Ty::Tuple(_, substs) 825 | TyKind::Tuple(_, substs)
775 | Ty::OpaqueType(_, substs) 826 | TyKind::OpaqueType(_, substs)
776 | Ty::AssociatedType(_, substs) 827 | TyKind::AssociatedType(_, substs)
777 | Ty::Closure(.., substs) => { 828 | TyKind::Closure(.., substs) => {
778 assert_eq!(substs.len(), new_substs.len()); 829 assert_eq!(substs.len(), new_substs.len());
779 *substs = new_substs; 830 *substs = new_substs;
780 } 831 }
@@ -786,44 +837,44 @@ impl Ty {
786 /// Returns the type parameters of this type if it has some (i.e. is an ADT 837 /// Returns the type parameters of this type if it has some (i.e. is an ADT
787 /// or function); so if `self` is `Option<u32>`, this returns the `u32`. 838 /// or function); so if `self` is `Option<u32>`, this returns the `u32`.
788 pub fn substs(&self) -> Option<&Substs> { 839 pub fn substs(&self) -> Option<&Substs> {
789 match self { 840 match self.interned(&Interner) {
790 Ty::Adt(_, substs) 841 TyKind::Adt(_, substs)
791 | Ty::Slice(substs) 842 | TyKind::Slice(substs)
792 | Ty::Array(substs) 843 | TyKind::Array(substs)
793 | Ty::Raw(_, substs) 844 | TyKind::Raw(_, substs)
794 | Ty::Ref(_, substs) 845 | TyKind::Ref(_, substs)
795 | Ty::FnDef(_, substs) 846 | TyKind::FnDef(_, substs)
796 | Ty::Function(FnPointer { substs, .. }) 847 | TyKind::Function(FnPointer { substs, .. })
797 | Ty::Tuple(_, substs) 848 | TyKind::Tuple(_, substs)
798 | Ty::OpaqueType(_, substs) 849 | TyKind::OpaqueType(_, substs)
799 | Ty::AssociatedType(_, substs) 850 | TyKind::AssociatedType(_, substs)
800 | Ty::Closure(.., substs) => Some(substs), 851 | TyKind::Closure(.., substs) => Some(substs),
801 _ => None, 852 _ => None,
802 } 853 }
803 } 854 }
804 855
805 pub fn substs_mut(&mut self) -> Option<&mut Substs> { 856 pub fn substs_mut(&mut self) -> Option<&mut Substs> {
806 match self { 857 match &mut self.0 {
807 Ty::Adt(_, substs) 858 TyKind::Adt(_, substs)
808 | Ty::Slice(substs) 859 | TyKind::Slice(substs)
809 | Ty::Array(substs) 860 | TyKind::Array(substs)
810 | Ty::Raw(_, substs) 861 | TyKind::Raw(_, substs)
811 | Ty::Ref(_, substs) 862 | TyKind::Ref(_, substs)
812 | Ty::FnDef(_, substs) 863 | TyKind::FnDef(_, substs)
813 | Ty::Function(FnPointer { substs, .. }) 864 | TyKind::Function(FnPointer { substs, .. })
814 | Ty::Tuple(_, substs) 865 | TyKind::Tuple(_, substs)
815 | Ty::OpaqueType(_, substs) 866 | TyKind::OpaqueType(_, substs)
816 | Ty::AssociatedType(_, substs) 867 | TyKind::AssociatedType(_, substs)
817 | Ty::Closure(.., substs) => Some(substs), 868 | TyKind::Closure(.., substs) => Some(substs),
818 _ => None, 869 _ => None,
819 } 870 }
820 } 871 }
821 872
822 pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<GenericPredicate>> { 873 pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<GenericPredicate>> {
823 match self { 874 match self.interned(&Interner) {
824 Ty::OpaqueType(opaque_ty_id, ..) => { 875 TyKind::OpaqueType(opaque_ty_id, ..) => {
825 match opaque_ty_id { 876 match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) {
826 OpaqueTyId::AsyncBlockTypeImplTrait(def, _expr) => { 877 ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => {
827 let krate = def.module(db.upcast()).krate(); 878 let krate = def.module(db.upcast()).krate();
828 if let Some(future_trait) = db 879 if let Some(future_trait) = db
829 .lang_item(krate, "future_trait".into()) 880 .lang_item(krate, "future_trait".into())
@@ -841,32 +892,34 @@ impl Ty {
841 None 892 None
842 } 893 }
843 } 894 }
844 OpaqueTyId::ReturnTypeImplTrait(..) => None, 895 ImplTraitId::ReturnTypeImplTrait(..) => None,
845 } 896 }
846 } 897 }
847 Ty::Alias(AliasTy::Opaque(opaque_ty)) => { 898 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
848 let predicates = match opaque_ty.opaque_ty_id { 899 let predicates = match db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into())
849 OpaqueTyId::ReturnTypeImplTrait(func, idx) => { 900 {
901 ImplTraitId::ReturnTypeImplTrait(func, idx) => {
850 db.return_type_impl_traits(func).map(|it| { 902 db.return_type_impl_traits(func).map(|it| {
851 let data = (*it) 903 let data = (*it)
852 .as_ref() 904 .as_ref()
853 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 905 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
854 data.subst(&opaque_ty.parameters) 906 data.subst(&opaque_ty.substitution)
855 }) 907 })
856 } 908 }
857 // It always has an parameter for Future::Output type. 909 // It always has an parameter for Future::Output type.
858 OpaqueTyId::AsyncBlockTypeImplTrait(..) => unreachable!(), 910 ImplTraitId::AsyncBlockTypeImplTrait(..) => unreachable!(),
859 }; 911 };
860 912
861 predicates.map(|it| it.value) 913 predicates.map(|it| it.value)
862 } 914 }
863 Ty::Placeholder(id) => { 915 TyKind::Placeholder(idx) => {
916 let id = from_placeholder_idx(db, *idx);
864 let generic_params = db.generic_params(id.parent); 917 let generic_params = db.generic_params(id.parent);
865 let param_data = &generic_params.types[id.local_id]; 918 let param_data = &generic_params.types[id.local_id];
866 match param_data.provenance { 919 match param_data.provenance {
867 hir_def::generics::TypeParamProvenance::ArgumentImplTrait => { 920 hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
868 let predicates = db 921 let predicates = db
869 .generic_predicates_for_param(*id) 922 .generic_predicates_for_param(id)
870 .into_iter() 923 .into_iter()
871 .map(|pred| pred.value.clone()) 924 .map(|pred| pred.value.clone())
872 .collect_vec(); 925 .collect_vec();
@@ -881,15 +934,18 @@ impl Ty {
881 } 934 }
882 935
883 pub fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId> { 936 pub fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId> {
884 match self { 937 match self.interned(&Interner) {
885 Ty::AssociatedType(type_alias_id, ..) => { 938 TyKind::AssociatedType(id, ..) => {
886 match type_alias_id.lookup(db.upcast()).container { 939 match from_assoc_type_id(*id).lookup(db.upcast()).container {
887 AssocContainerId::TraitId(trait_id) => Some(trait_id), 940 AssocContainerId::TraitId(trait_id) => Some(trait_id),
888 _ => None, 941 _ => None,
889 } 942 }
890 } 943 }
891 Ty::Alias(AliasTy::Projection(projection_ty)) => { 944 TyKind::Alias(AliasTy::Projection(projection_ty)) => {
892 match projection_ty.associated_ty.lookup(db.upcast()).container { 945 match from_assoc_type_id(projection_ty.associated_ty_id)
946 .lookup(db.upcast())
947 .container
948 {
893 AssocContainerId::TraitId(trait_id) => Some(trait_id), 949 AssocContainerId::TraitId(trait_id) => Some(trait_id),
894 _ => None, 950 _ => None,
895 } 951 }
@@ -908,13 +964,13 @@ pub trait TypeWalk {
908 } 964 }
909 /// Walk the type, counting entered binders. 965 /// Walk the type, counting entered binders.
910 /// 966 ///
911 /// `Ty::Bound` variables use DeBruijn indexing, which means that 0 refers 967 /// `TyKind::Bound` variables use DeBruijn indexing, which means that 0 refers
912 /// to the innermost binder, 1 to the next, etc.. So when we want to 968 /// to the innermost binder, 1 to the next, etc.. So when we want to
913 /// substitute a certain bound variable, we can't just walk the whole type 969 /// substitute a certain bound variable, we can't just walk the whole type
914 /// and blindly replace each instance of a certain index; when we 'enter' 970 /// and blindly replace each instance of a certain index; when we 'enter'
915 /// things that introduce new bound variables, we have to keep track of 971 /// things that introduce new bound variables, we have to keep track of
916 /// that. Currently, the only thing that introduces bound variables on our 972 /// that. Currently, the only thing that introduces bound variables on our
917 /// side are `Ty::Dyn` and `Ty::Opaque`, which each introduce a bound 973 /// side are `TyKind::Dyn` and `TyKind::Opaque`, which each introduce a bound
918 /// variable for the self type. 974 /// variable for the self type.
919 fn walk_mut_binders( 975 fn walk_mut_binders(
920 &mut self, 976 &mut self,
@@ -932,7 +988,7 @@ pub trait TypeWalk {
932 { 988 {
933 self.walk_mut_binders( 989 self.walk_mut_binders(
934 &mut |ty_mut, binders| { 990 &mut |ty_mut, binders| {
935 let ty = mem::replace(ty_mut, Ty::Unknown); 991 let ty = mem::replace(ty_mut, Ty(TyKind::Unknown));
936 *ty_mut = f(ty, binders); 992 *ty_mut = f(ty, binders);
937 }, 993 },
938 binders, 994 binders,
@@ -945,13 +1001,13 @@ pub trait TypeWalk {
945 Self: Sized, 1001 Self: Sized,
946 { 1002 {
947 self.walk_mut(&mut |ty_mut| { 1003 self.walk_mut(&mut |ty_mut| {
948 let ty = mem::replace(ty_mut, Ty::Unknown); 1004 let ty = mem::replace(ty_mut, Ty(TyKind::Unknown));
949 *ty_mut = f(ty); 1005 *ty_mut = f(ty);
950 }); 1006 });
951 self 1007 self
952 } 1008 }
953 1009
954 /// Substitutes `Ty::Bound` vars with the given substitution. 1010 /// Substitutes `TyKind::Bound` vars with the given substitution.
955 fn subst_bound_vars(self, substs: &Substs) -> Self 1011 fn subst_bound_vars(self, substs: &Substs) -> Self
956 where 1012 where
957 Self: Sized, 1013 Self: Sized,
@@ -959,14 +1015,14 @@ pub trait TypeWalk {
959 self.subst_bound_vars_at_depth(substs, DebruijnIndex::INNERMOST) 1015 self.subst_bound_vars_at_depth(substs, DebruijnIndex::INNERMOST)
960 } 1016 }
961 1017
962 /// Substitutes `Ty::Bound` vars with the given substitution. 1018 /// Substitutes `TyKind::Bound` vars with the given substitution.
963 fn subst_bound_vars_at_depth(mut self, substs: &Substs, depth: DebruijnIndex) -> Self 1019 fn subst_bound_vars_at_depth(mut self, substs: &Substs, depth: DebruijnIndex) -> Self
964 where 1020 where
965 Self: Sized, 1021 Self: Sized,
966 { 1022 {
967 self.walk_mut_binders( 1023 self.walk_mut_binders(
968 &mut |ty, binders| { 1024 &mut |ty, binders| {
969 if let &mut Ty::BoundVar(bound) = ty { 1025 if let &mut TyKind::BoundVar(bound) = &mut ty.0 {
970 if bound.debruijn >= binders { 1026 if bound.debruijn >= binders {
971 *ty = substs.0[bound.index].clone().shift_bound_vars(binders); 1027 *ty = substs.0[bound.index].clone().shift_bound_vars(binders);
972 } 1028 }
@@ -977,17 +1033,17 @@ pub trait TypeWalk {
977 self 1033 self
978 } 1034 }
979 1035
980 /// Shifts up debruijn indices of `Ty::Bound` vars by `n`. 1036 /// Shifts up debruijn indices of `TyKind::Bound` vars by `n`.
981 fn shift_bound_vars(self, n: DebruijnIndex) -> Self 1037 fn shift_bound_vars(self, n: DebruijnIndex) -> Self
982 where 1038 where
983 Self: Sized, 1039 Self: Sized,
984 { 1040 {
985 self.fold_binders( 1041 self.fold_binders(
986 &mut |ty, binders| match ty { 1042 &mut |ty, binders| match &ty.0 {
987 Ty::BoundVar(bound) if bound.debruijn >= binders => { 1043 TyKind::BoundVar(bound) if bound.debruijn >= binders => {
988 Ty::BoundVar(bound.shifted_in_from(n)) 1044 TyKind::BoundVar(bound.shifted_in_from(n)).intern(&Interner)
989 } 1045 }
990 ty => ty, 1046 _ => ty,
991 }, 1047 },
992 DebruijnIndex::INNERMOST, 1048 DebruijnIndex::INNERMOST,
993 ) 1049 )
@@ -996,18 +1052,18 @@ pub trait TypeWalk {
996 1052
997impl TypeWalk for Ty { 1053impl TypeWalk for Ty {
998 fn walk(&self, f: &mut impl FnMut(&Ty)) { 1054 fn walk(&self, f: &mut impl FnMut(&Ty)) {
999 match self { 1055 match self.interned(&Interner) {
1000 Ty::Alias(AliasTy::Projection(p_ty)) => { 1056 TyKind::Alias(AliasTy::Projection(p_ty)) => {
1001 for t in p_ty.parameters.iter() { 1057 for t in p_ty.substitution.iter() {
1002 t.walk(f); 1058 t.walk(f);
1003 } 1059 }
1004 } 1060 }
1005 Ty::Alias(AliasTy::Opaque(o_ty)) => { 1061 TyKind::Alias(AliasTy::Opaque(o_ty)) => {
1006 for t in o_ty.parameters.iter() { 1062 for t in o_ty.substitution.iter() {
1007 t.walk(f); 1063 t.walk(f);
1008 } 1064 }
1009 } 1065 }
1010 Ty::Dyn(predicates) => { 1066 TyKind::Dyn(predicates) => {
1011 for p in predicates.iter() { 1067 for p in predicates.iter() {
1012 p.walk(f); 1068 p.walk(f);
1013 } 1069 }
@@ -1028,17 +1084,17 @@ impl TypeWalk for Ty {
1028 f: &mut impl FnMut(&mut Ty, DebruijnIndex), 1084 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
1029 binders: DebruijnIndex, 1085 binders: DebruijnIndex,
1030 ) { 1086 ) {
1031 match self { 1087 match &mut self.0 {
1032 Ty::Alias(AliasTy::Projection(p_ty)) => { 1088 TyKind::Alias(AliasTy::Projection(p_ty)) => {
1033 p_ty.parameters.walk_mut_binders(f, binders); 1089 p_ty.substitution.walk_mut_binders(f, binders);
1034 } 1090 }
1035 Ty::Dyn(predicates) => { 1091 TyKind::Dyn(predicates) => {
1036 for p in make_mut_slice(predicates) { 1092 for p in make_mut_slice(predicates) {
1037 p.walk_mut_binders(f, binders.shifted_in()); 1093 p.walk_mut_binders(f, binders.shifted_in());
1038 } 1094 }
1039 } 1095 }
1040 Ty::Alias(AliasTy::Opaque(o_ty)) => { 1096 TyKind::Alias(AliasTy::Opaque(o_ty)) => {
1041 o_ty.parameters.walk_mut_binders(f, binders); 1097 o_ty.substitution.walk_mut_binders(f, binders);
1042 } 1098 }
1043 _ => { 1099 _ => {
1044 if let Some(substs) = self.substs_mut() { 1100 if let Some(substs) = self.substs_mut() {
@@ -1068,7 +1124,7 @@ impl<T: TypeWalk> TypeWalk for Vec<T> {
1068} 1124}
1069 1125
1070#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] 1126#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
1071pub enum OpaqueTyId { 1127pub enum ImplTraitId {
1072 ReturnTypeImplTrait(hir_def::FunctionId, u16), 1128 ReturnTypeImplTrait(hir_def::FunctionId, u16),
1073 AsyncBlockTypeImplTrait(hir_def::DefWithBodyId, ExprId), 1129 AsyncBlockTypeImplTrait(hir_def::DefWithBodyId, ExprId),
1074} 1130}
@@ -1082,3 +1138,33 @@ pub struct ReturnTypeImplTraits {
1082pub(crate) struct ReturnTypeImplTrait { 1138pub(crate) struct ReturnTypeImplTrait {
1083 pub(crate) bounds: Binders<Vec<GenericPredicate>>, 1139 pub(crate) bounds: Binders<Vec<GenericPredicate>>,
1084} 1140}
1141
1142pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId {
1143 chalk_ir::ForeignDefId(salsa::InternKey::as_intern_id(&id))
1144}
1145
1146pub fn from_foreign_def_id(id: ForeignDefId) -> TypeAliasId {
1147 salsa::InternKey::from_intern_id(id.0)
1148}
1149
1150pub fn to_assoc_type_id(id: TypeAliasId) -> AssocTypeId {
1151 chalk_ir::AssocTypeId(salsa::InternKey::as_intern_id(&id))
1152}
1153
1154pub fn from_assoc_type_id(id: AssocTypeId) -> TypeAliasId {
1155 salsa::InternKey::from_intern_id(id.0)
1156}
1157
1158pub fn from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> TypeParamId {
1159 assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
1160 let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx));
1161 db.lookup_intern_type_param_id(interned_id)
1162}
1163
1164pub fn to_placeholder_idx(db: &dyn HirDatabase, id: TypeParamId) -> PlaceholderIndex {
1165 let interned_id = db.intern_type_param_id(id);
1166 PlaceholderIndex {
1167 ui: chalk_ir::UniverseIndex::ROOT,
1168 idx: salsa::InternKey::as_intern_id(&interned_id).as_usize(),
1169 }
1170}
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index 5fa83567b..d026310f4 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -8,7 +8,7 @@
8use std::{iter, sync::Arc}; 8use std::{iter, sync::Arc};
9 9
10use base_db::CrateId; 10use base_db::CrateId;
11use chalk_ir::Mutability; 11use chalk_ir::{cast::Cast, Mutability, Safety};
12use hir_def::{ 12use hir_def::{
13 adt::StructKind, 13 adt::StructKind,
14 builtin_type::BuiltinType, 14 builtin_type::BuiltinType,
@@ -27,13 +27,15 @@ use stdx::impl_from;
27 27
28use crate::{ 28use crate::{
29 db::HirDatabase, 29 db::HirDatabase,
30 to_assoc_type_id, to_placeholder_idx,
31 traits::chalk::{Interner, ToChalk},
30 utils::{ 32 utils::{
31 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,
32 make_mut_slice, variant_data, 34 make_mut_slice, variant_data,
33 }, 35 },
34 AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, FnPointer, FnSig, GenericPredicate, 36 AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, FnPointer, FnSig, GenericPredicate,
35 OpaqueTy, OpaqueTyId, PolyFnSig, ProjectionPredicate, ProjectionTy, ReturnTypeImplTrait, 37 ImplTraitId, OpaqueTy, PolyFnSig, ProjectionPredicate, ProjectionTy, ReturnTypeImplTrait,
36 ReturnTypeImplTraits, Substs, TraitEnvironment, TraitRef, Ty, TypeWalk, 38 ReturnTypeImplTraits, Substs, TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk,
37}; 39};
38 40
39#[derive(Debug)] 41#[derive(Debug)]
@@ -138,69 +140,71 @@ pub enum TypeParamLoweringMode {
138 Variable, 140 Variable,
139} 141}
140 142
141impl Ty { 143impl<'a> TyLoweringContext<'a> {
142 pub fn from_hir(ctx: &TyLoweringContext<'_>, type_ref: &TypeRef) -> Self { 144 pub fn lower_ty(&self, type_ref: &TypeRef) -> Ty {
143 Ty::from_hir_ext(ctx, type_ref).0 145 self.lower_ty_ext(type_ref).0
144 } 146 }
145 pub fn from_hir_ext(ctx: &TyLoweringContext<'_>, type_ref: &TypeRef) -> (Self, Option<TypeNs>) { 147
148 fn lower_ty_ext(&self, type_ref: &TypeRef) -> (Ty, Option<TypeNs>) {
146 let mut res = None; 149 let mut res = None;
147 let ty = match type_ref { 150 let ty = match type_ref {
148 TypeRef::Never => Ty::Never, 151 TypeRef::Never => TyKind::Never.intern(&Interner),
149 TypeRef::Tuple(inner) => { 152 TypeRef::Tuple(inner) => {
150 let inner_tys: Arc<[Ty]> = inner.iter().map(|tr| Ty::from_hir(ctx, tr)).collect(); 153 let inner_tys: Arc<[Ty]> = inner.iter().map(|tr| self.lower_ty(tr)).collect();
151 Ty::Tuple(inner_tys.len(), Substs(inner_tys)) 154 TyKind::Tuple(inner_tys.len(), Substs(inner_tys)).intern(&Interner)
152 } 155 }
153 TypeRef::Path(path) => { 156 TypeRef::Path(path) => {
154 let (ty, res_) = Ty::from_hir_path(ctx, path); 157 let (ty, res_) = self.lower_path(path);
155 res = res_; 158 res = res_;
156 ty 159 ty
157 } 160 }
158 TypeRef::RawPtr(inner, mutability) => { 161 TypeRef::RawPtr(inner, mutability) => {
159 let inner_ty = Ty::from_hir(ctx, inner); 162 let inner_ty = self.lower_ty(inner);
160 Ty::Raw(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty)) 163 TyKind::Raw(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty))
164 .intern(&Interner)
161 } 165 }
162 TypeRef::Array(inner) => { 166 TypeRef::Array(inner) => {
163 let inner_ty = Ty::from_hir(ctx, inner); 167 let inner_ty = self.lower_ty(inner);
164 Ty::Array(Substs::single(inner_ty)) 168 TyKind::Array(Substs::single(inner_ty)).intern(&Interner)
165 } 169 }
166 TypeRef::Slice(inner) => { 170 TypeRef::Slice(inner) => {
167 let inner_ty = Ty::from_hir(ctx, inner); 171 let inner_ty = self.lower_ty(inner);
168 Ty::Slice(Substs::single(inner_ty)) 172 TyKind::Slice(Substs::single(inner_ty)).intern(&Interner)
169 } 173 }
170 TypeRef::Reference(inner, _, mutability) => { 174 TypeRef::Reference(inner, _, mutability) => {
171 let inner_ty = Ty::from_hir(ctx, inner); 175 let inner_ty = self.lower_ty(inner);
172 Ty::Ref(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty)) 176 TyKind::Ref(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty))
177 .intern(&Interner)
173 } 178 }
174 TypeRef::Placeholder => Ty::Unknown, 179 TypeRef::Placeholder => TyKind::Unknown.intern(&Interner),
175 TypeRef::Fn(params, is_varargs) => { 180 TypeRef::Fn(params, is_varargs) => {
176 let substs = Substs(params.iter().map(|tr| Ty::from_hir(ctx, tr)).collect()); 181 let substs = Substs(params.iter().map(|tr| self.lower_ty(tr)).collect());
177 Ty::Function(FnPointer { 182 TyKind::Function(FnPointer {
178 num_args: substs.len() - 1, 183 num_args: substs.len() - 1,
179 sig: FnSig { variadic: *is_varargs }, 184 sig: FnSig { abi: (), safety: Safety::Safe, variadic: *is_varargs },
180 substs, 185 substs,
181 }) 186 })
187 .intern(&Interner)
182 } 188 }
183 TypeRef::DynTrait(bounds) => { 189 TypeRef::DynTrait(bounds) => {
184 let self_ty = Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)); 190 let self_ty =
185 let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| { 191 TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner);
186 bounds 192 let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
187 .iter() 193 bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone())).collect()
188 .flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone()))
189 .collect()
190 }); 194 });
191 Ty::Dyn(predicates) 195 TyKind::Dyn(predicates).intern(&Interner)
192 } 196 }
193 TypeRef::ImplTrait(bounds) => { 197 TypeRef::ImplTrait(bounds) => {
194 match ctx.impl_trait_mode { 198 match self.impl_trait_mode {
195 ImplTraitLoweringMode::Opaque => { 199 ImplTraitLoweringMode::Opaque => {
196 let idx = ctx.impl_trait_counter.get(); 200 let idx = self.impl_trait_counter.get();
197 ctx.impl_trait_counter.set(idx + 1); 201 self.impl_trait_counter.set(idx + 1);
198 202
199 assert!(idx as usize == ctx.opaque_type_data.borrow().len()); 203 assert!(idx as usize == self.opaque_type_data.borrow().len());
200 // this dance is to make sure the data is in the right 204 // this dance is to make sure the data is in the right
201 // place even if we encounter more opaque types while 205 // place even if we encounter more opaque types while
202 // lowering the bounds 206 // lowering the bounds
203 ctx.opaque_type_data 207 self.opaque_type_data
204 .borrow_mut() 208 .borrow_mut()
205 .push(ReturnTypeImplTrait { bounds: Binders::new(1, Vec::new()) }); 209 .push(ReturnTypeImplTrait { bounds: Binders::new(1, Vec::new()) });
206 // We don't want to lower the bounds inside the binders 210 // We don't want to lower the bounds inside the binders
@@ -212,65 +216,70 @@ impl Ty {
212 // other, but separately. So if the `T` refers to a type 216 // other, but separately. So if the `T` refers to a type
213 // parameter of the outer function, it's just one binder 217 // parameter of the outer function, it's just one binder
214 // away instead of two. 218 // away instead of two.
215 let actual_opaque_type_data = ctx 219 let actual_opaque_type_data = self
216 .with_debruijn(DebruijnIndex::INNERMOST, |ctx| { 220 .with_debruijn(DebruijnIndex::INNERMOST, |ctx| {
217 ReturnTypeImplTrait::from_hir(ctx, &bounds) 221 ctx.lower_impl_trait(&bounds)
218 }); 222 });
219 ctx.opaque_type_data.borrow_mut()[idx as usize] = actual_opaque_type_data; 223 self.opaque_type_data.borrow_mut()[idx as usize] = actual_opaque_type_data;
220 224
221 let func = match ctx.resolver.generic_def() { 225 let func = match self.resolver.generic_def() {
222 Some(GenericDefId::FunctionId(f)) => f, 226 Some(GenericDefId::FunctionId(f)) => f,
223 _ => panic!("opaque impl trait lowering in non-function"), 227 _ => panic!("opaque impl trait lowering in non-function"),
224 }; 228 };
225 let impl_trait_id = OpaqueTyId::ReturnTypeImplTrait(func, idx); 229 let impl_trait_id = ImplTraitId::ReturnTypeImplTrait(func, idx);
226 let generics = generics(ctx.db.upcast(), func.into()); 230 let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
227 let parameters = Substs::bound_vars(&generics, ctx.in_binders); 231 let generics = generics(self.db.upcast(), func.into());
228 Ty::Alias(AliasTy::Opaque(OpaqueTy { 232 let parameters = Substs::bound_vars(&generics, self.in_binders);
229 opaque_ty_id: impl_trait_id, 233 TyKind::Alias(AliasTy::Opaque(OpaqueTy {
230 parameters, 234 opaque_ty_id,
235 substitution: parameters,
231 })) 236 }))
237 .intern(&Interner)
232 } 238 }
233 ImplTraitLoweringMode::Param => { 239 ImplTraitLoweringMode::Param => {
234 let idx = ctx.impl_trait_counter.get(); 240 let idx = self.impl_trait_counter.get();
235 // FIXME we're probably doing something wrong here 241 // FIXME we're probably doing something wrong here
236 ctx.impl_trait_counter.set(idx + count_impl_traits(type_ref) as u16); 242 self.impl_trait_counter.set(idx + count_impl_traits(type_ref) as u16);
237 if let Some(def) = ctx.resolver.generic_def() { 243 if let Some(def) = self.resolver.generic_def() {
238 let generics = generics(ctx.db.upcast(), def); 244 let generics = generics(self.db.upcast(), def);
239 let param = generics 245 let param = generics
240 .iter() 246 .iter()
241 .filter(|(_, data)| { 247 .filter(|(_, data)| {
242 data.provenance == TypeParamProvenance::ArgumentImplTrait 248 data.provenance == TypeParamProvenance::ArgumentImplTrait
243 }) 249 })
244 .nth(idx as usize) 250 .nth(idx as usize)
245 .map_or(Ty::Unknown, |(id, _)| Ty::Placeholder(id)); 251 .map_or(TyKind::Unknown, |(id, _)| {
246 param 252 TyKind::Placeholder(to_placeholder_idx(self.db, id))
253 });
254 param.intern(&Interner)
247 } else { 255 } else {
248 Ty::Unknown 256 TyKind::Unknown.intern(&Interner)
249 } 257 }
250 } 258 }
251 ImplTraitLoweringMode::Variable => { 259 ImplTraitLoweringMode::Variable => {
252 let idx = ctx.impl_trait_counter.get(); 260 let idx = self.impl_trait_counter.get();
253 // FIXME we're probably doing something wrong here 261 // FIXME we're probably doing something wrong here
254 ctx.impl_trait_counter.set(idx + count_impl_traits(type_ref) as u16); 262 self.impl_trait_counter.set(idx + count_impl_traits(type_ref) as u16);
255 let (parent_params, self_params, list_params, _impl_trait_params) = 263 let (parent_params, self_params, list_params, _impl_trait_params) =
256 if let Some(def) = ctx.resolver.generic_def() { 264 if let Some(def) = self.resolver.generic_def() {
257 let generics = generics(ctx.db.upcast(), def); 265 let generics = generics(self.db.upcast(), def);
258 generics.provenance_split() 266 generics.provenance_split()
259 } else { 267 } else {
260 (0, 0, 0, 0) 268 (0, 0, 0, 0)
261 }; 269 };
262 Ty::BoundVar(BoundVar::new( 270 TyKind::BoundVar(BoundVar::new(
263 ctx.in_binders, 271 self.in_binders,
264 idx as usize + parent_params + self_params + list_params, 272 idx as usize + parent_params + self_params + list_params,
265 )) 273 ))
274 .intern(&Interner)
266 } 275 }
267 ImplTraitLoweringMode::Disallowed => { 276 ImplTraitLoweringMode::Disallowed => {
268 // FIXME: report error 277 // FIXME: report error
269 Ty::Unknown 278 TyKind::Unknown.intern(&Interner)
270 } 279 }
271 } 280 }
272 } 281 }
273 TypeRef::Error => Ty::Unknown, 282 TypeRef::Error => TyKind::Unknown.intern(&Interner),
274 }; 283 };
275 (ty, res) 284 (ty, res)
276 } 285 }
@@ -278,7 +287,7 @@ impl Ty {
278 /// This is only for `generic_predicates_for_param`, where we can't just 287 /// This is only for `generic_predicates_for_param`, where we can't just
279 /// lower the self types of the predicates since that could lead to cycles. 288 /// lower the self types of the predicates since that could lead to cycles.
280 /// So we just check here if the `type_ref` resolves to a generic param, and which. 289 /// So we just check here if the `type_ref` resolves to a generic param, and which.
281 fn from_hir_only_param(ctx: &TyLoweringContext<'_>, type_ref: &TypeRef) -> Option<TypeParamId> { 290 fn lower_ty_only_param(&self, type_ref: &TypeRef) -> Option<TypeParamId> {
282 let path = match type_ref { 291 let path = match type_ref {
283 TypeRef::Path(path) => path, 292 TypeRef::Path(path) => path,
284 _ => return None, 293 _ => return None,
@@ -290,7 +299,7 @@ impl Ty {
290 return None; 299 return None;
291 } 300 }
292 let resolution = 301 let resolution =
293 match ctx.resolver.resolve_path_in_type_ns(ctx.db.upcast(), path.mod_path()) { 302 match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path.mod_path()) {
294 Some((it, None)) => it, 303 Some((it, None)) => it,
295 _ => return None, 304 _ => return None,
296 }; 305 };
@@ -301,8 +310,8 @@ impl Ty {
301 } 310 }
302 } 311 }
303 312
304 pub(crate) fn from_type_relative_path( 313 pub(crate) fn lower_ty_relative_path(
305 ctx: &TyLoweringContext<'_>, 314 &self,
306 ty: Ty, 315 ty: Ty,
307 // We need the original resolution to lower `Self::AssocTy` correctly 316 // We need the original resolution to lower `Self::AssocTy` correctly
308 res: Option<TypeNs>, 317 res: Option<TypeNs>,
@@ -311,17 +320,17 @@ impl Ty {
311 if remaining_segments.len() == 1 { 320 if remaining_segments.len() == 1 {
312 // resolve unselected assoc types 321 // resolve unselected assoc types
313 let segment = remaining_segments.first().unwrap(); 322 let segment = remaining_segments.first().unwrap();
314 (Ty::select_associated_type(ctx, res, segment), None) 323 (self.select_associated_type(res, segment), None)
315 } else if remaining_segments.len() > 1 { 324 } else if remaining_segments.len() > 1 {
316 // FIXME report error (ambiguous associated type) 325 // FIXME report error (ambiguous associated type)
317 (Ty::Unknown, None) 326 (TyKind::Unknown.intern(&Interner), None)
318 } else { 327 } else {
319 (ty, res) 328 (ty, res)
320 } 329 }
321 } 330 }
322 331
323 pub(crate) fn from_partly_resolved_hir_path( 332 pub(crate) fn lower_partly_resolved_path(
324 ctx: &TyLoweringContext<'_>, 333 &self,
325 resolution: TypeNs, 334 resolution: TypeNs,
326 resolved_segment: PathSegment<'_>, 335 resolved_segment: PathSegment<'_>,
327 remaining_segments: PathSegments<'_>, 336 remaining_segments: PathSegments<'_>,
@@ -331,103 +340,109 @@ impl Ty {
331 TypeNs::TraitId(trait_) => { 340 TypeNs::TraitId(trait_) => {
332 // if this is a bare dyn Trait, we'll directly put the required ^0 for the self type in there 341 // if this is a bare dyn Trait, we'll directly put the required ^0 for the self type in there
333 let self_ty = if remaining_segments.len() == 0 { 342 let self_ty = if remaining_segments.len() == 0 {
334 Some(Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))) 343 Some(
344 TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
345 .intern(&Interner),
346 )
335 } else { 347 } else {
336 None 348 None
337 }; 349 };
338 let trait_ref = 350 let trait_ref =
339 TraitRef::from_resolved_path(ctx, trait_, resolved_segment, self_ty); 351 self.lower_trait_ref_from_resolved_path(trait_, resolved_segment, self_ty);
340 let ty = if remaining_segments.len() == 1 { 352 let ty = if remaining_segments.len() == 1 {
341 let segment = remaining_segments.first().unwrap(); 353 let segment = remaining_segments.first().unwrap();
342 let found = associated_type_by_name_including_super_traits( 354 let found = associated_type_by_name_including_super_traits(
343 ctx.db, 355 self.db,
344 trait_ref, 356 trait_ref,
345 &segment.name, 357 &segment.name,
346 ); 358 );
347 match found { 359 match found {
348 Some((super_trait_ref, associated_ty)) => { 360 Some((super_trait_ref, associated_ty)) => {
349 // FIXME handle type parameters on the segment 361 // FIXME handle type parameters on the segment
350 Ty::Alias(AliasTy::Projection(ProjectionTy { 362 TyKind::Alias(AliasTy::Projection(ProjectionTy {
351 associated_ty, 363 associated_ty_id: to_assoc_type_id(associated_ty),
352 parameters: super_trait_ref.substs, 364 substitution: super_trait_ref.substs,
353 })) 365 }))
366 .intern(&Interner)
354 } 367 }
355 None => { 368 None => {
356 // FIXME: report error (associated type not found) 369 // FIXME: report error (associated type not found)
357 Ty::Unknown 370 TyKind::Unknown.intern(&Interner)
358 } 371 }
359 } 372 }
360 } else if remaining_segments.len() > 1 { 373 } else if remaining_segments.len() > 1 {
361 // FIXME report error (ambiguous associated type) 374 // FIXME report error (ambiguous associated type)
362 Ty::Unknown 375 TyKind::Unknown.intern(&Interner)
363 } else { 376 } else {
364 Ty::Dyn(Arc::new([GenericPredicate::Implemented(trait_ref)])) 377 TyKind::Dyn(Arc::new([GenericPredicate::Implemented(trait_ref)]))
378 .intern(&Interner)
365 }; 379 };
366 return (ty, None); 380 return (ty, None);
367 } 381 }
368 TypeNs::GenericParam(param_id) => { 382 TypeNs::GenericParam(param_id) => {
369 let generics = generics( 383 let generics = generics(
370 ctx.db.upcast(), 384 self.db.upcast(),
371 ctx.resolver.generic_def().expect("generics in scope"), 385 self.resolver.generic_def().expect("generics in scope"),
372 ); 386 );
373 match ctx.type_param_mode { 387 match self.type_param_mode {
374 TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id), 388 TypeParamLoweringMode::Placeholder => {
389 TyKind::Placeholder(to_placeholder_idx(self.db, param_id))
390 }
375 TypeParamLoweringMode::Variable => { 391 TypeParamLoweringMode::Variable => {
376 let idx = generics.param_idx(param_id).expect("matching generics"); 392 let idx = generics.param_idx(param_id).expect("matching generics");
377 Ty::BoundVar(BoundVar::new(ctx.in_binders, idx)) 393 TyKind::BoundVar(BoundVar::new(self.in_binders, idx))
378 } 394 }
379 } 395 }
396 .intern(&Interner)
380 } 397 }
381 TypeNs::SelfType(impl_id) => { 398 TypeNs::SelfType(impl_id) => {
382 let generics = generics(ctx.db.upcast(), impl_id.into()); 399 let generics = generics(self.db.upcast(), impl_id.into());
383 let substs = match ctx.type_param_mode { 400 let substs = match self.type_param_mode {
384 TypeParamLoweringMode::Placeholder => { 401 TypeParamLoweringMode::Placeholder => {
385 Substs::type_params_for_generics(&generics) 402 Substs::type_params_for_generics(self.db, &generics)
386 } 403 }
387 TypeParamLoweringMode::Variable => { 404 TypeParamLoweringMode::Variable => {
388 Substs::bound_vars(&generics, ctx.in_binders) 405 Substs::bound_vars(&generics, self.in_binders)
389 } 406 }
390 }; 407 };
391 ctx.db.impl_self_ty(impl_id).subst(&substs) 408 self.db.impl_self_ty(impl_id).subst(&substs)
392 } 409 }
393 TypeNs::AdtSelfType(adt) => { 410 TypeNs::AdtSelfType(adt) => {
394 let generics = generics(ctx.db.upcast(), adt.into()); 411 let generics = generics(self.db.upcast(), adt.into());
395 let substs = match ctx.type_param_mode { 412 let substs = match self.type_param_mode {
396 TypeParamLoweringMode::Placeholder => { 413 TypeParamLoweringMode::Placeholder => {
397 Substs::type_params_for_generics(&generics) 414 Substs::type_params_for_generics(self.db, &generics)
398 } 415 }
399 TypeParamLoweringMode::Variable => { 416 TypeParamLoweringMode::Variable => {
400 Substs::bound_vars(&generics, ctx.in_binders) 417 Substs::bound_vars(&generics, self.in_binders)
401 } 418 }
402 }; 419 };
403 ctx.db.ty(adt.into()).subst(&substs) 420 self.db.ty(adt.into()).subst(&substs)
404 } 421 }
405 422
406 TypeNs::AdtId(it) => { 423 TypeNs::AdtId(it) => self.lower_path_inner(resolved_segment, it.into(), infer_args),
407 Ty::from_hir_path_inner(ctx, resolved_segment, it.into(), infer_args)
408 }
409 TypeNs::BuiltinType(it) => { 424 TypeNs::BuiltinType(it) => {
410 Ty::from_hir_path_inner(ctx, resolved_segment, it.into(), infer_args) 425 self.lower_path_inner(resolved_segment, it.into(), infer_args)
411 } 426 }
412 TypeNs::TypeAliasId(it) => { 427 TypeNs::TypeAliasId(it) => {
413 Ty::from_hir_path_inner(ctx, resolved_segment, it.into(), infer_args) 428 self.lower_path_inner(resolved_segment, it.into(), infer_args)
414 } 429 }
415 // FIXME: report error 430 // FIXME: report error
416 TypeNs::EnumVariantId(_) => return (Ty::Unknown, None), 431 TypeNs::EnumVariantId(_) => return (TyKind::Unknown.intern(&Interner), None),
417 }; 432 };
418 Ty::from_type_relative_path(ctx, ty, Some(resolution), remaining_segments) 433 self.lower_ty_relative_path(ty, Some(resolution), remaining_segments)
419 } 434 }
420 435
421 pub(crate) fn from_hir_path(ctx: &TyLoweringContext<'_>, path: &Path) -> (Ty, Option<TypeNs>) { 436 pub(crate) fn lower_path(&self, path: &Path) -> (Ty, Option<TypeNs>) {
422 // Resolve the path (in type namespace) 437 // Resolve the path (in type namespace)
423 if let Some(type_ref) = path.type_anchor() { 438 if let Some(type_ref) = path.type_anchor() {
424 let (ty, res) = Ty::from_hir_ext(ctx, &type_ref); 439 let (ty, res) = self.lower_ty_ext(&type_ref);
425 return Ty::from_type_relative_path(ctx, ty, res, path.segments()); 440 return self.lower_ty_relative_path(ty, res, path.segments());
426 } 441 }
427 let (resolution, remaining_index) = 442 let (resolution, remaining_index) =
428 match ctx.resolver.resolve_path_in_type_ns(ctx.db.upcast(), path.mod_path()) { 443 match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path.mod_path()) {
429 Some(it) => it, 444 Some(it) => it,
430 None => return (Ty::Unknown, None), 445 None => return (TyKind::Unknown.intern(&Interner), None),
431 }; 446 };
432 let (resolved_segment, remaining_segments) = match remaining_index { 447 let (resolved_segment, remaining_segments) = match remaining_index {
433 None => ( 448 None => (
@@ -436,31 +451,23 @@ impl Ty {
436 ), 451 ),
437 Some(i) => (path.segments().get(i - 1).unwrap(), path.segments().skip(i)), 452 Some(i) => (path.segments().get(i - 1).unwrap(), path.segments().skip(i)),
438 }; 453 };
439 Ty::from_partly_resolved_hir_path( 454 self.lower_partly_resolved_path(resolution, resolved_segment, remaining_segments, false)
440 ctx,
441 resolution,
442 resolved_segment,
443 remaining_segments,
444 false,
445 )
446 } 455 }
447 456
448 fn select_associated_type( 457 fn select_associated_type(&self, res: Option<TypeNs>, segment: PathSegment<'_>) -> Ty {
449 ctx: &TyLoweringContext<'_>,
450 res: Option<TypeNs>,
451 segment: PathSegment<'_>,
452 ) -> Ty {
453 if let Some(res) = res { 458 if let Some(res) = res {
454 let ty = 459 let ty = associated_type_shorthand_candidates(
455 associated_type_shorthand_candidates(ctx.db, res, move |name, t, associated_ty| { 460 self.db,
461 res,
462 move |name, t, associated_ty| {
456 if name == segment.name { 463 if name == segment.name {
457 let substs = match ctx.type_param_mode { 464 let substs = match self.type_param_mode {
458 TypeParamLoweringMode::Placeholder => { 465 TypeParamLoweringMode::Placeholder => {
459 // if we're lowering to placeholders, we have to put 466 // if we're lowering to placeholders, we have to put
460 // them in now 467 // them in now
461 let s = Substs::type_params( 468 let s = Substs::type_params(
462 ctx.db, 469 self.db,
463 ctx.resolver.generic_def().expect( 470 self.resolver.generic_def().expect(
464 "there should be generics if there's a generic param", 471 "there should be generics if there's a generic param",
465 ), 472 ),
466 ); 473 );
@@ -470,25 +477,29 @@ impl Ty {
470 }; 477 };
471 // We need to shift in the bound vars, since 478 // We need to shift in the bound vars, since
472 // associated_type_shorthand_candidates does not do that 479 // associated_type_shorthand_candidates does not do that
473 let substs = substs.shift_bound_vars(ctx.in_binders); 480 let substs = substs.shift_bound_vars(self.in_binders);
474 // FIXME handle type parameters on the segment 481 // FIXME handle type parameters on the segment
475 return Some(Ty::Alias(AliasTy::Projection(ProjectionTy { 482 return Some(
476 associated_ty, 483 TyKind::Alias(AliasTy::Projection(ProjectionTy {
477 parameters: substs, 484 associated_ty_id: to_assoc_type_id(associated_ty),
478 }))); 485 substitution: substs,
486 }))
487 .intern(&Interner),
488 );
479 } 489 }
480 490
481 None 491 None
482 }); 492 },
493 );
483 494
484 ty.unwrap_or(Ty::Unknown) 495 ty.unwrap_or(TyKind::Unknown.intern(&Interner))
485 } else { 496 } else {
486 Ty::Unknown 497 TyKind::Unknown.intern(&Interner)
487 } 498 }
488 } 499 }
489 500
490 fn from_hir_path_inner( 501 fn lower_path_inner(
491 ctx: &TyLoweringContext<'_>, 502 &self,
492 segment: PathSegment<'_>, 503 segment: PathSegment<'_>,
493 typeable: TyDefId, 504 typeable: TyDefId,
494 infer_args: bool, 505 infer_args: bool,
@@ -498,14 +509,14 @@ impl Ty {
498 TyDefId::AdtId(it) => Some(it.into()), 509 TyDefId::AdtId(it) => Some(it.into()),
499 TyDefId::TypeAliasId(it) => Some(it.into()), 510 TyDefId::TypeAliasId(it) => Some(it.into()),
500 }; 511 };
501 let substs = substs_from_path_segment(ctx, segment, generic_def, infer_args); 512 let substs = self.substs_from_path_segment(segment, generic_def, infer_args);
502 ctx.db.ty(typeable).subst(&substs) 513 self.db.ty(typeable).subst(&substs)
503 } 514 }
504 515
505 /// Collect generic arguments from a path into a `Substs`. See also 516 /// Collect generic arguments from a path into a `Substs`. See also
506 /// `create_substs_for_ast_path` and `def_to_ty` in rustc. 517 /// `create_substs_for_ast_path` and `def_to_ty` in rustc.
507 pub(super) fn substs_from_path( 518 pub(super) fn substs_from_path(
508 ctx: &TyLoweringContext<'_>, 519 &self,
509 path: &Path, 520 path: &Path,
510 // Note that we don't call `db.value_type(resolved)` here, 521 // Note that we don't call `db.value_type(resolved)` here,
511 // `ValueTyDefId` is just a convenient way to pass generics and 522 // `ValueTyDefId` is just a convenient way to pass generics and
@@ -535,169 +546,161 @@ impl Ty {
535 (segment, Some(var.parent.into())) 546 (segment, Some(var.parent.into()))
536 } 547 }
537 }; 548 };
538 substs_from_path_segment(ctx, segment, generic_def, infer_args) 549 self.substs_from_path_segment(segment, generic_def, infer_args)
539 } 550 }
540}
541 551
542fn substs_from_path_segment( 552 fn substs_from_path_segment(
543 ctx: &TyLoweringContext<'_>, 553 &self,
544 segment: PathSegment<'_>, 554 segment: PathSegment<'_>,
545 def_generic: Option<GenericDefId>, 555 def_generic: Option<GenericDefId>,
546 infer_args: bool, 556 infer_args: bool,
547) -> Substs { 557 ) -> Substs {
548 let mut substs = Vec::new(); 558 let mut substs = Vec::new();
549 let def_generics = def_generic.map(|def| generics(ctx.db.upcast(), def)); 559 let def_generics = def_generic.map(|def| generics(self.db.upcast(), def));
550 560
551 let (parent_params, self_params, type_params, impl_trait_params) = 561 let (parent_params, self_params, type_params, impl_trait_params) =
552 def_generics.map_or((0, 0, 0, 0), |g| g.provenance_split()); 562 def_generics.map_or((0, 0, 0, 0), |g| g.provenance_split());
553 let total_len = parent_params + self_params + type_params + impl_trait_params; 563 let total_len = parent_params + self_params + type_params + impl_trait_params;
554 564
555 substs.extend(iter::repeat(Ty::Unknown).take(parent_params)); 565 substs.extend(iter::repeat(TyKind::Unknown.intern(&Interner)).take(parent_params));
556 566
557 let mut had_explicit_type_args = false; 567 let mut had_explicit_type_args = false;
558 568
559 if let Some(generic_args) = &segment.args_and_bindings { 569 if let Some(generic_args) = &segment.args_and_bindings {
560 if !generic_args.has_self_type { 570 if !generic_args.has_self_type {
561 substs.extend(iter::repeat(Ty::Unknown).take(self_params)); 571 substs.extend(iter::repeat(TyKind::Unknown.intern(&Interner)).take(self_params));
562 } 572 }
563 let expected_num = 573 let expected_num =
564 if generic_args.has_self_type { self_params + type_params } else { type_params }; 574 if generic_args.has_self_type { self_params + type_params } else { type_params };
565 let skip = if generic_args.has_self_type && self_params == 0 { 1 } else { 0 }; 575 let skip = if generic_args.has_self_type && self_params == 0 { 1 } else { 0 };
566 // if args are provided, it should be all of them, but we can't rely on that 576 // if args are provided, it should be all of them, but we can't rely on that
567 for arg in generic_args 577 for arg in generic_args
568 .args 578 .args
569 .iter() 579 .iter()
570 .filter(|arg| matches!(arg, GenericArg::Type(_))) 580 .filter(|arg| matches!(arg, GenericArg::Type(_)))
571 .skip(skip) 581 .skip(skip)
572 .take(expected_num) 582 .take(expected_num)
573 { 583 {
574 match arg { 584 match arg {
575 GenericArg::Type(type_ref) => { 585 GenericArg::Type(type_ref) => {
576 had_explicit_type_args = true; 586 had_explicit_type_args = true;
577 let ty = Ty::from_hir(ctx, type_ref); 587 let ty = self.lower_ty(type_ref);
578 substs.push(ty); 588 substs.push(ty);
589 }
590 GenericArg::Lifetime(_) => {}
579 } 591 }
580 GenericArg::Lifetime(_) => {}
581 } 592 }
582 } 593 }
583 }
584 594
585 // handle defaults. In expression or pattern path segments without 595 // handle defaults. In expression or pattern path segments without
586 // explicitly specified type arguments, missing type arguments are inferred 596 // explicitly specified type arguments, missing type arguments are inferred
587 // (i.e. defaults aren't used). 597 // (i.e. defaults aren't used).
588 if !infer_args || had_explicit_type_args { 598 if !infer_args || had_explicit_type_args {
589 if let Some(def_generic) = def_generic { 599 if let Some(def_generic) = def_generic {
590 let defaults = ctx.db.generic_defaults(def_generic); 600 let defaults = self.db.generic_defaults(def_generic);
591 assert_eq!(total_len, defaults.len()); 601 assert_eq!(total_len, defaults.len());
592 602
593 for default_ty in defaults.iter().skip(substs.len()) { 603 for default_ty in defaults.iter().skip(substs.len()) {
594 // each default can depend on the previous parameters 604 // each default can depend on the previous parameters
595 let substs_so_far = Substs(substs.clone().into()); 605 let substs_so_far = Substs(substs.clone().into());
596 substs.push(default_ty.clone().subst(&substs_so_far)); 606 substs.push(default_ty.clone().subst(&substs_so_far));
607 }
597 } 608 }
598 } 609 }
599 }
600 610
601 // add placeholders for args that were not provided 611 // add placeholders for args that were not provided
602 // FIXME: emit diagnostics in contexts where this is not allowed 612 // FIXME: emit diagnostics in contexts where this is not allowed
603 for _ in substs.len()..total_len { 613 for _ in substs.len()..total_len {
604 substs.push(Ty::Unknown); 614 substs.push(TyKind::Unknown.intern(&Interner));
605 } 615 }
606 assert_eq!(substs.len(), total_len); 616 assert_eq!(substs.len(), total_len);
607 617
608 Substs(substs.into()) 618 Substs(substs.into())
609} 619 }
610 620
611impl TraitRef { 621 fn lower_trait_ref_from_path(
612 fn from_path( 622 &self,
613 ctx: &TyLoweringContext<'_>,
614 path: &Path, 623 path: &Path,
615 explicit_self_ty: Option<Ty>, 624 explicit_self_ty: Option<Ty>,
616 ) -> Option<Self> { 625 ) -> Option<TraitRef> {
617 let resolved = 626 let resolved =
618 match ctx.resolver.resolve_path_in_type_ns_fully(ctx.db.upcast(), path.mod_path())? { 627 match self.resolver.resolve_path_in_type_ns_fully(self.db.upcast(), path.mod_path())? {
619 TypeNs::TraitId(tr) => tr, 628 TypeNs::TraitId(tr) => tr,
620 _ => return None, 629 _ => return None,
621 }; 630 };
622 let segment = path.segments().last().expect("path should have at least one segment"); 631 let segment = path.segments().last().expect("path should have at least one segment");
623 Some(TraitRef::from_resolved_path(ctx, resolved, segment, explicit_self_ty)) 632 Some(self.lower_trait_ref_from_resolved_path(resolved, segment, explicit_self_ty))
624 } 633 }
625 634
626 pub(crate) fn from_resolved_path( 635 pub(crate) fn lower_trait_ref_from_resolved_path(
627 ctx: &TyLoweringContext<'_>, 636 &self,
628 resolved: TraitId, 637 resolved: TraitId,
629 segment: PathSegment<'_>, 638 segment: PathSegment<'_>,
630 explicit_self_ty: Option<Ty>, 639 explicit_self_ty: Option<Ty>,
631 ) -> Self { 640 ) -> TraitRef {
632 let mut substs = TraitRef::substs_from_path(ctx, segment, resolved); 641 let mut substs = self.trait_ref_substs_from_path(segment, resolved);
633 if let Some(self_ty) = explicit_self_ty { 642 if let Some(self_ty) = explicit_self_ty {
634 make_mut_slice(&mut substs.0)[0] = self_ty; 643 make_mut_slice(&mut substs.0)[0] = self_ty;
635 } 644 }
636 TraitRef { trait_: resolved, substs } 645 TraitRef { trait_: resolved, substs }
637 } 646 }
638 647
639 fn from_hir( 648 fn lower_trait_ref(
640 ctx: &TyLoweringContext<'_>, 649 &self,
641 type_ref: &TypeRef, 650 type_ref: &TypeRef,
642 explicit_self_ty: Option<Ty>, 651 explicit_self_ty: Option<Ty>,
643 ) -> Option<Self> { 652 ) -> Option<TraitRef> {
644 let path = match type_ref { 653 let path = match type_ref {
645 TypeRef::Path(path) => path, 654 TypeRef::Path(path) => path,
646 _ => return None, 655 _ => return None,
647 }; 656 };
648 TraitRef::from_path(ctx, path, explicit_self_ty) 657 self.lower_trait_ref_from_path(path, explicit_self_ty)
649 } 658 }
650 659
651 fn substs_from_path( 660 fn trait_ref_substs_from_path(&self, segment: PathSegment<'_>, resolved: TraitId) -> Substs {
652 ctx: &TyLoweringContext<'_>, 661 self.substs_from_path_segment(segment, Some(resolved.into()), false)
653 segment: PathSegment<'_>,
654 resolved: TraitId,
655 ) -> Substs {
656 substs_from_path_segment(ctx, segment, Some(resolved.into()), false)
657 } 662 }
658}
659 663
660impl GenericPredicate { 664 pub(crate) fn lower_where_predicate(
661 pub(crate) fn from_where_predicate<'a>( 665 &'a self,
662 ctx: &'a TyLoweringContext<'a>,
663 where_predicate: &'a WherePredicate, 666 where_predicate: &'a WherePredicate,
664 ) -> impl Iterator<Item = GenericPredicate> + 'a { 667 ) -> impl Iterator<Item = GenericPredicate> + 'a {
665 match where_predicate { 668 match where_predicate {
666 WherePredicate::ForLifetime { target, bound, .. } 669 WherePredicate::ForLifetime { target, bound, .. }
667 | WherePredicate::TypeBound { target, bound } => { 670 | WherePredicate::TypeBound { target, bound } => {
668 let self_ty = match target { 671 let self_ty = match target {
669 WherePredicateTypeTarget::TypeRef(type_ref) => Ty::from_hir(ctx, type_ref), 672 WherePredicateTypeTarget::TypeRef(type_ref) => self.lower_ty(type_ref),
670 WherePredicateTypeTarget::TypeParam(param_id) => { 673 WherePredicateTypeTarget::TypeParam(param_id) => {
671 let generic_def = ctx.resolver.generic_def().expect("generics in scope"); 674 let generic_def = self.resolver.generic_def().expect("generics in scope");
672 let generics = generics(ctx.db.upcast(), generic_def); 675 let generics = generics(self.db.upcast(), generic_def);
673 let param_id = 676 let param_id =
674 hir_def::TypeParamId { parent: generic_def, local_id: *param_id }; 677 hir_def::TypeParamId { parent: generic_def, local_id: *param_id };
675 match ctx.type_param_mode { 678 let placeholder = to_placeholder_idx(self.db, param_id);
676 TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id), 679 match self.type_param_mode {
680 TypeParamLoweringMode::Placeholder => TyKind::Placeholder(placeholder),
677 TypeParamLoweringMode::Variable => { 681 TypeParamLoweringMode::Variable => {
678 let idx = generics.param_idx(param_id).expect("matching generics"); 682 let idx = generics.param_idx(param_id).expect("matching generics");
679 Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, idx)) 683 TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, idx))
680 } 684 }
681 } 685 }
686 .intern(&Interner)
682 } 687 }
683 }; 688 };
684 GenericPredicate::from_type_bound(ctx, bound, self_ty) 689 self.lower_type_bound(bound, self_ty).collect::<Vec<_>>().into_iter()
685 .collect::<Vec<_>>()
686 .into_iter()
687 } 690 }
688 WherePredicate::Lifetime { .. } => vec![].into_iter(), 691 WherePredicate::Lifetime { .. } => vec![].into_iter(),
689 } 692 }
690 } 693 }
691 694
692 pub(crate) fn from_type_bound<'a>( 695 pub(crate) fn lower_type_bound(
693 ctx: &'a TyLoweringContext<'a>, 696 &'a self,
694 bound: &'a TypeBound, 697 bound: &'a TypeBound,
695 self_ty: Ty, 698 self_ty: Ty,
696 ) -> impl Iterator<Item = GenericPredicate> + 'a { 699 ) -> impl Iterator<Item = GenericPredicate> + 'a {
697 let mut bindings = None; 700 let mut bindings = None;
698 let trait_ref = match bound { 701 let trait_ref = match bound {
699 TypeBound::Path(path) => { 702 TypeBound::Path(path) => {
700 bindings = TraitRef::from_path(ctx, path, Some(self_ty)); 703 bindings = self.lower_trait_ref_from_path(path, Some(self_ty));
701 Some( 704 Some(
702 bindings.clone().map_or(GenericPredicate::Error, GenericPredicate::Implemented), 705 bindings.clone().map_or(GenericPredicate::Error, GenericPredicate::Implemented),
703 ) 706 )
@@ -708,64 +711,62 @@ impl GenericPredicate {
708 trait_ref.into_iter().chain( 711 trait_ref.into_iter().chain(
709 bindings 712 bindings
710 .into_iter() 713 .into_iter()
711 .flat_map(move |tr| assoc_type_bindings_from_type_bound(ctx, bound, tr)), 714 .flat_map(move |tr| self.assoc_type_bindings_from_type_bound(bound, tr)),
712 ) 715 )
713 } 716 }
714}
715 717
716fn assoc_type_bindings_from_type_bound<'a>( 718 fn assoc_type_bindings_from_type_bound(
717 ctx: &'a TyLoweringContext<'a>, 719 &'a self,
718 bound: &'a TypeBound, 720 bound: &'a TypeBound,
719 trait_ref: TraitRef, 721 trait_ref: TraitRef,
720) -> impl Iterator<Item = GenericPredicate> + 'a { 722 ) -> impl Iterator<Item = GenericPredicate> + 'a {
721 let last_segment = match bound { 723 let last_segment = match bound {
722 TypeBound::Path(path) => path.segments().last(), 724 TypeBound::Path(path) => path.segments().last(),
723 TypeBound::Error | TypeBound::Lifetime(_) => None, 725 TypeBound::Error | TypeBound::Lifetime(_) => None,
724 }; 726 };
725 last_segment 727 last_segment
726 .into_iter() 728 .into_iter()
727 .flat_map(|segment| segment.args_and_bindings.into_iter()) 729 .flat_map(|segment| segment.args_and_bindings.into_iter())
728 .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) 730 .flat_map(|args_and_bindings| args_and_bindings.bindings.iter())
729 .flat_map(move |binding| { 731 .flat_map(move |binding| {
730 let found = associated_type_by_name_including_super_traits( 732 let found = associated_type_by_name_including_super_traits(
731 ctx.db, 733 self.db,
732 trait_ref.clone(), 734 trait_ref.clone(),
733 &binding.name, 735 &binding.name,
734 ); 736 );
735 let (super_trait_ref, associated_ty) = match found { 737 let (super_trait_ref, associated_ty) = match found {
736 None => return SmallVec::<[GenericPredicate; 1]>::new(), 738 None => return SmallVec::<[GenericPredicate; 1]>::new(),
737 Some(t) => t, 739 Some(t) => t,
738 }; 740 };
739 let projection_ty = ProjectionTy { associated_ty, parameters: super_trait_ref.substs }; 741 let projection_ty = ProjectionTy {
740 let mut preds = SmallVec::with_capacity( 742 associated_ty_id: to_assoc_type_id(associated_ty),
741 binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(), 743 substitution: super_trait_ref.substs,
742 ); 744 };
743 if let Some(type_ref) = &binding.type_ref { 745 let mut preds = SmallVec::with_capacity(
744 let ty = Ty::from_hir(ctx, type_ref); 746 binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
745 let projection_predicate = 747 );
746 ProjectionPredicate { projection_ty: projection_ty.clone(), ty }; 748 if let Some(type_ref) = &binding.type_ref {
747 preds.push(GenericPredicate::Projection(projection_predicate)); 749 let ty = self.lower_ty(type_ref);
748 } 750 let projection_predicate =
749 for bound in &binding.bounds { 751 ProjectionPredicate { projection_ty: projection_ty.clone(), ty };
750 preds.extend(GenericPredicate::from_type_bound( 752 preds.push(GenericPredicate::Projection(projection_predicate));
751 ctx, 753 }
752 bound, 754 for bound in &binding.bounds {
753 Ty::Alias(AliasTy::Projection(projection_ty.clone())), 755 preds.extend(self.lower_type_bound(
754 )); 756 bound,
755 } 757 TyKind::Alias(AliasTy::Projection(projection_ty.clone())).intern(&Interner),
756 preds 758 ));
757 }) 759 }
758} 760 preds
761 })
762 }
759 763
760impl ReturnTypeImplTrait { 764 fn lower_impl_trait(&self, bounds: &[TypeBound]) -> ReturnTypeImplTrait {
761 fn from_hir(ctx: &TyLoweringContext, bounds: &[TypeBound]) -> Self {
762 cov_mark::hit!(lower_rpit); 765 cov_mark::hit!(lower_rpit);
763 let self_ty = Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)); 766 let self_ty =
764 let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| { 767 TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner);
765 bounds 768 let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
766 .iter() 769 bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone())).collect()
767 .flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone()))
768 .collect()
769 }); 770 });
770 ReturnTypeImplTrait { bounds: Binders::new(1, predicates) } 771 ReturnTypeImplTrait { bounds: Binders::new(1, predicates) }
771 } 772 }
@@ -861,7 +862,7 @@ pub(crate) fn field_types_query(
861 let ctx = 862 let ctx =
862 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); 863 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
863 for (field_id, field_data) in var_data.fields().iter() { 864 for (field_id, field_data) in var_data.fields().iter() {
864 res.insert(field_id, Binders::new(generics.len(), Ty::from_hir(&ctx, &field_data.type_ref))) 865 res.insert(field_id, Binders::new(generics.len(), ctx.lower_ty(&field_data.type_ref)))
865 } 866 }
866 Arc::new(res) 867 Arc::new(res)
867} 868}
@@ -889,16 +890,13 @@ pub(crate) fn generic_predicates_for_param_query(
889 WherePredicate::ForLifetime { target, .. } 890 WherePredicate::ForLifetime { target, .. }
890 | WherePredicate::TypeBound { target, .. } => match target { 891 | WherePredicate::TypeBound { target, .. } => match target {
891 WherePredicateTypeTarget::TypeRef(type_ref) => { 892 WherePredicateTypeTarget::TypeRef(type_ref) => {
892 Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id) 893 ctx.lower_ty_only_param(type_ref) == Some(param_id)
893 } 894 }
894 WherePredicateTypeTarget::TypeParam(local_id) => *local_id == param_id.local_id, 895 WherePredicateTypeTarget::TypeParam(local_id) => *local_id == param_id.local_id,
895 }, 896 },
896 WherePredicate::Lifetime { .. } => false, 897 WherePredicate::Lifetime { .. } => false,
897 }) 898 })
898 .flat_map(|pred| { 899 .flat_map(|pred| ctx.lower_where_predicate(pred).map(|p| Binders::new(generics.len(), p)))
899 GenericPredicate::from_where_predicate(&ctx, pred)
900 .map(|p| Binders::new(generics.len(), p))
901 })
902 .collect() 900 .collect()
903} 901}
904 902
@@ -910,41 +908,55 @@ pub(crate) fn generic_predicates_for_param_recover(
910 Arc::new([]) 908 Arc::new([])
911} 909}
912 910
913impl TraitEnvironment { 911pub(crate) fn trait_environment_query(
914 pub fn lower(db: &dyn HirDatabase, resolver: &Resolver) -> Arc<TraitEnvironment> { 912 db: &dyn HirDatabase,
915 let ctx = TyLoweringContext::new(db, &resolver) 913 def: GenericDefId,
916 .with_type_param_mode(TypeParamLoweringMode::Placeholder); 914) -> Arc<TraitEnvironment> {
917 let mut predicates = resolver 915 let resolver = def.resolver(db.upcast());
918 .where_predicates_in_scope() 916 let ctx = TyLoweringContext::new(db, &resolver)
919 .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) 917 .with_type_param_mode(TypeParamLoweringMode::Placeholder);
920 .collect::<Vec<_>>(); 918 let mut traits_in_scope = Vec::new();
921 919 let mut clauses = Vec::new();
922 if let Some(def) = resolver.generic_def() { 920 for pred in resolver.where_predicates_in_scope() {
923 let container: Option<AssocContainerId> = match def { 921 for pred in ctx.lower_where_predicate(pred) {
924 // FIXME: is there a function for this? 922 if pred.is_error() {
925 GenericDefId::FunctionId(f) => Some(f.lookup(db.upcast()).container), 923 continue;
926 GenericDefId::AdtId(_) => None,
927 GenericDefId::TraitId(_) => None,
928 GenericDefId::TypeAliasId(t) => Some(t.lookup(db.upcast()).container),
929 GenericDefId::ImplId(_) => None,
930 GenericDefId::EnumVariantId(_) => None,
931 GenericDefId::ConstId(c) => Some(c.lookup(db.upcast()).container),
932 };
933 if let Some(AssocContainerId::TraitId(trait_id)) = container {
934 // add `Self: Trait<T1, T2, ...>` to the environment in trait
935 // function default implementations (and hypothetical code
936 // inside consts or type aliases)
937 cov_mark::hit!(trait_self_implements_self);
938 let substs = Substs::type_params(db, trait_id);
939 let trait_ref = TraitRef { trait_: trait_id, substs };
940 let pred = GenericPredicate::Implemented(trait_ref);
941
942 predicates.push(pred);
943 } 924 }
925 if let GenericPredicate::Implemented(tr) = &pred {
926 traits_in_scope.push((tr.self_ty().clone(), tr.trait_));
927 }
928 let program_clause: chalk_ir::ProgramClause<Interner> =
929 pred.clone().to_chalk(db).cast(&Interner);
930 clauses.push(program_clause.into_from_env_clause(&Interner));
944 } 931 }
932 }
945 933
946 Arc::new(TraitEnvironment { predicates }) 934 let container: Option<AssocContainerId> = match def {
935 // FIXME: is there a function for this?
936 GenericDefId::FunctionId(f) => Some(f.lookup(db.upcast()).container),
937 GenericDefId::AdtId(_) => None,
938 GenericDefId::TraitId(_) => None,
939 GenericDefId::TypeAliasId(t) => Some(t.lookup(db.upcast()).container),
940 GenericDefId::ImplId(_) => None,
941 GenericDefId::EnumVariantId(_) => None,
942 GenericDefId::ConstId(c) => Some(c.lookup(db.upcast()).container),
943 };
944 if let Some(AssocContainerId::TraitId(trait_id)) = container {
945 // add `Self: Trait<T1, T2, ...>` to the environment in trait
946 // function default implementations (and hypothetical code
947 // inside consts or type aliases)
948 cov_mark::hit!(trait_self_implements_self);
949 let substs = Substs::type_params(db, trait_id);
950 let trait_ref = TraitRef { trait_: trait_id, substs };
951 let pred = GenericPredicate::Implemented(trait_ref);
952 let program_clause: chalk_ir::ProgramClause<Interner> =
953 pred.clone().to_chalk(db).cast(&Interner);
954 clauses.push(program_clause.into_from_env_clause(&Interner));
947 } 955 }
956
957 let env = chalk_ir::Environment::new(&Interner).add_clauses(&Interner, clauses);
958
959 Arc::new(TraitEnvironment { traits_from_clauses: traits_in_scope, env })
948} 960}
949 961
950/// Resolve the where clause(s) of an item with generics. 962/// Resolve the where clause(s) of an item with generics.
@@ -958,10 +970,7 @@ pub(crate) fn generic_predicates_query(
958 let generics = generics(db.upcast(), def); 970 let generics = generics(db.upcast(), def);
959 resolver 971 resolver
960 .where_predicates_in_scope() 972 .where_predicates_in_scope()
961 .flat_map(|pred| { 973 .flat_map(|pred| ctx.lower_where_predicate(pred).map(|p| Binders::new(generics.len(), p)))
962 GenericPredicate::from_where_predicate(&ctx, pred)
963 .map(|p| Binders::new(generics.len(), p))
964 })
965 .collect() 974 .collect()
966} 975}
967 976
@@ -979,17 +988,18 @@ pub(crate) fn generic_defaults_query(
979 .iter() 988 .iter()
980 .enumerate() 989 .enumerate()
981 .map(|(idx, (_, p))| { 990 .map(|(idx, (_, p))| {
982 let mut ty = p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(&ctx, t)); 991 let mut ty =
992 p.default.as_ref().map_or(TyKind::Unknown.intern(&Interner), |t| ctx.lower_ty(t));
983 993
984 // Each default can only refer to previous parameters. 994 // Each default can only refer to previous parameters.
985 ty.walk_mut_binders( 995 ty.walk_mut_binders(
986 &mut |ty, binders| match ty { 996 &mut |ty, binders| match &mut ty.0 {
987 Ty::BoundVar(BoundVar { debruijn, index }) if *debruijn == binders => { 997 TyKind::BoundVar(BoundVar { debruijn, index }) if *debruijn == binders => {
988 if *index >= idx { 998 if *index >= idx {
989 // type variable default referring to parameter coming 999 // type variable default referring to parameter coming
990 // after it. This is forbidden (FIXME: report 1000 // after it. This is forbidden (FIXME: report
991 // diagnostic) 1001 // diagnostic)
992 *ty = Ty::Unknown; 1002 *ty = TyKind::Unknown.intern(&Interner);
993 } 1003 }
994 } 1004 }
995 _ => {} 1005 _ => {}
@@ -1010,11 +1020,11 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
1010 let ctx_params = TyLoweringContext::new(db, &resolver) 1020 let ctx_params = TyLoweringContext::new(db, &resolver)
1011 .with_impl_trait_mode(ImplTraitLoweringMode::Variable) 1021 .with_impl_trait_mode(ImplTraitLoweringMode::Variable)
1012 .with_type_param_mode(TypeParamLoweringMode::Variable); 1022 .with_type_param_mode(TypeParamLoweringMode::Variable);
1013 let params = data.params.iter().map(|tr| Ty::from_hir(&ctx_params, tr)).collect::<Vec<_>>(); 1023 let params = data.params.iter().map(|tr| (&ctx_params).lower_ty(tr)).collect::<Vec<_>>();
1014 let ctx_ret = TyLoweringContext::new(db, &resolver) 1024 let ctx_ret = TyLoweringContext::new(db, &resolver)
1015 .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) 1025 .with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
1016 .with_type_param_mode(TypeParamLoweringMode::Variable); 1026 .with_type_param_mode(TypeParamLoweringMode::Variable);
1017 let ret = Ty::from_hir(&ctx_ret, &data.ret_type); 1027 let ret = (&ctx_ret).lower_ty(&data.ret_type);
1018 let generics = generics(db.upcast(), def.into()); 1028 let generics = generics(db.upcast(), def.into());
1019 let num_binders = generics.len(); 1029 let num_binders = generics.len();
1020 Binders::new(num_binders, CallableSig::from_params_and_return(params, ret, data.is_varargs)) 1030 Binders::new(num_binders, CallableSig::from_params_and_return(params, ret, data.is_varargs))
@@ -1025,7 +1035,10 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
1025fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> Binders<Ty> { 1035fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> Binders<Ty> {
1026 let generics = generics(db.upcast(), def.into()); 1036 let generics = generics(db.upcast(), def.into());
1027 let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); 1037 let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST);
1028 Binders::new(substs.len(), Ty::FnDef(def.into(), substs)) 1038 Binders::new(
1039 substs.len(),
1040 TyKind::FnDef(CallableDefId::FunctionId(def).to_chalk(db), substs).intern(&Interner),
1041 )
1029} 1042}
1030 1043
1031/// Build the declared type of a const. 1044/// Build the declared type of a const.
@@ -1036,7 +1049,7 @@ fn type_for_const(db: &dyn HirDatabase, def: ConstId) -> Binders<Ty> {
1036 let ctx = 1049 let ctx =
1037 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); 1050 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
1038 1051
1039 Binders::new(generics.len(), Ty::from_hir(&ctx, &data.type_ref)) 1052 Binders::new(generics.len(), ctx.lower_ty(&data.type_ref))
1040} 1053}
1041 1054
1042/// Build the declared type of a static. 1055/// Build the declared type of a static.
@@ -1045,7 +1058,7 @@ fn type_for_static(db: &dyn HirDatabase, def: StaticId) -> Binders<Ty> {
1045 let resolver = def.resolver(db.upcast()); 1058 let resolver = def.resolver(db.upcast());
1046 let ctx = TyLoweringContext::new(db, &resolver); 1059 let ctx = TyLoweringContext::new(db, &resolver);
1047 1060
1048 Binders::new(0, Ty::from_hir(&ctx, &data.type_ref)) 1061 Binders::new(0, ctx.lower_ty(&data.type_ref))
1049} 1062}
1050 1063
1051fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnSig { 1064fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnSig {
@@ -1054,8 +1067,7 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS
1054 let resolver = def.resolver(db.upcast()); 1067 let resolver = def.resolver(db.upcast());
1055 let ctx = 1068 let ctx =
1056 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); 1069 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
1057 let params = 1070 let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>();
1058 fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>();
1059 let ret = type_for_adt(db, def.into()); 1071 let ret = type_for_adt(db, def.into());
1060 Binders::new(ret.num_binders, CallableSig::from_params_and_return(params, ret.value, false)) 1072 Binders::new(ret.num_binders, CallableSig::from_params_and_return(params, ret.value, false))
1061} 1073}
@@ -1068,7 +1080,10 @@ fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Binders<T
1068 } 1080 }
1069 let generics = generics(db.upcast(), def.into()); 1081 let generics = generics(db.upcast(), def.into());
1070 let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); 1082 let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST);
1071 Binders::new(substs.len(), Ty::FnDef(def.into(), substs)) 1083 Binders::new(
1084 substs.len(),
1085 TyKind::FnDef(CallableDefId::StructId(def).to_chalk(db), substs).intern(&Interner),
1086 )
1072} 1087}
1073 1088
1074fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -> PolyFnSig { 1089fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -> PolyFnSig {
@@ -1078,8 +1093,7 @@ fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId)
1078 let resolver = def.parent.resolver(db.upcast()); 1093 let resolver = def.parent.resolver(db.upcast());
1079 let ctx = 1094 let ctx =
1080 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); 1095 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
1081 let params = 1096 let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>();
1082 fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>();
1083 let ret = type_for_adt(db, def.parent.into()); 1097 let ret = type_for_adt(db, def.parent.into());
1084 Binders::new(ret.num_binders, CallableSig::from_params_and_return(params, ret.value, false)) 1098 Binders::new(ret.num_binders, CallableSig::from_params_and_return(params, ret.value, false))
1085} 1099}
@@ -1093,7 +1107,10 @@ fn type_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -
1093 } 1107 }
1094 let generics = generics(db.upcast(), def.parent.into()); 1108 let generics = generics(db.upcast(), def.parent.into());
1095 let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); 1109 let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST);
1096 Binders::new(substs.len(), Ty::FnDef(def.into(), substs)) 1110 Binders::new(
1111 substs.len(),
1112 TyKind::FnDef(CallableDefId::EnumVariantId(def).to_chalk(db), substs).intern(&Interner),
1113 )
1097} 1114}
1098 1115
1099fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> { 1116fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> {
@@ -1108,11 +1125,11 @@ fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> {
1108 let ctx = 1125 let ctx =
1109 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); 1126 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
1110 if db.type_alias_data(t).is_extern { 1127 if db.type_alias_data(t).is_extern {
1111 Binders::new(0, Ty::ForeignType(t)) 1128 Binders::new(0, TyKind::ForeignType(crate::to_foreign_def_id(t)).intern(&Interner))
1112 } else { 1129 } else {
1113 let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); 1130 let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST);
1114 let type_ref = &db.type_alias_data(t).type_ref; 1131 let type_ref = &db.type_alias_data(t).type_ref;
1115 let inner = Ty::from_hir(&ctx, type_ref.as_ref().unwrap_or(&TypeRef::Error)); 1132 let inner = ctx.lower_ty(type_ref.as_ref().unwrap_or(&TypeRef::Error));
1116 Binders::new(substs.len(), inner) 1133 Binders::new(substs.len(), inner)
1117 } 1134 }
1118} 1135}
@@ -1184,7 +1201,7 @@ pub(crate) fn ty_recover(db: &dyn HirDatabase, _cycle: &[String], def: &TyDefId)
1184 TyDefId::AdtId(it) => generics(db.upcast(), it.into()).len(), 1201 TyDefId::AdtId(it) => generics(db.upcast(), it.into()).len(),
1185 TyDefId::TypeAliasId(it) => generics(db.upcast(), it.into()).len(), 1202 TyDefId::TypeAliasId(it) => generics(db.upcast(), it.into()).len(),
1186 }; 1203 };
1187 Binders::new(num_binders, Ty::Unknown) 1204 Binders::new(num_binders, TyKind::Unknown.intern(&Interner))
1188} 1205}
1189 1206
1190pub(crate) fn value_ty_query(db: &dyn HirDatabase, def: ValueTyDefId) -> Binders<Ty> { 1207pub(crate) fn value_ty_query(db: &dyn HirDatabase, def: ValueTyDefId) -> Binders<Ty> {
@@ -1204,7 +1221,7 @@ pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binde
1204 let generics = generics(db.upcast(), impl_id.into()); 1221 let generics = generics(db.upcast(), impl_id.into());
1205 let ctx = 1222 let ctx =
1206 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); 1223 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
1207 Binders::new(generics.len(), Ty::from_hir(&ctx, &impl_data.target_type)) 1224 Binders::new(generics.len(), ctx.lower_ty(&impl_data.target_type))
1208} 1225}
1209 1226
1210pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty { 1227pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty {
@@ -1213,7 +1230,7 @@ pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> T
1213 let resolver = def.parent.resolver(db.upcast()); 1230 let resolver = def.parent.resolver(db.upcast());
1214 let ctx = TyLoweringContext::new(db, &resolver); 1231 let ctx = TyLoweringContext::new(db, &resolver);
1215 1232
1216 Ty::from_hir(&ctx, &data.ty) 1233 ctx.lower_ty(&data.ty)
1217} 1234}
1218 1235
1219pub(crate) fn impl_self_ty_recover( 1236pub(crate) fn impl_self_ty_recover(
@@ -1222,7 +1239,7 @@ pub(crate) fn impl_self_ty_recover(
1222 impl_id: &ImplId, 1239 impl_id: &ImplId,
1223) -> Binders<Ty> { 1240) -> Binders<Ty> {
1224 let generics = generics(db.upcast(), (*impl_id).into()); 1241 let generics = generics(db.upcast(), (*impl_id).into());
1225 Binders::new(generics.len(), Ty::Unknown) 1242 Binders::new(generics.len(), TyKind::Unknown.intern(&Interner))
1226} 1243}
1227 1244
1228pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<Binders<TraitRef>> { 1245pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<Binders<TraitRef>> {
@@ -1232,10 +1249,7 @@ pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<
1232 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); 1249 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
1233 let self_ty = db.impl_self_ty(impl_id); 1250 let self_ty = db.impl_self_ty(impl_id);
1234 let target_trait = impl_data.target_trait.as_ref()?; 1251 let target_trait = impl_data.target_trait.as_ref()?;
1235 Some(Binders::new( 1252 Some(Binders::new(self_ty.num_binders, ctx.lower_trait_ref(target_trait, Some(self_ty.value))?))
1236 self_ty.num_binders,
1237 TraitRef::from_hir(&ctx, target_trait, Some(self_ty.value))?,
1238 ))
1239} 1253}
1240 1254
1241pub(crate) fn return_type_impl_traits( 1255pub(crate) fn return_type_impl_traits(
@@ -1248,7 +1262,7 @@ pub(crate) fn return_type_impl_traits(
1248 let ctx_ret = TyLoweringContext::new(db, &resolver) 1262 let ctx_ret = TyLoweringContext::new(db, &resolver)
1249 .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) 1263 .with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
1250 .with_type_param_mode(TypeParamLoweringMode::Variable); 1264 .with_type_param_mode(TypeParamLoweringMode::Variable);
1251 let _ret = Ty::from_hir(&ctx_ret, &data.ret_type); 1265 let _ret = (&ctx_ret).lower_ty(&data.ret_type);
1252 let generics = generics(db.upcast(), def.into()); 1266 let generics = generics(db.upcast(), def.into());
1253 let num_binders = generics.len(); 1267 let num_binders = generics.len();
1254 let return_type_impl_traits = 1268 let return_type_impl_traits =
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index ccc12c075..c7055bee5 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -9,7 +9,7 @@ use base_db::CrateId;
9use chalk_ir::Mutability; 9use chalk_ir::Mutability;
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, TypeAliasId, 12 ImplId, Lookup, ModuleId, TraitId,
13}; 13};
14use hir_expand::name::Name; 14use hir_expand::name::Name;
15use rustc_hash::{FxHashMap, FxHashSet}; 15use rustc_hash::{FxHashMap, FxHashSet};
@@ -17,10 +17,11 @@ use rustc_hash::{FxHashMap, FxHashSet};
17use crate::{ 17use crate::{
18 autoderef, 18 autoderef,
19 db::HirDatabase, 19 db::HirDatabase,
20 from_foreign_def_id,
20 primitive::{self, FloatTy, IntTy, UintTy}, 21 primitive::{self, FloatTy, IntTy, UintTy},
21 utils::all_super_traits, 22 utils::all_super_traits,
22 AdtId, Canonical, DebruijnIndex, FnPointer, FnSig, InEnvironment, Scalar, Substs, 23 AdtId, Canonical, DebruijnIndex, FnPointer, FnSig, ForeignDefId, InEnvironment, Interner,
23 TraitEnvironment, TraitRef, Ty, TypeWalk, 24 Scalar, Substs, TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk,
24}; 25};
25 26
26/// This is used as a key for indexing impls. 27/// This is used as a key for indexing impls.
@@ -35,7 +36,7 @@ pub enum TyFingerprint {
35 Adt(hir_def::AdtId), 36 Adt(hir_def::AdtId),
36 Dyn(TraitId), 37 Dyn(TraitId),
37 Tuple(usize), 38 Tuple(usize),
38 ForeignType(TypeAliasId), 39 ForeignType(ForeignDefId),
39 FnPtr(usize, FnSig), 40 FnPtr(usize, FnSig),
40} 41}
41 42
@@ -44,18 +45,20 @@ impl TyFingerprint {
44 /// have impls: if we have some `struct S`, we can have an `impl S`, but not 45 /// have impls: if we have some `struct S`, we can have an `impl S`, but not
45 /// `impl &S`. Hence, this will return `None` for reference types and such. 46 /// `impl &S`. Hence, this will return `None` for reference types and such.
46 pub(crate) fn for_impl(ty: &Ty) -> Option<TyFingerprint> { 47 pub(crate) fn for_impl(ty: &Ty) -> Option<TyFingerprint> {
47 let fp = match ty { 48 let fp = match *ty.interned(&Interner) {
48 &Ty::Str => TyFingerprint::Str, 49 TyKind::Str => TyFingerprint::Str,
49 &Ty::Never => TyFingerprint::Never, 50 TyKind::Never => TyFingerprint::Never,
50 &Ty::Slice(..) => TyFingerprint::Slice, 51 TyKind::Slice(..) => TyFingerprint::Slice,
51 &Ty::Array(..) => TyFingerprint::Array, 52 TyKind::Array(..) => TyFingerprint::Array,
52 &Ty::Scalar(scalar) => TyFingerprint::Scalar(scalar), 53 TyKind::Scalar(scalar) => TyFingerprint::Scalar(scalar),
53 &Ty::Adt(AdtId(adt), _) => TyFingerprint::Adt(adt), 54 TyKind::Adt(AdtId(adt), _) => TyFingerprint::Adt(adt),
54 &Ty::Tuple(cardinality, _) => TyFingerprint::Tuple(cardinality), 55 TyKind::Tuple(cardinality, _) => TyFingerprint::Tuple(cardinality),
55 &Ty::Raw(mutability, ..) => TyFingerprint::RawPtr(mutability), 56 TyKind::Raw(mutability, ..) => TyFingerprint::RawPtr(mutability),
56 &Ty::ForeignType(alias_id, ..) => TyFingerprint::ForeignType(alias_id), 57 TyKind::ForeignType(alias_id, ..) => TyFingerprint::ForeignType(alias_id),
57 &Ty::Function(FnPointer { num_args, sig, .. }) => TyFingerprint::FnPtr(num_args, sig), 58 TyKind::Function(FnPointer { num_args, sig, .. }) => {
58 Ty::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_))?, 59 TyFingerprint::FnPtr(num_args, sig)
60 }
61 TyKind::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_))?,
59 _ => return None, 62 _ => return None,
60 }; 63 };
61 Some(fp) 64 Some(fp)
@@ -230,31 +233,33 @@ impl Ty {
230 233
231 let mod_to_crate_ids = |module: ModuleId| Some(std::iter::once(module.krate()).collect()); 234 let mod_to_crate_ids = |module: ModuleId| Some(std::iter::once(module.krate()).collect());
232 235
233 let lang_item_targets = match self { 236 let lang_item_targets = match self.interned(&Interner) {
234 Ty::Adt(AdtId(def_id), _) => { 237 TyKind::Adt(AdtId(def_id), _) => {
235 return mod_to_crate_ids(def_id.module(db.upcast())); 238 return mod_to_crate_ids(def_id.module(db.upcast()));
236 } 239 }
237 Ty::ForeignType(type_alias_id) => { 240 TyKind::ForeignType(id) => {
238 return mod_to_crate_ids(type_alias_id.lookup(db.upcast()).module(db.upcast())); 241 return mod_to_crate_ids(
242 from_foreign_def_id(*id).lookup(db.upcast()).module(db.upcast()),
243 );
239 } 244 }
240 Ty::Scalar(Scalar::Bool) => lang_item_crate!("bool"), 245 TyKind::Scalar(Scalar::Bool) => lang_item_crate!("bool"),
241 Ty::Scalar(Scalar::Char) => lang_item_crate!("char"), 246 TyKind::Scalar(Scalar::Char) => lang_item_crate!("char"),
242 Ty::Scalar(Scalar::Float(f)) => match f { 247 TyKind::Scalar(Scalar::Float(f)) => match f {
243 // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime) 248 // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime)
244 FloatTy::F32 => lang_item_crate!("f32", "f32_runtime"), 249 FloatTy::F32 => lang_item_crate!("f32", "f32_runtime"),
245 FloatTy::F64 => lang_item_crate!("f64", "f64_runtime"), 250 FloatTy::F64 => lang_item_crate!("f64", "f64_runtime"),
246 }, 251 },
247 &Ty::Scalar(Scalar::Int(t)) => { 252 &TyKind::Scalar(Scalar::Int(t)) => {
248 lang_item_crate!(primitive::int_ty_to_string(t)) 253 lang_item_crate!(primitive::int_ty_to_string(t))
249 } 254 }
250 &Ty::Scalar(Scalar::Uint(t)) => { 255 &TyKind::Scalar(Scalar::Uint(t)) => {
251 lang_item_crate!(primitive::uint_ty_to_string(t)) 256 lang_item_crate!(primitive::uint_ty_to_string(t))
252 } 257 }
253 Ty::Str => lang_item_crate!("str_alloc", "str"), 258 TyKind::Str => lang_item_crate!("str_alloc", "str"),
254 Ty::Slice(_) => lang_item_crate!("slice_alloc", "slice"), 259 TyKind::Slice(_) => lang_item_crate!("slice_alloc", "slice"),
255 Ty::Raw(Mutability::Not, _) => lang_item_crate!("const_ptr"), 260 TyKind::Raw(Mutability::Not, _) => lang_item_crate!("const_ptr"),
256 Ty::Raw(Mutability::Mut, _) => lang_item_crate!("mut_ptr"), 261 TyKind::Raw(Mutability::Mut, _) => lang_item_crate!("mut_ptr"),
257 Ty::Dyn(_) => { 262 TyKind::Dyn(_) => {
258 return self.dyn_trait().and_then(|trait_| { 263 return self.dyn_trait().and_then(|trait_| {
259 mod_to_crate_ids(GenericDefId::TraitId(trait_).module(db.upcast())) 264 mod_to_crate_ids(GenericDefId::TraitId(trait_).module(db.upcast()))
260 }); 265 });
@@ -430,7 +435,8 @@ fn iterate_method_candidates_with_autoref(
430 } 435 }
431 let refed = Canonical { 436 let refed = Canonical {
432 kinds: deref_chain[0].kinds.clone(), 437 kinds: deref_chain[0].kinds.clone(),
433 value: Ty::Ref(Mutability::Not, Substs::single(deref_chain[0].value.clone())), 438 value: TyKind::Ref(Mutability::Not, Substs::single(deref_chain[0].value.clone()))
439 .intern(&Interner),
434 }; 440 };
435 if iterate_method_candidates_by_receiver( 441 if iterate_method_candidates_by_receiver(
436 &refed, 442 &refed,
@@ -446,7 +452,8 @@ fn iterate_method_candidates_with_autoref(
446 } 452 }
447 let ref_muted = Canonical { 453 let ref_muted = Canonical {
448 kinds: deref_chain[0].kinds.clone(), 454 kinds: deref_chain[0].kinds.clone(),
449 value: Ty::Ref(Mutability::Mut, Substs::single(deref_chain[0].value.clone())), 455 value: TyKind::Ref(Mutability::Mut, Substs::single(deref_chain[0].value.clone()))
456 .intern(&Interner),
450 }; 457 };
451 if iterate_method_candidates_by_receiver( 458 if iterate_method_candidates_by_receiver(
452 &ref_muted, 459 &ref_muted,
@@ -526,10 +533,9 @@ fn iterate_trait_method_candidates(
526 // if ty is `dyn Trait`, the trait doesn't need to be in scope 533 // if ty is `dyn Trait`, the trait doesn't need to be in scope
527 let inherent_trait = 534 let inherent_trait =
528 self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t)); 535 self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t));
529 let env_traits = if let Ty::Placeholder(_) = self_ty.value { 536 let env_traits = if let TyKind::Placeholder(_) = self_ty.value.interned(&Interner) {
530 // if we have `T: Trait` in the param env, the trait doesn't need to be in scope 537 // if we have `T: Trait` in the param env, the trait doesn't need to be in scope
531 env.trait_predicates_for_self_ty(&self_ty.value) 538 env.traits_in_scope_from_clauses(&self_ty.value)
532 .map(|tr| tr.trait_)
533 .flat_map(|t| all_super_traits(db.upcast(), t)) 539 .flat_map(|t| all_super_traits(db.upcast(), t))
534 .collect() 540 .collect()
535 } else { 541 } else {
@@ -680,13 +686,13 @@ pub(crate) fn inherent_impl_substs(
680} 686}
681 687
682/// This replaces any 'free' Bound vars in `s` (i.e. those with indices past 688/// This replaces any 'free' Bound vars in `s` (i.e. those with indices past
683/// num_vars_to_keep) by `Ty::Unknown`. 689/// num_vars_to_keep) by `TyKind::Unknown`.
684fn fallback_bound_vars(s: Substs, num_vars_to_keep: usize) -> Substs { 690fn fallback_bound_vars(s: Substs, num_vars_to_keep: usize) -> Substs {
685 s.fold_binders( 691 s.fold_binders(
686 &mut |ty, binders| { 692 &mut |ty, binders| {
687 if let Ty::BoundVar(bound) = &ty { 693 if let TyKind::BoundVar(bound) = ty.interned(&Interner) {
688 if bound.index >= num_vars_to_keep && bound.debruijn >= binders { 694 if bound.index >= num_vars_to_keep && bound.debruijn >= binders {
689 Ty::Unknown 695 TyKind::Unknown.intern(&Interner)
690 } else { 696 } else {
691 ty 697 ty
692 } 698 }
@@ -773,9 +779,11 @@ fn autoderef_method_receiver(
773) -> Vec<Canonical<Ty>> { 779) -> Vec<Canonical<Ty>> {
774 let mut deref_chain: Vec<_> = autoderef::autoderef(db, Some(krate), ty).collect(); 780 let mut deref_chain: Vec<_> = autoderef::autoderef(db, Some(krate), ty).collect();
775 // As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!) 781 // As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!)
776 if let Some(Ty::Array(parameters)) = deref_chain.last().map(|ty| &ty.value) { 782 if let Some(TyKind::Array(parameters)) =
783 deref_chain.last().map(|ty| ty.value.interned(&Interner))
784 {
777 let kinds = deref_chain.last().unwrap().kinds.clone(); 785 let kinds = deref_chain.last().unwrap().kinds.clone();
778 let unsized_ty = Ty::Slice(parameters.clone()); 786 let unsized_ty = TyKind::Slice(parameters.clone()).intern(&Interner);
779 deref_chain.push(Canonical { value: unsized_ty, kinds }) 787 deref_chain.push(Canonical { value: unsized_ty, kinds })
780 } 788 }
781 deref_chain 789 deref_chain
diff --git a/crates/hir_ty/src/op.rs b/crates/hir_ty/src/op.rs
index bb9b8bbfc..527c5cbbd 100644
--- a/crates/hir_ty/src/op.rs
+++ b/crates/hir_ty/src/op.rs
@@ -2,51 +2,55 @@
2use chalk_ir::TyVariableKind; 2use chalk_ir::TyVariableKind;
3use hir_def::expr::{ArithOp, BinaryOp, CmpOp}; 3use hir_def::expr::{ArithOp, BinaryOp, CmpOp};
4 4
5use crate::{Scalar, Ty}; 5use crate::{Interner, Scalar, Ty, TyKind};
6 6
7pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty { 7pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty {
8 match op { 8 match op {
9 BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => Ty::Scalar(Scalar::Bool), 9 BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
10 BinaryOp::Assignment { .. } => Ty::unit(), 10 BinaryOp::Assignment { .. } => Ty::unit(),
11 BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => match lhs_ty { 11 BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => {
12 Ty::Scalar(Scalar::Int(_)) 12 match lhs_ty.interned(&Interner) {
13 | Ty::Scalar(Scalar::Uint(_)) 13 TyKind::Scalar(Scalar::Int(_))
14 | Ty::Scalar(Scalar::Float(_)) => lhs_ty, 14 | TyKind::Scalar(Scalar::Uint(_))
15 Ty::InferenceVar(_, TyVariableKind::Integer) 15 | TyKind::Scalar(Scalar::Float(_)) => lhs_ty,
16 | Ty::InferenceVar(_, TyVariableKind::Float) => lhs_ty, 16 TyKind::InferenceVar(_, TyVariableKind::Integer)
17 _ => Ty::Unknown, 17 | TyKind::InferenceVar(_, TyVariableKind::Float) => lhs_ty,
18 }, 18 _ => TyKind::Unknown.intern(&Interner),
19 BinaryOp::ArithOp(_) => match rhs_ty { 19 }
20 Ty::Scalar(Scalar::Int(_)) 20 }
21 | Ty::Scalar(Scalar::Uint(_)) 21 BinaryOp::ArithOp(_) => match rhs_ty.interned(&Interner) {
22 | Ty::Scalar(Scalar::Float(_)) => rhs_ty, 22 TyKind::Scalar(Scalar::Int(_))
23 Ty::InferenceVar(_, TyVariableKind::Integer) 23 | TyKind::Scalar(Scalar::Uint(_))
24 | Ty::InferenceVar(_, TyVariableKind::Float) => rhs_ty, 24 | TyKind::Scalar(Scalar::Float(_)) => rhs_ty,
25 _ => Ty::Unknown, 25 TyKind::InferenceVar(_, TyVariableKind::Integer)
26 | TyKind::InferenceVar(_, TyVariableKind::Float) => rhs_ty,
27 _ => TyKind::Unknown.intern(&Interner),
26 }, 28 },
27 } 29 }
28} 30}
29 31
30pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { 32pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty {
31 match op { 33 match op {
32 BinaryOp::LogicOp(..) => Ty::Scalar(Scalar::Bool), 34 BinaryOp::LogicOp(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
33 BinaryOp::Assignment { op: None } => lhs_ty, 35 BinaryOp::Assignment { op: None } => lhs_ty,
34 BinaryOp::CmpOp(CmpOp::Eq { .. }) => match lhs_ty { 36 BinaryOp::CmpOp(CmpOp::Eq { .. }) => match lhs_ty.interned(&Interner) {
35 Ty::Scalar(_) | Ty::Str => lhs_ty, 37 TyKind::Scalar(_) | TyKind::Str => lhs_ty,
36 Ty::InferenceVar(_, TyVariableKind::Integer) 38 TyKind::InferenceVar(_, TyVariableKind::Integer)
37 | Ty::InferenceVar(_, TyVariableKind::Float) => lhs_ty, 39 | TyKind::InferenceVar(_, TyVariableKind::Float) => lhs_ty,
38 _ => Ty::Unknown, 40 _ => TyKind::Unknown.intern(&Interner),
39 }, 41 },
40 BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => Ty::Unknown, 42 BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => {
43 TyKind::Unknown.intern(&Interner)
44 }
41 BinaryOp::CmpOp(CmpOp::Ord { .. }) 45 BinaryOp::CmpOp(CmpOp::Ord { .. })
42 | BinaryOp::Assignment { op: Some(_) } 46 | BinaryOp::Assignment { op: Some(_) }
43 | BinaryOp::ArithOp(_) => match lhs_ty { 47 | BinaryOp::ArithOp(_) => match lhs_ty.interned(&Interner) {
44 Ty::Scalar(Scalar::Int(_)) 48 TyKind::Scalar(Scalar::Int(_))
45 | Ty::Scalar(Scalar::Uint(_)) 49 | TyKind::Scalar(Scalar::Uint(_))
46 | Ty::Scalar(Scalar::Float(_)) => lhs_ty, 50 | TyKind::Scalar(Scalar::Float(_)) => lhs_ty,
47 Ty::InferenceVar(_, TyVariableKind::Integer) 51 TyKind::InferenceVar(_, TyVariableKind::Integer)
48 | Ty::InferenceVar(_, TyVariableKind::Float) => lhs_ty, 52 | TyKind::InferenceVar(_, TyVariableKind::Float) => lhs_ty,
49 _ => Ty::Unknown, 53 _ => TyKind::Unknown.intern(&Interner),
50 }, 54 },
51 } 55 }
52} 56}
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs
index fc770ea60..0a4141e69 100644
--- a/crates/hir_ty/src/tests.rs
+++ b/crates/hir_ty/src/tests.rs
@@ -19,6 +19,7 @@ use hir_def::{
19 item_scope::ItemScope, 19 item_scope::ItemScope,
20 keys, 20 keys,
21 nameres::DefMap, 21 nameres::DefMap,
22 src::HasSource,
22 AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId, 23 AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId,
23}; 24};
24use hir_expand::{db::AstDatabase, InFile}; 25use hir_expand::{db::AstDatabase, InFile};
@@ -195,18 +196,15 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
195 defs.sort_by_key(|def| match def { 196 defs.sort_by_key(|def| match def {
196 DefWithBodyId::FunctionId(it) => { 197 DefWithBodyId::FunctionId(it) => {
197 let loc = it.lookup(&db); 198 let loc = it.lookup(&db);
198 let tree = db.item_tree(loc.id.file_id); 199 loc.source(&db).value.syntax().text_range().start()
199 tree.source(&db, loc.id).syntax().text_range().start()
200 } 200 }
201 DefWithBodyId::ConstId(it) => { 201 DefWithBodyId::ConstId(it) => {
202 let loc = it.lookup(&db); 202 let loc = it.lookup(&db);
203 let tree = db.item_tree(loc.id.file_id); 203 loc.source(&db).value.syntax().text_range().start()
204 tree.source(&db, loc.id).syntax().text_range().start()
205 } 204 }
206 DefWithBodyId::StaticId(it) => { 205 DefWithBodyId::StaticId(it) => {
207 let loc = it.lookup(&db); 206 let loc = it.lookup(&db);
208 let tree = db.item_tree(loc.id.file_id); 207 loc.source(&db).value.syntax().text_range().start()
209 tree.source(&db, loc.id).syntax().text_range().start()
210 } 208 }
211 }); 209 });
212 for def in defs { 210 for def in defs {
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs
index e4cdb6d53..a6a63c673 100644
--- a/crates/hir_ty/src/traits.rs
+++ b/crates/hir_ty/src/traits.rs
@@ -10,7 +10,9 @@ use stdx::panic_context;
10 10
11use crate::{db::HirDatabase, DebruijnIndex, Substs}; 11use crate::{db::HirDatabase, DebruijnIndex, Substs};
12 12
13use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; 13use super::{
14 Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TyKind, TypeWalk,
15};
14 16
15use self::chalk::{from_chalk, Interner, ToChalk}; 17use self::chalk::{from_chalk, Interner, ToChalk};
16 18
@@ -38,26 +40,38 @@ fn create_chalk_solver() -> chalk_recursive::RecursiveSolver<Interner> {
38/// fn foo<T: Default>(t: T) {} 40/// fn foo<T: Default>(t: T) {}
39/// ``` 41/// ```
40/// we assume that `T: Default`. 42/// we assume that `T: Default`.
41#[derive(Clone, Debug, PartialEq, Eq, Hash)] 43#[derive(Debug, Clone, PartialEq, Eq, Hash)]
42pub struct TraitEnvironment { 44pub struct TraitEnvironment {
43 pub predicates: Vec<GenericPredicate>, 45 // When we're using Chalk's Ty we can make this a BTreeMap since it's Ord,
46 // but for now it's too annoying...
47 pub(crate) traits_from_clauses: Vec<(Ty, TraitId)>,
48 pub(crate) env: chalk_ir::Environment<Interner>,
44} 49}
45 50
46impl TraitEnvironment { 51impl TraitEnvironment {
47 /// Returns trait refs with the given self type which are supposed to hold 52 pub(crate) fn traits_in_scope_from_clauses<'a>(
48 /// in this trait env. E.g. if we are in `foo<T: SomeTrait>()`, this will
49 /// find that `T: SomeTrait` if we call it for `T`.
50 pub(crate) fn trait_predicates_for_self_ty<'a>(
51 &'a self, 53 &'a self,
52 ty: &'a Ty, 54 ty: &'a Ty,
53 ) -> impl Iterator<Item = &'a TraitRef> + 'a { 55 ) -> impl Iterator<Item = TraitId> + 'a {
54 self.predicates.iter().filter_map(move |pred| match pred { 56 self.traits_from_clauses.iter().filter_map(move |(self_ty, trait_id)| {
55 GenericPredicate::Implemented(tr) if tr.self_ty() == ty => Some(tr), 57 if self_ty == ty {
56 _ => None, 58 Some(*trait_id)
59 } else {
60 None
61 }
57 }) 62 })
58 } 63 }
59} 64}
60 65
66impl Default for TraitEnvironment {
67 fn default() -> Self {
68 TraitEnvironment {
69 traits_from_clauses: Vec::new(),
70 env: chalk_ir::Environment::new(&Interner),
71 }
72 }
73}
74
61/// Something (usually a goal), along with an environment. 75/// Something (usually a goal), along with an environment.
62#[derive(Clone, Debug, PartialEq, Eq, Hash)] 76#[derive(Clone, Debug, PartialEq, Eq, Hash)]
63pub struct InEnvironment<T> { 77pub struct InEnvironment<T> {
@@ -129,7 +143,7 @@ pub(crate) fn trait_solve_query(
129 log::info!("trait_solve_query({})", goal.value.value.display(db)); 143 log::info!("trait_solve_query({})", goal.value.value.display(db));
130 144
131 if let Obligation::Projection(pred) = &goal.value.value { 145 if let Obligation::Projection(pred) = &goal.value.value {
132 if let Ty::BoundVar(_) = &pred.projection_ty.parameters[0] { 146 if let TyKind::BoundVar(_) = &pred.projection_ty.substitution[0].interned(&Interner) {
133 // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible 147 // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible
134 return Some(Solution::Ambig(Guidance::Unknown)); 148 return Some(Solution::Ambig(Guidance::Unknown));
135 } 149 }
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs
index 565672b6b..232cf9cd0 100644
--- a/crates/hir_ty/src/traits/chalk.rs
+++ b/crates/hir_ty/src/traits/chalk.rs
@@ -17,29 +17,31 @@ use super::ChalkContext;
17use crate::{ 17use crate::{
18 db::HirDatabase, 18 db::HirDatabase,
19 display::HirDisplay, 19 display::HirDisplay,
20 from_assoc_type_id,
20 method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, 21 method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
22 to_assoc_type_id,
21 utils::generics, 23 utils::generics,
22 BoundVar, CallableDefId, CallableSig, DebruijnIndex, GenericPredicate, ProjectionPredicate, 24 BoundVar, CallableDefId, CallableSig, DebruijnIndex, FnDefId, GenericPredicate,
23 ProjectionTy, Substs, TraitRef, Ty, 25 ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TyKind,
24}; 26};
25use mapping::{ 27use mapping::{
26 convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsAssocType, 28 convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue,
27 TypeAliasAsValue,
28}; 29};
29 30
31pub use self::interner::Interner;
30pub(crate) use self::interner::*; 32pub(crate) use self::interner::*;
31 33
32pub(super) mod tls; 34pub(super) mod tls;
33mod interner; 35mod interner;
34mod mapping; 36mod mapping;
35 37
36pub(super) trait ToChalk { 38pub(crate) trait ToChalk {
37 type Chalk; 39 type Chalk;
38 fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk; 40 fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk;
39 fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self; 41 fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self;
40} 42}
41 43
42pub(super) fn from_chalk<T, ChalkT>(db: &dyn HirDatabase, chalk: ChalkT) -> T 44pub(crate) fn from_chalk<T, ChalkT>(db: &dyn HirDatabase, chalk: ChalkT) -> T
43where 45where
44 T: ToChalk<Chalk = ChalkT>, 46 T: ToChalk<Chalk = ChalkT>,
45{ 47{
@@ -90,7 +92,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
90 ty: &Ty, 92 ty: &Ty,
91 binders: &CanonicalVarKinds<Interner>, 93 binders: &CanonicalVarKinds<Interner>,
92 ) -> Option<chalk_ir::TyVariableKind> { 94 ) -> Option<chalk_ir::TyVariableKind> {
93 if let Ty::BoundVar(bv) = ty { 95 if let TyKind::BoundVar(bv) = ty.interned(&Interner) {
94 let binders = binders.as_slice(&Interner); 96 let binders = binders.as_slice(&Interner);
95 if bv.debruijn == DebruijnIndex::INNERMOST { 97 if bv.debruijn == DebruijnIndex::INNERMOST {
96 if let chalk_ir::VariableKind::Ty(tk) = binders[bv.index].kind { 98 if let chalk_ir::VariableKind::Ty(tk) = binders[bv.index].kind {
@@ -175,10 +177,9 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
175 } 177 }
176 178
177 fn opaque_ty_data(&self, id: chalk_ir::OpaqueTyId<Interner>) -> Arc<OpaqueTyDatum> { 179 fn opaque_ty_data(&self, id: chalk_ir::OpaqueTyId<Interner>) -> Arc<OpaqueTyDatum> {
178 let interned_id = crate::db::InternedOpaqueTyId::from(id); 180 let full_id = self.db.lookup_intern_impl_trait_id(id.into());
179 let full_id = self.db.lookup_intern_impl_trait_id(interned_id);
180 let bound = match full_id { 181 let bound = match full_id {
181 crate::OpaqueTyId::ReturnTypeImplTrait(func, idx) => { 182 crate::ImplTraitId::ReturnTypeImplTrait(func, idx) => {
182 let datas = self 183 let datas = self
183 .db 184 .db
184 .return_type_impl_traits(func) 185 .return_type_impl_traits(func)
@@ -200,7 +201,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
200 let num_vars = datas.num_binders; 201 let num_vars = datas.num_binders;
201 make_binders(bound, num_vars) 202 make_binders(bound, num_vars)
202 } 203 }
203 crate::OpaqueTyId::AsyncBlockTypeImplTrait(..) => { 204 crate::ImplTraitId::AsyncBlockTypeImplTrait(..) => {
204 if let Some((future_trait, future_output)) = self 205 if let Some((future_trait, future_output)) = self
205 .db 206 .db
206 .lang_item(self.krate, "future_trait".into()) 207 .lang_item(self.krate, "future_trait".into())
@@ -220,21 +221,25 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
220 let impl_bound = GenericPredicate::Implemented(TraitRef { 221 let impl_bound = GenericPredicate::Implemented(TraitRef {
221 trait_: future_trait, 222 trait_: future_trait,
222 // Self type as the first parameter. 223 // Self type as the first parameter.
223 substs: Substs::single(Ty::BoundVar(BoundVar { 224 substs: Substs::single(
224 debruijn: DebruijnIndex::INNERMOST, 225 TyKind::BoundVar(BoundVar {
225 index: 0, 226 debruijn: DebruijnIndex::INNERMOST,
226 })), 227 index: 0,
228 })
229 .intern(&Interner),
230 ),
227 }); 231 });
228 let proj_bound = GenericPredicate::Projection(ProjectionPredicate { 232 let proj_bound = GenericPredicate::Projection(ProjectionPredicate {
229 // The parameter of the opaque type. 233 // The parameter of the opaque type.
230 ty: Ty::BoundVar(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 }), 234 ty: TyKind::BoundVar(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 })
235 .intern(&Interner),
231 projection_ty: ProjectionTy { 236 projection_ty: ProjectionTy {
232 associated_ty: future_output, 237 associated_ty_id: to_assoc_type_id(future_output),
233 // Self type as the first parameter. 238 // Self type as the first parameter.
234 parameters: Substs::single(Ty::BoundVar(BoundVar::new( 239 substitution: Substs::single(
235 DebruijnIndex::INNERMOST, 240 TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
236 0, 241 .intern(&Interner),
237 ))), 242 ),
238 }, 243 },
239 }); 244 });
240 let bound = OpaqueTyDatumBound { 245 let bound = OpaqueTyDatumBound {
@@ -263,7 +268,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
263 268
264 fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId<Interner>) -> chalk_ir::Ty<Interner> { 269 fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId<Interner>) -> chalk_ir::Ty<Interner> {
265 // FIXME: actually provide the hidden type; it is relevant for auto traits 270 // FIXME: actually provide the hidden type; it is relevant for auto traits
266 Ty::Unknown.to_chalk(self.db) 271 TyKind::Unknown.intern(&Interner).to_chalk(self.db)
267 } 272 }
268 273
269 fn is_object_safe(&self, _trait_id: chalk_ir::TraitId<Interner>) -> bool { 274 fn is_object_safe(&self, _trait_id: chalk_ir::TraitId<Interner>) -> bool {
@@ -378,7 +383,7 @@ pub(crate) fn associated_ty_data_query(
378 id: AssocTypeId, 383 id: AssocTypeId,
379) -> Arc<AssociatedTyDatum> { 384) -> Arc<AssociatedTyDatum> {
380 debug!("associated_ty_data {:?}", id); 385 debug!("associated_ty_data {:?}", id);
381 let type_alias: TypeAliasId = from_chalk::<TypeAliasAsAssocType, _>(db, id).0; 386 let type_alias: TypeAliasId = from_assoc_type_id(id);
382 let trait_ = match type_alias.lookup(db.upcast()).container { 387 let trait_ = match type_alias.lookup(db.upcast()).container {
383 AssocContainerId::TraitId(t) => t, 388 AssocContainerId::TraitId(t) => t,
384 _ => panic!("associated type not in trait"), 389 _ => panic!("associated type not in trait"),
@@ -391,11 +396,12 @@ pub(crate) fn associated_ty_data_query(
391 let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db.upcast()); 396 let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db.upcast());
392 let ctx = crate::TyLoweringContext::new(db, &resolver) 397 let ctx = crate::TyLoweringContext::new(db, &resolver)
393 .with_type_param_mode(crate::lower::TypeParamLoweringMode::Variable); 398 .with_type_param_mode(crate::lower::TypeParamLoweringMode::Variable);
394 let self_ty = Ty::BoundVar(crate::BoundVar::new(crate::DebruijnIndex::INNERMOST, 0)); 399 let self_ty =
400 TyKind::BoundVar(BoundVar::new(crate::DebruijnIndex::INNERMOST, 0)).intern(&Interner);
395 let bounds = type_alias_data 401 let bounds = type_alias_data
396 .bounds 402 .bounds
397 .iter() 403 .iter()
398 .flat_map(|bound| GenericPredicate::from_type_bound(&ctx, bound, self_ty.clone())) 404 .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone()))
399 .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty)) 405 .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty))
400 .map(|bound| make_binders(bound.shifted_in(&Interner), 0)) 406 .map(|bound| make_binders(bound.shifted_in(&Interner), 0))
401 .collect(); 407 .collect();
@@ -432,10 +438,8 @@ pub(crate) fn trait_datum_query(
432 fundamental: false, 438 fundamental: false,
433 }; 439 };
434 let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars); 440 let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars);
435 let associated_ty_ids = trait_data 441 let associated_ty_ids =
436 .associated_types() 442 trait_data.associated_types().map(|type_alias| to_assoc_type_id(type_alias)).collect();
437 .map(|type_alias| TypeAliasAsAssocType(type_alias).to_chalk(db))
438 .collect();
439 let trait_datum_bound = rust_ir::TraitDatumBound { where_clauses }; 443 let trait_datum_bound = rust_ir::TraitDatumBound { where_clauses };
440 let well_known = 444 let well_known =
441 lang_attr(db.upcast(), trait_).and_then(|name| well_known_trait_from_lang_attr(&name)); 445 lang_attr(db.upcast(), trait_).and_then(|name| well_known_trait_from_lang_attr(&name));
@@ -487,19 +491,14 @@ pub(crate) fn struct_datum_query(
487 struct_id: AdtId, 491 struct_id: AdtId,
488) -> Arc<StructDatum> { 492) -> Arc<StructDatum> {
489 debug!("struct_datum {:?}", struct_id); 493 debug!("struct_datum {:?}", struct_id);
490 let type_ctor = Ty::Adt(struct_id, Substs::empty());
491 let chalk_ir::AdtId(adt_id) = struct_id; 494 let chalk_ir::AdtId(adt_id) = struct_id;
492 debug!("struct {:?} = {:?}", struct_id, type_ctor);
493 let num_params = generics(db.upcast(), adt_id.into()).len(); 495 let num_params = generics(db.upcast(), adt_id.into()).len();
494 let upstream = adt_id.module(db.upcast()).krate() != krate; 496 let upstream = adt_id.module(db.upcast()).krate() != krate;
495 let where_clauses = type_ctor 497 let where_clauses = {
496 .as_generic_def() 498 let generic_params = generics(db.upcast(), adt_id.into());
497 .map(|generic_def| { 499 let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST);
498 let generic_params = generics(db.upcast(), generic_def); 500 convert_where_clauses(db, adt_id.into(), &bound_vars)
499 let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST); 501 };
500 convert_where_clauses(db, generic_def, &bound_vars)
501 })
502 .unwrap_or_else(Vec::new);
503 let flags = rust_ir::AdtFlags { 502 let flags = rust_ir::AdtFlags {
504 upstream, 503 upstream,
505 // FIXME set fundamental and phantom_data flags correctly 504 // FIXME set fundamental and phantom_data flags correctly
@@ -622,7 +621,7 @@ fn type_alias_associated_ty_value(
622 let value_bound = rust_ir::AssociatedTyValueBound { ty: ty.value.to_chalk(db) }; 621 let value_bound = rust_ir::AssociatedTyValueBound { ty: ty.value.to_chalk(db) };
623 let value = rust_ir::AssociatedTyValue { 622 let value = rust_ir::AssociatedTyValue {
624 impl_id: impl_id.to_chalk(db), 623 impl_id: impl_id.to_chalk(db),
625 associated_ty_id: TypeAliasAsAssocType(assoc_ty).to_chalk(db), 624 associated_ty_id: to_assoc_type_id(assoc_ty),
626 value: make_binders(value_bound, ty.num_binders), 625 value: make_binders(value_bound, ty.num_binders),
627 }; 626 };
628 Arc::new(value) 627 Arc::new(value)
@@ -716,14 +715,14 @@ impl From<crate::db::InternedOpaqueTyId> for OpaqueTyId {
716 } 715 }
717} 716}
718 717
719impl From<chalk_ir::ClosureId<Interner>> for crate::db::ClosureId { 718impl From<chalk_ir::ClosureId<Interner>> for crate::db::InternedClosureId {
720 fn from(id: chalk_ir::ClosureId<Interner>) -> Self { 719 fn from(id: chalk_ir::ClosureId<Interner>) -> Self {
721 Self::from_intern_id(id.0) 720 Self::from_intern_id(id.0)
722 } 721 }
723} 722}
724 723
725impl From<crate::db::ClosureId> for chalk_ir::ClosureId<Interner> { 724impl From<crate::db::InternedClosureId> for chalk_ir::ClosureId<Interner> {
726 fn from(id: crate::db::ClosureId) -> Self { 725 fn from(id: crate::db::InternedClosureId) -> Self {
727 chalk_ir::ClosureId(id.as_intern_id()) 726 chalk_ir::ClosureId(id.as_intern_id())
728 } 727 }
729} 728}
diff --git a/crates/hir_ty/src/traits/chalk/interner.rs b/crates/hir_ty/src/traits/chalk/interner.rs
index 54bd1c724..1dc3f497d 100644
--- a/crates/hir_ty/src/traits/chalk/interner.rs
+++ b/crates/hir_ty/src/traits/chalk/interner.rs
@@ -12,7 +12,6 @@ pub struct Interner;
12 12
13pub(crate) type AssocTypeId = chalk_ir::AssocTypeId<Interner>; 13pub(crate) type AssocTypeId = chalk_ir::AssocTypeId<Interner>;
14pub(crate) type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>; 14pub(crate) type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>;
15pub(crate) type ForeignDefId = chalk_ir::ForeignDefId<Interner>;
16pub(crate) type TraitId = chalk_ir::TraitId<Interner>; 15pub(crate) type TraitId = chalk_ir::TraitId<Interner>;
17pub(crate) type TraitDatum = chalk_solve::rust_ir::TraitDatum<Interner>; 16pub(crate) type TraitDatum = chalk_solve::rust_ir::TraitDatum<Interner>;
18pub(crate) type AdtId = chalk_ir::AdtId<Interner>; 17pub(crate) type AdtId = chalk_ir::AdtId<Interner>;
@@ -21,7 +20,6 @@ pub(crate) type ImplId = chalk_ir::ImplId<Interner>;
21pub(crate) type ImplDatum = chalk_solve::rust_ir::ImplDatum<Interner>; 20pub(crate) type ImplDatum = chalk_solve::rust_ir::ImplDatum<Interner>;
22pub(crate) type AssociatedTyValueId = chalk_solve::rust_ir::AssociatedTyValueId<Interner>; 21pub(crate) type AssociatedTyValueId = chalk_solve::rust_ir::AssociatedTyValueId<Interner>;
23pub(crate) type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue<Interner>; 22pub(crate) type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue<Interner>;
24pub(crate) type FnDefId = chalk_ir::FnDefId<Interner>;
25pub(crate) type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>; 23pub(crate) type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>;
26pub(crate) type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; 24pub(crate) type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
27pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum<Interner>; 25pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum<Interner>;
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs
index 3a08b67e9..05a4bf0df 100644
--- a/crates/hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/hir_ty/src/traits/chalk/mapping.rs
@@ -3,10 +3,7 @@
3//! Chalk (in both directions); plus some helper functions for more specialized 3//! Chalk (in both directions); plus some helper functions for more specialized
4//! conversions. 4//! conversions.
5 5
6use chalk_ir::{ 6use chalk_ir::{cast::Cast, fold::shift::Shift, interner::HasInterner, LifetimeData};
7 cast::Cast, fold::shift::Shift, interner::HasInterner, LifetimeData, PlaceholderIndex,
8 UniverseIndex,
9};
10use chalk_solve::rust_ir; 7use chalk_solve::rust_ir;
11 8
12use base_db::salsa::InternKey; 9use base_db::salsa::InternKey;
@@ -14,10 +11,11 @@ use hir_def::{AssocContainerId, GenericDefId, Lookup, TypeAliasId};
14 11
15use crate::{ 12use crate::{
16 db::HirDatabase, 13 db::HirDatabase,
14 from_assoc_type_id,
17 primitive::UintTy, 15 primitive::UintTy,
18 traits::{Canonical, Obligation}, 16 traits::{Canonical, Obligation},
19 AliasTy, CallableDefId, FnPointer, FnSig, GenericPredicate, InEnvironment, OpaqueTy, 17 AliasTy, CallableDefId, FnPointer, GenericPredicate, InEnvironment, OpaqueTy,
20 OpaqueTyId, ProjectionPredicate, ProjectionTy, Scalar, Substs, TraitEnvironment, TraitRef, Ty, 18 ProjectionPredicate, ProjectionTy, Scalar, Substs, TraitRef, Ty,
21}; 19};
22 20
23use super::interner::*; 21use super::interner::*;
@@ -26,71 +24,62 @@ use super::*;
26impl ToChalk for Ty { 24impl ToChalk for Ty {
27 type Chalk = chalk_ir::Ty<Interner>; 25 type Chalk = chalk_ir::Ty<Interner>;
28 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> { 26 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> {
29 match self { 27 match self.0 {
30 Ty::Ref(m, parameters) => ref_to_chalk(db, m, parameters), 28 TyKind::Ref(m, parameters) => ref_to_chalk(db, m, parameters),
31 Ty::Array(parameters) => array_to_chalk(db, parameters), 29 TyKind::Array(parameters) => array_to_chalk(db, parameters),
32 Ty::Function(FnPointer { sig: FnSig { variadic }, substs, .. }) => { 30 TyKind::Function(FnPointer { sig, substs, .. }) => {
33 let substitution = chalk_ir::FnSubst(substs.to_chalk(db).shifted_in(&Interner)); 31 let substitution = chalk_ir::FnSubst(substs.to_chalk(db).shifted_in(&Interner));
34 chalk_ir::TyKind::Function(chalk_ir::FnPointer { 32 chalk_ir::TyKind::Function(chalk_ir::FnPointer {
35 num_binders: 0, 33 num_binders: 0,
36 sig: chalk_ir::FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic }, 34 sig,
37 substitution, 35 substitution,
38 }) 36 })
39 .intern(&Interner) 37 .intern(&Interner)
40 } 38 }
41 Ty::AssociatedType(type_alias, substs) => { 39 TyKind::AssociatedType(assoc_type_id, substs) => {
42 let assoc_type = TypeAliasAsAssocType(type_alias);
43 let assoc_type_id = assoc_type.to_chalk(db);
44 let substitution = substs.to_chalk(db); 40 let substitution = substs.to_chalk(db);
45 chalk_ir::TyKind::AssociatedType(assoc_type_id, substitution).intern(&Interner) 41 chalk_ir::TyKind::AssociatedType(assoc_type_id, substitution).intern(&Interner)
46 } 42 }
47 43
48 Ty::OpaqueType(impl_trait_id, substs) => { 44 TyKind::OpaqueType(id, substs) => {
49 let id = impl_trait_id.to_chalk(db);
50 let substitution = substs.to_chalk(db); 45 let substitution = substs.to_chalk(db);
51 chalk_ir::TyKind::OpaqueType(id, substitution).intern(&Interner) 46 chalk_ir::TyKind::OpaqueType(id, substitution).intern(&Interner)
52 } 47 }
53 48
54 Ty::ForeignType(type_alias) => { 49 TyKind::ForeignType(id) => chalk_ir::TyKind::Foreign(id).intern(&Interner),
55 let foreign_type = TypeAliasAsForeignType(type_alias);
56 let foreign_type_id = foreign_type.to_chalk(db);
57 chalk_ir::TyKind::Foreign(foreign_type_id).intern(&Interner)
58 }
59 50
60 Ty::Scalar(scalar) => chalk_ir::TyKind::Scalar(scalar).intern(&Interner), 51 TyKind::Scalar(scalar) => chalk_ir::TyKind::Scalar(scalar).intern(&Interner),
61 52
62 Ty::Tuple(cardinality, substs) => { 53 TyKind::Tuple(cardinality, substs) => {
63 let substitution = substs.to_chalk(db); 54 let substitution = substs.to_chalk(db);
64 chalk_ir::TyKind::Tuple(cardinality.into(), substitution).intern(&Interner) 55 chalk_ir::TyKind::Tuple(cardinality.into(), substitution).intern(&Interner)
65 } 56 }
66 Ty::Raw(mutability, substs) => { 57 TyKind::Raw(mutability, substs) => {
67 let ty = substs[0].clone().to_chalk(db); 58 let ty = substs[0].clone().to_chalk(db);
68 chalk_ir::TyKind::Raw(mutability, ty).intern(&Interner) 59 chalk_ir::TyKind::Raw(mutability, ty).intern(&Interner)
69 } 60 }
70 Ty::Slice(substs) => { 61 TyKind::Slice(substs) => {
71 chalk_ir::TyKind::Slice(substs[0].clone().to_chalk(db)).intern(&Interner) 62 chalk_ir::TyKind::Slice(substs[0].clone().to_chalk(db)).intern(&Interner)
72 } 63 }
73 Ty::Str => chalk_ir::TyKind::Str.intern(&Interner), 64 TyKind::Str => chalk_ir::TyKind::Str.intern(&Interner),
74 Ty::FnDef(callable_def, substs) => { 65 TyKind::FnDef(id, substs) => {
75 let id = callable_def.to_chalk(db);
76 let substitution = substs.to_chalk(db); 66 let substitution = substs.to_chalk(db);
77 chalk_ir::TyKind::FnDef(id, substitution).intern(&Interner) 67 chalk_ir::TyKind::FnDef(id, substitution).intern(&Interner)
78 } 68 }
79 Ty::Never => chalk_ir::TyKind::Never.intern(&Interner), 69 TyKind::Never => chalk_ir::TyKind::Never.intern(&Interner),
80 70
81 Ty::Closure(def, expr, substs) => { 71 TyKind::Closure(closure_id, substs) => {
82 let closure_id = db.intern_closure((def, expr));
83 let substitution = substs.to_chalk(db); 72 let substitution = substs.to_chalk(db);
84 chalk_ir::TyKind::Closure(closure_id.into(), substitution).intern(&Interner) 73 chalk_ir::TyKind::Closure(closure_id, substitution).intern(&Interner)
85 } 74 }
86 75
87 Ty::Adt(adt_id, substs) => { 76 TyKind::Adt(adt_id, substs) => {
88 let substitution = substs.to_chalk(db); 77 let substitution = substs.to_chalk(db);
89 chalk_ir::TyKind::Adt(adt_id, substitution).intern(&Interner) 78 chalk_ir::TyKind::Adt(adt_id, substitution).intern(&Interner)
90 } 79 }
91 Ty::Alias(AliasTy::Projection(proj_ty)) => { 80 TyKind::Alias(AliasTy::Projection(proj_ty)) => {
92 let associated_ty_id = TypeAliasAsAssocType(proj_ty.associated_ty).to_chalk(db); 81 let associated_ty_id = proj_ty.associated_ty_id;
93 let substitution = proj_ty.parameters.to_chalk(db); 82 let substitution = proj_ty.substitution.to_chalk(db);
94 chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy { 83 chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
95 associated_ty_id, 84 associated_ty_id,
96 substitution, 85 substitution,
@@ -98,17 +87,17 @@ impl ToChalk for Ty {
98 .cast(&Interner) 87 .cast(&Interner)
99 .intern(&Interner) 88 .intern(&Interner)
100 } 89 }
101 Ty::Placeholder(id) => { 90 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
102 let interned_id = db.intern_type_param_id(id); 91 let opaque_ty_id = opaque_ty.opaque_ty_id;
103 PlaceholderIndex { 92 let substitution = opaque_ty.substitution.to_chalk(db);
104 ui: UniverseIndex::ROOT, 93 chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy { opaque_ty_id, substitution })
105 idx: interned_id.as_intern_id().as_usize(), 94 .cast(&Interner)
106 } 95 .intern(&Interner)
107 .to_ty::<Interner>(&Interner) 96 }
108 } 97 TyKind::Placeholder(idx) => idx.to_ty::<Interner>(&Interner),
109 Ty::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner), 98 TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner),
110 Ty::InferenceVar(..) => panic!("uncanonicalized infer ty"), 99 TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"),
111 Ty::Dyn(predicates) => { 100 TyKind::Dyn(predicates) => {
112 let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter( 101 let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter(
113 &Interner, 102 &Interner,
114 predicates.iter().filter(|p| !p.is_error()).cloned().map(|p| p.to_chalk(db)), 103 predicates.iter().filter(|p| !p.is_error()).cloned().map(|p| p.to_chalk(db)),
@@ -119,43 +108,30 @@ impl ToChalk for Ty {
119 }; 108 };
120 chalk_ir::TyKind::Dyn(bounded_ty).intern(&Interner) 109 chalk_ir::TyKind::Dyn(bounded_ty).intern(&Interner)
121 } 110 }
122 Ty::Alias(AliasTy::Opaque(opaque_ty)) => { 111 TyKind::Unknown => chalk_ir::TyKind::Error.intern(&Interner),
123 let opaque_ty_id = opaque_ty.opaque_ty_id.to_chalk(db);
124 let substitution = opaque_ty.parameters.to_chalk(db);
125 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy {
126 opaque_ty_id,
127 substitution,
128 }))
129 .intern(&Interner)
130 }
131 Ty::Unknown => chalk_ir::TyKind::Error.intern(&Interner),
132 } 112 }
133 } 113 }
134 fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self { 114 fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self {
135 match chalk.data(&Interner).kind.clone() { 115 match chalk.data(&Interner).kind.clone() {
136 chalk_ir::TyKind::Error => Ty::Unknown, 116 chalk_ir::TyKind::Error => TyKind::Unknown,
137 chalk_ir::TyKind::Array(ty, _size) => Ty::Array(Substs::single(from_chalk(db, ty))), 117 chalk_ir::TyKind::Array(ty, _size) => TyKind::Array(Substs::single(from_chalk(db, ty))),
138 chalk_ir::TyKind::Placeholder(idx) => { 118 chalk_ir::TyKind::Placeholder(idx) => TyKind::Placeholder(idx),
139 assert_eq!(idx.ui, UniverseIndex::ROOT);
140 let interned_id = crate::db::GlobalTypeParamId::from_intern_id(
141 crate::salsa::InternId::from(idx.idx),
142 );
143 Ty::Placeholder(db.lookup_intern_type_param_id(interned_id))
144 }
145 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(proj)) => { 119 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(proj)) => {
146 let associated_ty = 120 let associated_ty = proj.associated_ty_id;
147 from_chalk::<TypeAliasAsAssocType, _>(db, proj.associated_ty_id).0;
148 let parameters = from_chalk(db, proj.substitution); 121 let parameters = from_chalk(db, proj.substitution);
149 Ty::Alias(AliasTy::Projection(ProjectionTy { associated_ty, parameters })) 122 TyKind::Alias(AliasTy::Projection(ProjectionTy {
123 associated_ty_id: associated_ty,
124 substitution: parameters,
125 }))
150 } 126 }
151 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(opaque_ty)) => { 127 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(opaque_ty)) => {
152 let impl_trait_id = from_chalk(db, opaque_ty.opaque_ty_id); 128 let opaque_ty_id = opaque_ty.opaque_ty_id;
153 let parameters = from_chalk(db, opaque_ty.substitution); 129 let parameters = from_chalk(db, opaque_ty.substitution);
154 Ty::Alias(AliasTy::Opaque(OpaqueTy { opaque_ty_id: impl_trait_id, parameters })) 130 TyKind::Alias(AliasTy::Opaque(OpaqueTy { opaque_ty_id, substitution: parameters }))
155 } 131 }
156 chalk_ir::TyKind::Function(chalk_ir::FnPointer { 132 chalk_ir::TyKind::Function(chalk_ir::FnPointer {
157 num_binders, 133 num_binders,
158 sig: chalk_ir::FnSig { variadic, .. }, 134 sig,
159 substitution, 135 substitution,
160 .. 136 ..
161 }) => { 137 }) => {
@@ -164,14 +140,10 @@ impl ToChalk for Ty {
164 db, 140 db,
165 substitution.0.shifted_out(&Interner).expect("fn ptr should have no binders"), 141 substitution.0.shifted_out(&Interner).expect("fn ptr should have no binders"),
166 ); 142 );
167 Ty::Function(FnPointer { 143 TyKind::Function(FnPointer { num_args: (substs.len() - 1), sig, substs })
168 num_args: (substs.len() - 1),
169 sig: FnSig { variadic },
170 substs,
171 })
172 } 144 }
173 chalk_ir::TyKind::BoundVar(idx) => Ty::BoundVar(idx), 145 chalk_ir::TyKind::BoundVar(idx) => TyKind::BoundVar(idx),
174 chalk_ir::TyKind::InferenceVar(_iv, _kind) => Ty::Unknown, 146 chalk_ir::TyKind::InferenceVar(_iv, _kind) => TyKind::Unknown,
175 chalk_ir::TyKind::Dyn(where_clauses) => { 147 chalk_ir::TyKind::Dyn(where_clauses) => {
176 assert_eq!(where_clauses.bounds.binders.len(&Interner), 1); 148 assert_eq!(where_clauses.bounds.binders.len(&Interner), 1);
177 let predicates = where_clauses 149 let predicates = where_clauses
@@ -180,49 +152,43 @@ impl ToChalk for Ty {
180 .iter(&Interner) 152 .iter(&Interner)
181 .map(|c| from_chalk(db, c.clone())) 153 .map(|c| from_chalk(db, c.clone()))
182 .collect(); 154 .collect();
183 Ty::Dyn(predicates) 155 TyKind::Dyn(predicates)
184 } 156 }
185 157
186 chalk_ir::TyKind::Adt(adt_id, subst) => Ty::Adt(adt_id, from_chalk(db, subst)), 158 chalk_ir::TyKind::Adt(adt_id, subst) => TyKind::Adt(adt_id, from_chalk(db, subst)),
187 chalk_ir::TyKind::AssociatedType(type_id, subst) => Ty::AssociatedType( 159 chalk_ir::TyKind::AssociatedType(type_id, subst) => {
188 from_chalk::<TypeAliasAsAssocType, _>(db, type_id).0, 160 TyKind::AssociatedType(type_id, from_chalk(db, subst))
189 from_chalk(db, subst), 161 }
190 ),
191 162
192 chalk_ir::TyKind::OpaqueType(opaque_type_id, subst) => { 163 chalk_ir::TyKind::OpaqueType(opaque_type_id, subst) => {
193 Ty::OpaqueType(from_chalk(db, opaque_type_id), from_chalk(db, subst)) 164 TyKind::OpaqueType(opaque_type_id, from_chalk(db, subst))
194 } 165 }
195 166
196 chalk_ir::TyKind::Scalar(scalar) => Ty::Scalar(scalar), 167 chalk_ir::TyKind::Scalar(scalar) => TyKind::Scalar(scalar),
197 chalk_ir::TyKind::Tuple(cardinality, subst) => { 168 chalk_ir::TyKind::Tuple(cardinality, subst) => {
198 Ty::Tuple(cardinality, from_chalk(db, subst)) 169 TyKind::Tuple(cardinality, from_chalk(db, subst))
199 } 170 }
200 chalk_ir::TyKind::Raw(mutability, ty) => { 171 chalk_ir::TyKind::Raw(mutability, ty) => {
201 Ty::Raw(mutability, Substs::single(from_chalk(db, ty))) 172 TyKind::Raw(mutability, Substs::single(from_chalk(db, ty)))
202 } 173 }
203 chalk_ir::TyKind::Slice(ty) => Ty::Slice(Substs::single(from_chalk(db, ty))), 174 chalk_ir::TyKind::Slice(ty) => TyKind::Slice(Substs::single(from_chalk(db, ty))),
204 chalk_ir::TyKind::Ref(mutability, _lifetime, ty) => { 175 chalk_ir::TyKind::Ref(mutability, _lifetime, ty) => {
205 Ty::Ref(mutability, Substs::single(from_chalk(db, ty))) 176 TyKind::Ref(mutability, Substs::single(from_chalk(db, ty)))
206 } 177 }
207 chalk_ir::TyKind::Str => Ty::Str, 178 chalk_ir::TyKind::Str => TyKind::Str,
208 chalk_ir::TyKind::Never => Ty::Never, 179 chalk_ir::TyKind::Never => TyKind::Never,
209 180
210 chalk_ir::TyKind::FnDef(fn_def_id, subst) => { 181 chalk_ir::TyKind::FnDef(fn_def_id, subst) => {
211 Ty::FnDef(from_chalk(db, fn_def_id), from_chalk(db, subst)) 182 TyKind::FnDef(fn_def_id, from_chalk(db, subst))
212 } 183 }
213 184
214 chalk_ir::TyKind::Closure(id, subst) => { 185 chalk_ir::TyKind::Closure(id, subst) => TyKind::Closure(id, from_chalk(db, subst)),
215 let id: crate::db::ClosureId = id.into();
216 let (def, expr) = db.lookup_intern_closure(id);
217 Ty::Closure(def, expr, from_chalk(db, subst))
218 }
219 186
220 chalk_ir::TyKind::Foreign(foreign_def_id) => { 187 chalk_ir::TyKind::Foreign(foreign_def_id) => TyKind::ForeignType(foreign_def_id),
221 Ty::ForeignType(from_chalk::<TypeAliasAsForeignType, _>(db, foreign_def_id).0)
222 }
223 chalk_ir::TyKind::Generator(_, _) => unimplemented!(), // FIXME 188 chalk_ir::TyKind::Generator(_, _) => unimplemented!(), // FIXME
224 chalk_ir::TyKind::GeneratorWitness(_, _) => unimplemented!(), // FIXME 189 chalk_ir::TyKind::GeneratorWitness(_, _) => unimplemented!(), // FIXME
225 } 190 }
191 .intern(&Interner)
226 } 192 }
227} 193}
228 194
@@ -298,21 +264,6 @@ impl ToChalk for hir_def::TraitId {
298 } 264 }
299} 265}
300 266
301impl ToChalk for OpaqueTyId {
302 type Chalk = chalk_ir::OpaqueTyId<Interner>;
303
304 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::OpaqueTyId<Interner> {
305 db.intern_impl_trait_id(self).into()
306 }
307
308 fn from_chalk(
309 db: &dyn HirDatabase,
310 opaque_ty_id: chalk_ir::OpaqueTyId<Interner>,
311 ) -> OpaqueTyId {
312 db.lookup_intern_impl_trait_id(opaque_ty_id.into())
313 }
314}
315
316impl ToChalk for hir_def::ImplId { 267impl ToChalk for hir_def::ImplId {
317 type Chalk = ImplId; 268 type Chalk = ImplId;
318 269
@@ -337,34 +288,6 @@ impl ToChalk for CallableDefId {
337 } 288 }
338} 289}
339 290
340pub(crate) struct TypeAliasAsAssocType(pub(crate) TypeAliasId);
341
342impl ToChalk for TypeAliasAsAssocType {
343 type Chalk = AssocTypeId;
344
345 fn to_chalk(self, _db: &dyn HirDatabase) -> AssocTypeId {
346 chalk_ir::AssocTypeId(self.0.as_intern_id())
347 }
348
349 fn from_chalk(_db: &dyn HirDatabase, assoc_type_id: AssocTypeId) -> TypeAliasAsAssocType {
350 TypeAliasAsAssocType(InternKey::from_intern_id(assoc_type_id.0))
351 }
352}
353
354pub(crate) struct TypeAliasAsForeignType(pub(crate) TypeAliasId);
355
356impl ToChalk for TypeAliasAsForeignType {
357 type Chalk = ForeignDefId;
358
359 fn to_chalk(self, _db: &dyn HirDatabase) -> ForeignDefId {
360 chalk_ir::ForeignDefId(self.0.as_intern_id())
361 }
362
363 fn from_chalk(_db: &dyn HirDatabase, foreign_def_id: ForeignDefId) -> TypeAliasAsForeignType {
364 TypeAliasAsForeignType(InternKey::from_intern_id(foreign_def_id.0))
365 }
366}
367
368pub(crate) struct TypeAliasAsValue(pub(crate) TypeAliasId); 291pub(crate) struct TypeAliasAsValue(pub(crate) TypeAliasId);
369 292
370impl ToChalk for TypeAliasAsValue { 293impl ToChalk for TypeAliasAsValue {
@@ -446,8 +369,8 @@ impl ToChalk for ProjectionTy {
446 369
447 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::ProjectionTy<Interner> { 370 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::ProjectionTy<Interner> {
448 chalk_ir::ProjectionTy { 371 chalk_ir::ProjectionTy {
449 associated_ty_id: TypeAliasAsAssocType(self.associated_ty).to_chalk(db), 372 associated_ty_id: self.associated_ty_id,
450 substitution: self.parameters.to_chalk(db), 373 substitution: self.substitution.to_chalk(db),
451 } 374 }
452 } 375 }
453 376
@@ -456,12 +379,8 @@ impl ToChalk for ProjectionTy {
456 projection_ty: chalk_ir::ProjectionTy<Interner>, 379 projection_ty: chalk_ir::ProjectionTy<Interner>,
457 ) -> ProjectionTy { 380 ) -> ProjectionTy {
458 ProjectionTy { 381 ProjectionTy {
459 associated_ty: from_chalk::<TypeAliasAsAssocType, _>( 382 associated_ty_id: projection_ty.associated_ty_id,
460 db, 383 substitution: from_chalk(db, projection_ty.substitution),
461 projection_ty.associated_ty_id,
462 )
463 .0,
464 parameters: from_chalk(db, projection_ty.substitution),
465 } 384 }
466 } 385 }
467} 386}
@@ -536,31 +455,6 @@ where
536 } 455 }
537} 456}
538 457
539impl ToChalk for Arc<TraitEnvironment> {
540 type Chalk = chalk_ir::Environment<Interner>;
541
542 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Environment<Interner> {
543 let mut clauses = Vec::new();
544 for pred in &self.predicates {
545 if pred.is_error() {
546 // for env, we just ignore errors
547 continue;
548 }
549 let program_clause: chalk_ir::ProgramClause<Interner> =
550 pred.clone().to_chalk(db).cast(&Interner);
551 clauses.push(program_clause.into_from_env_clause(&Interner));
552 }
553 chalk_ir::Environment::new(&Interner).add_clauses(&Interner, clauses)
554 }
555
556 fn from_chalk(
557 _db: &dyn HirDatabase,
558 _env: chalk_ir::Environment<Interner>,
559 ) -> Arc<TraitEnvironment> {
560 unimplemented!()
561 }
562}
563
564impl<T: ToChalk> ToChalk for InEnvironment<T> 458impl<T: ToChalk> ToChalk for InEnvironment<T>
565where 459where
566 T::Chalk: chalk_ir::interner::HasInterner<Interner = Interner>, 460 T::Chalk: chalk_ir::interner::HasInterner<Interner = Interner>,
@@ -569,19 +463,16 @@ where
569 463
570 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> { 464 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> {
571 chalk_ir::InEnvironment { 465 chalk_ir::InEnvironment {
572 environment: self.environment.to_chalk(db), 466 environment: self.environment.env.clone(),
573 goal: self.value.to_chalk(db), 467 goal: self.value.to_chalk(db),
574 } 468 }
575 } 469 }
576 470
577 fn from_chalk( 471 fn from_chalk(
578 db: &dyn HirDatabase, 472 _db: &dyn HirDatabase,
579 in_env: chalk_ir::InEnvironment<T::Chalk>, 473 _in_env: chalk_ir::InEnvironment<T::Chalk>,
580 ) -> InEnvironment<T> { 474 ) -> InEnvironment<T> {
581 InEnvironment { 475 unimplemented!()
582 environment: from_chalk(db, in_env.environment),
583 value: from_chalk(db, in_env.goal),
584 }
585 } 476 }
586} 477}
587 478
@@ -639,22 +530,24 @@ pub(super) fn generic_predicate_to_inline_bound(
639 Some(rust_ir::InlineBound::TraitBound(trait_bound)) 530 Some(rust_ir::InlineBound::TraitBound(trait_bound))
640 } 531 }
641 GenericPredicate::Projection(proj) => { 532 GenericPredicate::Projection(proj) => {
642 if &proj.projection_ty.parameters[0] != self_ty { 533 if &proj.projection_ty.substitution[0] != self_ty {
643 return None; 534 return None;
644 } 535 }
645 let trait_ = match proj.projection_ty.associated_ty.lookup(db.upcast()).container { 536 let trait_ = match from_assoc_type_id(proj.projection_ty.associated_ty_id)
537 .lookup(db.upcast())
538 .container
539 {
646 AssocContainerId::TraitId(t) => t, 540 AssocContainerId::TraitId(t) => t,
647 _ => panic!("associated type not in trait"), 541 _ => panic!("associated type not in trait"),
648 }; 542 };
649 let args_no_self = proj.projection_ty.parameters[1..] 543 let args_no_self = proj.projection_ty.substitution[1..]
650 .iter() 544 .iter()
651 .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) 545 .map(|ty| ty.clone().to_chalk(db).cast(&Interner))
652 .collect(); 546 .collect();
653 let alias_eq_bound = rust_ir::AliasEqBound { 547 let alias_eq_bound = rust_ir::AliasEqBound {
654 value: proj.ty.clone().to_chalk(db), 548 value: proj.ty.clone().to_chalk(db),
655 trait_bound: rust_ir::TraitBound { trait_id: trait_.to_chalk(db), args_no_self }, 549 trait_bound: rust_ir::TraitBound { trait_id: trait_.to_chalk(db), args_no_self },
656 associated_ty_id: TypeAliasAsAssocType(proj.projection_ty.associated_ty) 550 associated_ty_id: proj.projection_ty.associated_ty_id,
657 .to_chalk(db),
658 parameters: Vec::new(), // FIXME we don't support generic associated types yet 551 parameters: Vec::new(), // FIXME we don't support generic associated types yet
659 }; 552 };
660 Some(rust_ir::InlineBound::AliasEqBound(alias_eq_bound)) 553 Some(rust_ir::InlineBound::AliasEqBound(alias_eq_bound))
diff --git a/crates/hir_ty/src/traits/chalk/tls.rs b/crates/hir_ty/src/traits/chalk/tls.rs
index 75b16172e..8892a63a9 100644
--- a/crates/hir_ty/src/traits/chalk/tls.rs
+++ b/crates/hir_ty/src/traits/chalk/tls.rs
@@ -4,8 +4,8 @@ use std::fmt;
4use chalk_ir::{AliasTy, GenericArg, Goal, Goals, Lifetime, ProgramClauseImplication}; 4use chalk_ir::{AliasTy, GenericArg, Goal, Goals, Lifetime, ProgramClauseImplication};
5use itertools::Itertools; 5use itertools::Itertools;
6 6
7use super::{from_chalk, Interner, TypeAliasAsAssocType}; 7use super::{from_chalk, Interner};
8use crate::{db::HirDatabase, CallableDefId}; 8use crate::{db::HirDatabase, from_assoc_type_id, CallableDefId};
9use hir_def::{AdtId, AssocContainerId, Lookup, TypeAliasId}; 9use hir_def::{AdtId, AssocContainerId, Lookup, TypeAliasId};
10 10
11pub(crate) use unsafe_tls::{set_current_program, with_current_program}; 11pub(crate) use unsafe_tls::{set_current_program, with_current_program};
@@ -41,7 +41,7 @@ impl DebugContext<'_> {
41 id: super::AssocTypeId, 41 id: super::AssocTypeId,
42 fmt: &mut fmt::Formatter<'_>, 42 fmt: &mut fmt::Formatter<'_>,
43 ) -> Result<(), fmt::Error> { 43 ) -> Result<(), fmt::Error> {
44 let type_alias: TypeAliasId = from_chalk::<TypeAliasAsAssocType, _>(self.0, id).0; 44 let type_alias: TypeAliasId = from_assoc_type_id(id);
45 let type_alias_data = self.0.type_alias_data(type_alias); 45 let type_alias_data = self.0.type_alias_data(type_alias);
46 let trait_ = match type_alias.lookup(self.0.upcast()).container { 46 let trait_ = match type_alias.lookup(self.0.upcast()).container {
47 AssocContainerId::TraitId(t) => t, 47 AssocContainerId::TraitId(t) => t,
@@ -75,8 +75,7 @@ impl DebugContext<'_> {
75 projection_ty: &chalk_ir::ProjectionTy<Interner>, 75 projection_ty: &chalk_ir::ProjectionTy<Interner>,
76 fmt: &mut fmt::Formatter<'_>, 76 fmt: &mut fmt::Formatter<'_>,
77 ) -> Result<(), fmt::Error> { 77 ) -> Result<(), fmt::Error> {
78 let type_alias: TypeAliasId = 78 let type_alias = from_assoc_type_id(projection_ty.associated_ty_id);
79 from_chalk::<TypeAliasAsAssocType, _>(self.0, projection_ty.associated_ty_id).0;
80 let type_alias_data = self.0.type_alias_data(type_alias); 79 let type_alias_data = self.0.type_alias_data(type_alias);
81 let trait_ = match type_alias.lookup(self.0.upcast()).container { 80 let trait_ = match type_alias.lookup(self.0.upcast()).container {
82 AssocContainerId::TraitId(t) => t, 81 AssocContainerId::TraitId(t) => t,
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index d1a250d48..a8b169e87 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -87,7 +87,7 @@ pub use crate::{
87pub use hir::{Documentation, Semantics}; 87pub use hir::{Documentation, Semantics};
88pub use ide_assists::{Assist, AssistConfig, AssistId, AssistKind}; 88pub use ide_assists::{Assist, AssistConfig, AssistId, AssistKind};
89pub use ide_completion::{ 89pub use ide_completion::{
90 CompletionConfig, CompletionItem, CompletionItemKind, CompletionScore, ImportEdit, 90 CompletionConfig, CompletionItem, CompletionItemKind, CompletionRelevance, ImportEdit,
91 InsertTextFormat, 91 InsertTextFormat,
92}; 92};
93pub use ide_db::{ 93pub use ide_db::{
@@ -447,6 +447,15 @@ impl Analysis {
447 self.with_db(|db| runnables::runnables(db, file_id)) 447 self.with_db(|db| runnables::runnables(db, file_id))
448 } 448 }
449 449
450 /// Returns the set of tests for the given file position.
451 pub fn related_tests(
452 &self,
453 position: FilePosition,
454 search_scope: Option<SearchScope>,
455 ) -> Cancelable<Vec<Runnable>> {
456 self.with_db(|db| runnables::related_tests(db, position, search_scope))
457 }
458
450 /// Computes syntax highlighting for the given file 459 /// Computes syntax highlighting for the given file
451 pub fn highlight(&self, file_id: FileId) -> Cancelable<Vec<HlRange>> { 460 pub fn highlight(&self, file_id: FileId) -> Cancelable<Vec<HlRange>> {
452 self.with_db(|db| syntax_highlighting::highlight(db, file_id, None, false)) 461 self.with_db(|db| syntax_highlighting::highlight(db, file_id, None, false))
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs
index bb68bcc78..1e378279d 100644
--- a/crates/ide/src/references/rename.rs
+++ b/crates/ide/src/references/rename.rs
@@ -21,7 +21,7 @@ use crate::{display::TryToNav, FilePosition, FileSystemEdit, RangeInfo, SourceCh
21 21
22type RenameResult<T> = Result<T, RenameError>; 22type RenameResult<T> = Result<T, RenameError>;
23#[derive(Debug)] 23#[derive(Debug)]
24pub struct RenameError(pub(crate) String); 24pub struct RenameError(String);
25 25
26impl fmt::Display for RenameError { 26impl fmt::Display for RenameError {
27 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 27 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -47,16 +47,15 @@ pub(crate) fn prepare_rename(
47 let sema = Semantics::new(db); 47 let sema = Semantics::new(db);
48 let source_file = sema.parse(position.file_id); 48 let source_file = sema.parse(position.file_id);
49 let syntax = source_file.syntax(); 49 let syntax = source_file.syntax();
50 let range = match &sema 50 let name_like = sema
51 .find_node_at_offset_with_descend(&syntax, position.offset) 51 .find_node_at_offset_with_descend(&syntax, position.offset)
52 .ok_or_else(|| format_err!("No references found at position"))? 52 .ok_or_else(|| format_err!("No references found at position"))?;
53 { 53 let node = match &name_like {
54 ast::NameLike::Name(it) => it.syntax(), 54 ast::NameLike::Name(it) => it.syntax(),
55 ast::NameLike::NameRef(it) => it.syntax(), 55 ast::NameLike::NameRef(it) => it.syntax(),
56 ast::NameLike::Lifetime(it) => it.syntax(), 56 ast::NameLike::Lifetime(it) => it.syntax(),
57 } 57 };
58 .text_range(); 58 Ok(RangeInfo::new(sema.original_range(node).range, ()))
59 Ok(RangeInfo::new(range, ()))
60} 59}
61 60
62// Feature: Rename 61// Feature: Rename
@@ -546,6 +545,8 @@ mod tests {
546 545
547 use crate::{fixture, FileId}; 546 use crate::{fixture, FileId};
548 547
548 use super::{RangeInfo, RenameError};
549
549 fn check(new_name: &str, ra_fixture_before: &str, ra_fixture_after: &str) { 550 fn check(new_name: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
550 let ra_fixture_after = &trim_indent(ra_fixture_after); 551 let ra_fixture_after = &trim_indent(ra_fixture_after);
551 let (analysis, position) = fixture::position(ra_fixture_before); 552 let (analysis, position) = fixture::position(ra_fixture_before);
@@ -591,6 +592,45 @@ mod tests {
591 expect.assert_debug_eq(&source_change) 592 expect.assert_debug_eq(&source_change)
592 } 593 }
593 594
595 fn check_prepare(ra_fixture: &str, expect: Expect) {
596 let (analysis, position) = fixture::position(ra_fixture);
597 let result = analysis
598 .prepare_rename(position)
599 .unwrap_or_else(|err| panic!("PrepareRename was cancelled: {}", err));
600 match result {
601 Ok(RangeInfo { range, info: () }) => {
602 let source = analysis.file_text(position.file_id).unwrap();
603 expect.assert_eq(&format!("{:?}: {}", range, &source[range]))
604 }
605 Err(RenameError(err)) => expect.assert_eq(&err),
606 };
607 }
608
609 #[test]
610 fn test_prepare_rename_namelikes() {
611 check_prepare(r"fn name$0<'lifetime>() {}", expect![[r#"3..7: name"#]]);
612 check_prepare(r"fn name<'lifetime$0>() {}", expect![[r#"8..17: 'lifetime"#]]);
613 check_prepare(r"fn name<'lifetime>() { name$0(); }", expect![[r#"23..27: name"#]]);
614 }
615
616 #[test]
617 fn test_prepare_rename_in_macro() {
618 check_prepare(
619 r"macro_rules! foo {
620 ($ident:ident) => {
621 pub struct $ident;
622 }
623}
624foo!(Foo$0);",
625 expect![[r#"83..86: Foo"#]],
626 );
627 }
628
629 #[test]
630 fn test_prepare_rename_keyword() {
631 check_prepare(r"struct$0 Foo;", expect![[r#"No references found at position"#]]);
632 }
633
594 #[test] 634 #[test]
595 fn test_rename_to_underscore() { 635 fn test_rename_to_underscore() {
596 check("_", r#"fn main() { let i$0 = 1; }"#, r#"fn main() { let _ = 1; }"#); 636 check("_", r#"fn main() { let i$0 = 1; }"#, r#"fn main() { let _ = 1; }"#);
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs
index 280565563..27d35de5b 100644
--- a/crates/ide/src/runnables.rs
+++ b/crates/ide/src/runnables.rs
@@ -1,10 +1,17 @@
1use std::fmt; 1use std::fmt;
2 2
3use ast::NameOwner;
3use cfg::CfgExpr; 4use cfg::CfgExpr;
4use hir::{AsAssocItem, HasAttrs, HasSource, Semantics}; 5use hir::{AsAssocItem, HasAttrs, HasSource, HirDisplay, Semantics};
5use ide_assists::utils::test_related_attribute; 6use ide_assists::utils::test_related_attribute;
6use ide_db::{defs::Definition, RootDatabase, SymbolKind}; 7use ide_db::{
8 base_db::{FilePosition, FileRange},
9 defs::Definition,
10 search::SearchScope,
11 RootDatabase, SymbolKind,
12};
7use itertools::Itertools; 13use itertools::Itertools;
14use rustc_hash::FxHashSet;
8use syntax::{ 15use syntax::{
9 ast::{self, AstNode, AttrsOwner}, 16 ast::{self, AstNode, AttrsOwner},
10 match_ast, SyntaxNode, 17 match_ast, SyntaxNode,
@@ -12,17 +19,17 @@ use syntax::{
12 19
13use crate::{ 20use crate::{
14 display::{ToNav, TryToNav}, 21 display::{ToNav, TryToNav},
15 FileId, NavigationTarget, 22 references, FileId, NavigationTarget,
16}; 23};
17 24
18#[derive(Debug, Clone)] 25#[derive(Debug, Clone, Hash, PartialEq, Eq)]
19pub struct Runnable { 26pub struct Runnable {
20 pub nav: NavigationTarget, 27 pub nav: NavigationTarget,
21 pub kind: RunnableKind, 28 pub kind: RunnableKind,
22 pub cfg: Option<CfgExpr>, 29 pub cfg: Option<CfgExpr>,
23} 30}
24 31
25#[derive(Debug, Clone)] 32#[derive(Debug, Clone, Hash, PartialEq, Eq)]
26pub enum TestId { 33pub enum TestId {
27 Name(String), 34 Name(String),
28 Path(String), 35 Path(String),
@@ -37,7 +44,7 @@ impl fmt::Display for TestId {
37 } 44 }
38} 45}
39 46
40#[derive(Debug, Clone)] 47#[derive(Debug, Clone, Hash, PartialEq, Eq)]
41pub enum RunnableKind { 48pub enum RunnableKind {
42 Test { test_id: TestId, attr: TestAttr }, 49 Test { test_id: TestId, attr: TestAttr },
43 TestMod { path: String }, 50 TestMod { path: String },
@@ -105,6 +112,105 @@ pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
105 res 112 res
106} 113}
107 114
115// Feature: Related Tests
116//
117// Provides a sneak peek of all tests where the current item is used.
118//
119// The simplest way to use this feature is via the context menu:
120// - Right-click on the selected item. The context menu opens.
121// - Select **Peek related tests**
122//
123// |===
124// | Editor | Action Name
125//
126// | VS Code | **Rust Analyzer: Peek related tests**
127// |===
128pub(crate) fn related_tests(
129 db: &RootDatabase,
130 position: FilePosition,
131 search_scope: Option<SearchScope>,
132) -> Vec<Runnable> {
133 let sema = Semantics::new(db);
134 let mut res: FxHashSet<Runnable> = FxHashSet::default();
135
136 find_related_tests(&sema, position, search_scope, &mut res);
137
138 res.into_iter().collect_vec()
139}
140
141fn find_related_tests(
142 sema: &Semantics<RootDatabase>,
143 position: FilePosition,
144 search_scope: Option<SearchScope>,
145 tests: &mut FxHashSet<Runnable>,
146) {
147 if let Some(refs) = references::find_all_refs(&sema, position, search_scope) {
148 for (file_id, refs) in refs.references {
149 let file = sema.parse(file_id);
150 let file = file.syntax();
151 let functions = refs.iter().filter_map(|(range, _)| {
152 let token = file.token_at_offset(range.start()).next()?;
153 let token = sema.descend_into_macros(token);
154 let syntax = token.parent();
155 syntax.ancestors().find_map(ast::Fn::cast)
156 });
157
158 for fn_def in functions {
159 if let Some(runnable) = as_test_runnable(&sema, &fn_def) {
160 // direct test
161 tests.insert(runnable);
162 } else if let Some(module) = parent_test_module(&sema, &fn_def) {
163 // indirect test
164 find_related_tests_in_module(sema, &fn_def, &module, tests);
165 }
166 }
167 }
168 }
169}
170
171fn find_related_tests_in_module(
172 sema: &Semantics<RootDatabase>,
173 fn_def: &ast::Fn,
174 parent_module: &hir::Module,
175 tests: &mut FxHashSet<Runnable>,
176) {
177 if let Some(fn_name) = fn_def.name() {
178 let mod_source = parent_module.definition_source(sema.db);
179 let range = match mod_source.value {
180 hir::ModuleSource::Module(m) => m.syntax().text_range(),
181 hir::ModuleSource::BlockExpr(b) => b.syntax().text_range(),
182 hir::ModuleSource::SourceFile(f) => f.syntax().text_range(),
183 };
184
185 let file_id = mod_source.file_id.original_file(sema.db);
186 let mod_scope = SearchScope::file_range(FileRange { file_id, range });
187 let fn_pos = FilePosition { file_id, offset: fn_name.syntax().text_range().start() };
188 find_related_tests(sema, fn_pos, Some(mod_scope), tests)
189 }
190}
191
192fn as_test_runnable(sema: &Semantics<RootDatabase>, fn_def: &ast::Fn) -> Option<Runnable> {
193 if test_related_attribute(&fn_def).is_some() {
194 let function = sema.to_def(fn_def)?;
195 runnable_fn(sema, function)
196 } else {
197 None
198 }
199}
200
201fn parent_test_module(sema: &Semantics<RootDatabase>, fn_def: &ast::Fn) -> Option<hir::Module> {
202 fn_def.syntax().ancestors().find_map(|node| {
203 let module = ast::Module::cast(node)?;
204 let module = sema.to_def(&module)?;
205
206 if has_test_function_or_multiple_test_submodules(sema, &module) {
207 Some(module)
208 } else {
209 None
210 }
211 })
212}
213
108fn runnables_mod(sema: &Semantics<RootDatabase>, acc: &mut Vec<Runnable>, module: hir::Module) { 214fn runnables_mod(sema: &Semantics<RootDatabase>, acc: &mut Vec<Runnable>, module: hir::Module) {
109 acc.extend(module.declarations(sema.db).into_iter().filter_map(|def| { 215 acc.extend(module.declarations(sema.db).into_iter().filter_map(|def| {
110 let runnable = match def { 216 let runnable = match def {
@@ -234,11 +340,21 @@ fn module_def_doctest(sema: &Semantics<RootDatabase>, def: hir::ModuleDef) -> Op
234 // FIXME: this also looks very wrong 340 // FIXME: this also looks very wrong
235 if let Some(assoc_def) = assoc_def { 341 if let Some(assoc_def) = assoc_def {
236 if let hir::AssocItemContainer::Impl(imp) = assoc_def.container(sema.db) { 342 if let hir::AssocItemContainer::Impl(imp) = assoc_def.container(sema.db) {
237 if let Some(adt) = imp.target_ty(sema.db).as_adt() { 343 let ty = imp.target_ty(sema.db);
238 let name = adt.name(sema.db).to_string(); 344 if let Some(adt) = ty.as_adt() {
345 let name = adt.name(sema.db);
239 let idx = path.rfind(':').map_or(0, |idx| idx + 1); 346 let idx = path.rfind(':').map_or(0, |idx| idx + 1);
240 let (prefix, suffix) = path.split_at(idx); 347 let (prefix, suffix) = path.split_at(idx);
241 return format!("{}{}::{}", prefix, name, suffix); 348 let mut ty_params = ty.type_parameters().peekable();
349 let params = if ty_params.peek().is_some() {
350 format!(
351 "<{}>",
352 ty_params.format_with(", ", |ty, cb| cb(&ty.display(sema.db)))
353 )
354 } else {
355 String::new()
356 };
357 return format!("{}{}{}::{}", prefix, name, params, suffix);
242 } 358 }
243 } 359 }
244 } 360 }
@@ -256,7 +372,7 @@ fn module_def_doctest(sema: &Semantics<RootDatabase>, def: hir::ModuleDef) -> Op
256 Some(res) 372 Some(res)
257} 373}
258 374
259#[derive(Debug, Copy, Clone)] 375#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
260pub struct TestAttr { 376pub struct TestAttr {
261 pub ignore: bool, 377 pub ignore: bool,
262} 378}
@@ -349,6 +465,12 @@ mod tests {
349 ); 465 );
350 } 466 }
351 467
468 fn check_tests(ra_fixture: &str, expect: Expect) {
469 let (analysis, position) = fixture::position(ra_fixture);
470 let tests = analysis.related_tests(position, None).unwrap();
471 expect.assert_debug_eq(&tests);
472 }
473
352 #[test] 474 #[test]
353 fn test_runnables() { 475 fn test_runnables() {
354 check( 476 check(
@@ -1074,4 +1196,261 @@ mod tests {
1074 "#]], 1196 "#]],
1075 ); 1197 );
1076 } 1198 }
1199
1200 #[test]
1201 fn find_no_tests() {
1202 check_tests(
1203 r#"
1204//- /lib.rs
1205fn foo$0() { };
1206"#,
1207 expect![[r#"
1208 []
1209 "#]],
1210 );
1211 }
1212
1213 #[test]
1214 fn find_direct_fn_test() {
1215 check_tests(
1216 r#"
1217//- /lib.rs
1218fn foo$0() { };
1219
1220mod tests {
1221 #[test]
1222 fn foo_test() {
1223 super::foo()
1224 }
1225}
1226"#,
1227 expect![[r#"
1228 [
1229 Runnable {
1230 nav: NavigationTarget {
1231 file_id: FileId(
1232 0,
1233 ),
1234 full_range: 31..85,
1235 focus_range: 46..54,
1236 name: "foo_test",
1237 kind: Function,
1238 },
1239 kind: Test {
1240 test_id: Path(
1241 "tests::foo_test",
1242 ),
1243 attr: TestAttr {
1244 ignore: false,
1245 },
1246 },
1247 cfg: None,
1248 },
1249 ]
1250 "#]],
1251 );
1252 }
1253
1254 #[test]
1255 fn find_direct_struct_test() {
1256 check_tests(
1257 r#"
1258//- /lib.rs
1259struct Fo$0o;
1260fn foo(arg: &Foo) { };
1261
1262mod tests {
1263 use super::*;
1264
1265 #[test]
1266 fn foo_test() {
1267 foo(Foo);
1268 }
1269}
1270"#,
1271 expect![[r#"
1272 [
1273 Runnable {
1274 nav: NavigationTarget {
1275 file_id: FileId(
1276 0,
1277 ),
1278 full_range: 71..122,
1279 focus_range: 86..94,
1280 name: "foo_test",
1281 kind: Function,
1282 },
1283 kind: Test {
1284 test_id: Path(
1285 "tests::foo_test",
1286 ),
1287 attr: TestAttr {
1288 ignore: false,
1289 },
1290 },
1291 cfg: None,
1292 },
1293 ]
1294 "#]],
1295 );
1296 }
1297
1298 #[test]
1299 fn find_indirect_fn_test() {
1300 check_tests(
1301 r#"
1302//- /lib.rs
1303fn foo$0() { };
1304
1305mod tests {
1306 use super::foo;
1307
1308 fn check1() {
1309 check2()
1310 }
1311
1312 fn check2() {
1313 foo()
1314 }
1315
1316 #[test]
1317 fn foo_test() {
1318 check1()
1319 }
1320}
1321"#,
1322 expect![[r#"
1323 [
1324 Runnable {
1325 nav: NavigationTarget {
1326 file_id: FileId(
1327 0,
1328 ),
1329 full_range: 133..183,
1330 focus_range: 148..156,
1331 name: "foo_test",
1332 kind: Function,
1333 },
1334 kind: Test {
1335 test_id: Path(
1336 "tests::foo_test",
1337 ),
1338 attr: TestAttr {
1339 ignore: false,
1340 },
1341 },
1342 cfg: None,
1343 },
1344 ]
1345 "#]],
1346 );
1347 }
1348
1349 #[test]
1350 fn tests_are_unique() {
1351 check_tests(
1352 r#"
1353//- /lib.rs
1354fn foo$0() { };
1355
1356mod tests {
1357 use super::foo;
1358
1359 #[test]
1360 fn foo_test() {
1361 foo();
1362 foo();
1363 }
1364
1365 #[test]
1366 fn foo2_test() {
1367 foo();
1368 foo();
1369 }
1370
1371}
1372"#,
1373 expect![[r#"
1374 [
1375 Runnable {
1376 nav: NavigationTarget {
1377 file_id: FileId(
1378 0,
1379 ),
1380 full_range: 52..115,
1381 focus_range: 67..75,
1382 name: "foo_test",
1383 kind: Function,
1384 },
1385 kind: Test {
1386 test_id: Path(
1387 "tests::foo_test",
1388 ),
1389 attr: TestAttr {
1390 ignore: false,
1391 },
1392 },
1393 cfg: None,
1394 },
1395 Runnable {
1396 nav: NavigationTarget {
1397 file_id: FileId(
1398 0,
1399 ),
1400 full_range: 121..185,
1401 focus_range: 136..145,
1402 name: "foo2_test",
1403 kind: Function,
1404 },
1405 kind: Test {
1406 test_id: Path(
1407 "tests::foo2_test",
1408 ),
1409 attr: TestAttr {
1410 ignore: false,
1411 },
1412 },
1413 cfg: None,
1414 },
1415 ]
1416 "#]],
1417 );
1418 }
1419
1420 #[test]
1421 fn doc_test_type_params() {
1422 check(
1423 r#"
1424//- /lib.rs
1425$0
1426struct Foo<T, U>;
1427
1428impl<T, U> Foo<T, U> {
1429 /// ```rust
1430 /// ````
1431 fn t() {}
1432}
1433"#,
1434 &[&DOCTEST],
1435 expect![[r#"
1436 [
1437 Runnable {
1438 nav: NavigationTarget {
1439 file_id: FileId(
1440 0,
1441 ),
1442 full_range: 47..85,
1443 name: "t",
1444 },
1445 kind: DocTest {
1446 test_id: Path(
1447 "Foo<T, U>::t",
1448 ),
1449 },
1450 cfg: None,
1451 },
1452 ]
1453 "#]],
1454 );
1455 }
1077} 1456}
diff --git a/crates/ide_assists/src/handlers/add_turbo_fish.rs b/crates/ide_assists/src/handlers/add_turbo_fish.rs
index 3b6efbab4..ee879c151 100644
--- a/crates/ide_assists/src/handlers/add_turbo_fish.rs
+++ b/crates/ide_assists/src/handlers/add_turbo_fish.rs
@@ -56,13 +56,20 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<(
56 if let Some(let_stmt) = ctx.find_node_at_offset::<ast::LetStmt>() { 56 if let Some(let_stmt) = ctx.find_node_at_offset::<ast::LetStmt>() {
57 if let_stmt.colon_token().is_none() { 57 if let_stmt.colon_token().is_none() {
58 let type_pos = let_stmt.pat()?.syntax().last_token()?.text_range().end(); 58 let type_pos = let_stmt.pat()?.syntax().last_token()?.text_range().end();
59 let semi_pos = let_stmt.syntax().last_token()?.text_range().end();
60
59 acc.add( 61 acc.add(
60 AssistId("add_type_ascription", AssistKind::RefactorRewrite), 62 AssistId("add_type_ascription", AssistKind::RefactorRewrite),
61 "Add `: _` before assignment operator", 63 "Add `: _` before assignment operator",
62 ident.text_range(), 64 ident.text_range(),
63 |builder| match ctx.config.snippet_cap { 65 |builder| {
64 Some(cap) => builder.insert_snippet(cap, type_pos, ": ${0:_}"), 66 if let_stmt.semicolon_token().is_none() {
65 None => builder.insert(type_pos, ": _"), 67 builder.insert(semi_pos, ";");
68 }
69 match ctx.config.snippet_cap {
70 Some(cap) => builder.insert_snippet(cap, type_pos, ": ${0:_}"),
71 None => builder.insert(type_pos, ": _"),
72 }
66 }, 73 },
67 )? 74 )?
68 } else { 75 } else {
@@ -265,4 +272,24 @@ fn main() {
265"#, 272"#,
266 ); 273 );
267 } 274 }
275
276 #[test]
277 fn add_type_ascription_append_semicolon() {
278 check_assist_by_label(
279 add_turbo_fish,
280 r#"
281fn make<T>() -> T {}
282fn main() {
283 let x = make$0()
284}
285"#,
286 r#"
287fn make<T>() -> T {}
288fn main() {
289 let x: ${0:_} = make();
290}
291"#,
292 "Add `: _` before assignment operator",
293 );
294 }
268} 295}
diff --git a/crates/ide_assists/src/handlers/apply_demorgan.rs b/crates/ide_assists/src/handlers/apply_demorgan.rs
index a1c339603..5c936a510 100644
--- a/crates/ide_assists/src/handlers/apply_demorgan.rs
+++ b/crates/ide_assists/src/handlers/apply_demorgan.rs
@@ -1,3 +1,5 @@
1use std::collections::VecDeque;
2
1use syntax::ast::{self, AstNode}; 3use syntax::ast::{self, AstNode};
2 4
3use crate::{utils::invert_boolean_expression, AssistContext, AssistId, AssistKind, Assists}; 5use crate::{utils::invert_boolean_expression, AssistContext, AssistId, AssistKind, Assists};
@@ -30,19 +32,52 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext) -> Option<(
30 return None; 32 return None;
31 } 33 }
32 34
33 let lhs = expr.lhs()?; 35 let mut expr = expr;
34 let lhs_range = lhs.syntax().text_range(); 36
35 let not_lhs = invert_boolean_expression(&ctx.sema, lhs); 37 // Walk up the tree while we have the same binary operator
38 while let Some(parent_expr) = expr.syntax().parent().and_then(ast::BinExpr::cast) {
39 if let Some(parent_op) = expr.op_kind() {
40 if parent_op == op {
41 expr = parent_expr
42 }
43 }
44 }
45
46 let mut expr_stack = vec![expr.clone()];
47 let mut terms = Vec::new();
48 let mut op_ranges = Vec::new();
49
50 // Find all the children with the same binary operator
51 while let Some(expr) = expr_stack.pop() {
52 let mut traverse_bin_expr_arm = |expr| {
53 if let ast::Expr::BinExpr(bin_expr) = expr {
54 if let Some(expr_op) = bin_expr.op_kind() {
55 if expr_op == op {
56 expr_stack.push(bin_expr);
57 } else {
58 terms.push(ast::Expr::BinExpr(bin_expr));
59 }
60 } else {
61 terms.push(ast::Expr::BinExpr(bin_expr));
62 }
63 } else {
64 terms.push(expr);
65 }
66 };
36 67
37 let rhs = expr.rhs()?; 68 op_ranges.extend(expr.op_token().map(|t| t.text_range()));
38 let rhs_range = rhs.syntax().text_range(); 69 traverse_bin_expr_arm(expr.lhs()?);
39 let not_rhs = invert_boolean_expression(&ctx.sema, rhs); 70 traverse_bin_expr_arm(expr.rhs()?);
71 }
40 72
41 acc.add( 73 acc.add(
42 AssistId("apply_demorgan", AssistKind::RefactorRewrite), 74 AssistId("apply_demorgan", AssistKind::RefactorRewrite),
43 "Apply De Morgan's law", 75 "Apply De Morgan's law",
44 op_range, 76 op_range,
45 |edit| { 77 |edit| {
78 terms.sort_by_key(|t| t.syntax().text_range().start());
79 let mut terms = VecDeque::from(terms);
80
46 let paren_expr = expr.syntax().parent().and_then(|parent| ast::ParenExpr::cast(parent)); 81 let paren_expr = expr.syntax().parent().and_then(|parent| ast::ParenExpr::cast(parent));
47 82
48 let neg_expr = paren_expr 83 let neg_expr = paren_expr
@@ -57,11 +92,18 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext) -> Option<(
57 } 92 }
58 }); 93 });
59 94
60 edit.replace(op_range, opposite_op); 95 for op_range in op_ranges {
96 edit.replace(op_range, opposite_op);
97 }
61 98
62 if let Some(paren_expr) = paren_expr { 99 if let Some(paren_expr) = paren_expr {
63 edit.replace(lhs_range, not_lhs.syntax().text()); 100 for term in terms {
64 edit.replace(rhs_range, not_rhs.syntax().text()); 101 let range = term.syntax().text_range();
102 let not_term = invert_boolean_expression(&ctx.sema, term);
103
104 edit.replace(range, not_term.syntax().text());
105 }
106
65 if let Some(neg_expr) = neg_expr { 107 if let Some(neg_expr) = neg_expr {
66 cov_mark::hit!(demorgan_double_negation); 108 cov_mark::hit!(demorgan_double_negation);
67 edit.replace(neg_expr.op_token().unwrap().text_range(), ""); 109 edit.replace(neg_expr.op_token().unwrap().text_range(), "");
@@ -70,8 +112,25 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext) -> Option<(
70 edit.replace(paren_expr.l_paren_token().unwrap().text_range(), "!("); 112 edit.replace(paren_expr.l_paren_token().unwrap().text_range(), "!(");
71 } 113 }
72 } else { 114 } else {
73 edit.replace(lhs_range, format!("!({}", not_lhs.syntax().text())); 115 if let Some(lhs) = terms.pop_front() {
74 edit.replace(rhs_range, format!("{})", not_rhs.syntax().text())); 116 let lhs_range = lhs.syntax().text_range();
117 let not_lhs = invert_boolean_expression(&ctx.sema, lhs);
118
119 edit.replace(lhs_range, format!("!({}", not_lhs.syntax().text()));
120 }
121
122 if let Some(rhs) = terms.pop_back() {
123 let rhs_range = rhs.syntax().text_range();
124 let not_rhs = invert_boolean_expression(&ctx.sema, rhs);
125
126 edit.replace(rhs_range, format!("{})", not_rhs.syntax().text()));
127 }
128
129 for term in terms {
130 let term_range = term.syntax().text_range();
131 let not_term = invert_boolean_expression(&ctx.sema, term);
132 edit.replace(term_range, not_term.syntax().text());
133 }
75 } 134 }
76 }, 135 },
77 ) 136 )
@@ -180,6 +239,12 @@ fn f() {
180 } 239 }
181 240
182 #[test] 241 #[test]
242 fn demorgan_multiple_terms() {
243 check_assist(apply_demorgan, "fn f() { x ||$0 y || z }", "fn f() { !(!x && !y && !z) }");
244 check_assist(apply_demorgan, "fn f() { x || y ||$0 z }", "fn f() { !(!x && !y && !z) }");
245 }
246
247 #[test]
183 fn demorgan_doesnt_apply_with_cursor_not_on_op() { 248 fn demorgan_doesnt_apply_with_cursor_not_on_op() {
184 check_assist_not_applicable(apply_demorgan, "fn f() { $0 !x || !x }") 249 check_assist_not_applicable(apply_demorgan, "fn f() { $0 !x || !x }")
185 } 250 }
diff --git a/crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs b/crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs
new file mode 100644
index 000000000..4e75a7b14
--- /dev/null
+++ b/crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs
@@ -0,0 +1,248 @@
1use ide_db::helpers::FamousDefs;
2use syntax::{
3 ast::{self, edit::AstNodeEdit, make, ArgListOwner},
4 AstNode,
5};
6
7use crate::{AssistContext, AssistId, AssistKind, Assists};
8
9// Assist: convert_iter_for_each_to_for
10//
11// Converts an Iterator::for_each function into a for loop.
12//
13// ```
14// # //- /lib.rs crate:core
15// # pub mod iter { pub mod traits { pub mod iterator { pub trait Iterator {} } } }
16// # pub struct SomeIter;
17// # impl self::iter::traits::iterator::Iterator for SomeIter {}
18// # //- /lib.rs crate:main deps:core
19// # use core::SomeIter;
20// fn main() {
21// let iter = SomeIter;
22// iter.for_each$0(|(x, y)| {
23// println!("x: {}, y: {}", x, y);
24// });
25// }
26// ```
27// ->
28// ```
29// # use core::SomeIter;
30// fn main() {
31// let iter = SomeIter;
32// for (x, y) in iter {
33// println!("x: {}, y: {}", x, y);
34// }
35// }
36// ```
37
38pub(crate) fn convert_iter_for_each_to_for(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
39 let method = ctx.find_node_at_offset::<ast::MethodCallExpr>()?;
40
41 let closure = match method.arg_list()?.args().next()? {
42 ast::Expr::ClosureExpr(expr) => expr,
43 _ => return None,
44 };
45
46 let (method, receiver) = validate_method_call_expr(ctx, method)?;
47
48 let param_list = closure.param_list()?;
49 let param = param_list.params().next()?.pat()?;
50 let body = closure.body()?;
51
52 let stmt = method.syntax().parent().and_then(ast::ExprStmt::cast);
53 let syntax = stmt.as_ref().map_or(method.syntax(), |stmt| stmt.syntax());
54
55 acc.add(
56 AssistId("convert_iter_for_each_to_for", AssistKind::RefactorRewrite),
57 "Replace this `Iterator::for_each` with a for loop",
58 syntax.text_range(),
59 |builder| {
60 let indent = stmt.as_ref().map_or(method.indent_level(), |stmt| stmt.indent_level());
61
62 let block = match body {
63 ast::Expr::BlockExpr(block) => block,
64 _ => make::block_expr(Vec::new(), Some(body)),
65 }
66 .reset_indent()
67 .indent(indent);
68
69 let expr_for_loop = make::expr_for_loop(param, receiver, block);
70 builder.replace(syntax.text_range(), expr_for_loop.syntax().text())
71 },
72 )
73}
74
75fn validate_method_call_expr(
76 ctx: &AssistContext,
77 expr: ast::MethodCallExpr,
78) -> Option<(ast::Expr, ast::Expr)> {
79 let name_ref = expr.name_ref()?;
80 if name_ref.syntax().text_range().intersect(ctx.frange.range).is_none()
81 || name_ref.text() != "for_each"
82 {
83 return None;
84 }
85
86 let sema = &ctx.sema;
87
88 let receiver = expr.receiver()?;
89 let expr = ast::Expr::MethodCallExpr(expr);
90
91 let it_type = sema.type_of_expr(&receiver)?;
92 let module = sema.scope(receiver.syntax()).module()?;
93 let krate = module.krate();
94
95 let iter_trait = FamousDefs(sema, Some(krate)).core_iter_Iterator()?;
96 it_type.impls_trait(sema.db, iter_trait, &[]).then(|| (expr, receiver))
97}
98
99#[cfg(test)]
100mod tests {
101 use crate::tests::{self, check_assist};
102
103 use super::*;
104
105 const EMPTY_ITER_FIXTURE: &'static str = r"
106//- /lib.rs deps:core crate:empty_iter
107pub struct EmptyIter;
108impl Iterator for EmptyIter {
109 type Item = usize;
110 fn next(&mut self) -> Option<Self::Item> { None }
111}
112pub struct Empty;
113impl Empty {
114 pub fn iter(&self) -> EmptyIter { EmptyIter }
115}
116";
117
118 fn check_assist_with_fixtures(before: &str, after: &str) {
119 let before = &format!(
120 "//- /main.rs crate:main deps:core,empty_iter{}{}{}",
121 before,
122 EMPTY_ITER_FIXTURE,
123 FamousDefs::FIXTURE,
124 );
125 check_assist(convert_iter_for_each_to_for, before, after);
126 }
127
128 fn check_assist_not_applicable(before: &str) {
129 let before = &format!(
130 "//- /main.rs crate:main deps:core,empty_iter{}{}{}",
131 before,
132 EMPTY_ITER_FIXTURE,
133 FamousDefs::FIXTURE,
134 );
135 tests::check_assist_not_applicable(convert_iter_for_each_to_for, before);
136 }
137
138 #[test]
139 fn test_for_each_in_method_stmt() {
140 check_assist_with_fixtures(
141 r#"
142use empty_iter::*;
143fn main() {
144 let x = Empty;
145 x.iter().$0for_each(|(x, y)| {
146 println!("x: {}, y: {}", x, y);
147 });
148}"#,
149 r#"
150use empty_iter::*;
151fn main() {
152 let x = Empty;
153 for (x, y) in x.iter() {
154 println!("x: {}, y: {}", x, y);
155 }
156}
157"#,
158 )
159 }
160
161 #[test]
162 fn test_for_each_in_method() {
163 check_assist_with_fixtures(
164 r#"
165use empty_iter::*;
166fn main() {
167 let x = Empty;
168 x.iter().$0for_each(|(x, y)| {
169 println!("x: {}, y: {}", x, y);
170 })
171}"#,
172 r#"
173use empty_iter::*;
174fn main() {
175 let x = Empty;
176 for (x, y) in x.iter() {
177 println!("x: {}, y: {}", x, y);
178 }
179}
180"#,
181 )
182 }
183
184 #[test]
185 fn test_for_each_in_iter_stmt() {
186 check_assist_with_fixtures(
187 r#"
188use empty_iter::*;
189fn main() {
190 let x = Empty.iter();
191 x.$0for_each(|(x, y)| {
192 println!("x: {}, y: {}", x, y);
193 });
194}"#,
195 r#"
196use empty_iter::*;
197fn main() {
198 let x = Empty.iter();
199 for (x, y) in x {
200 println!("x: {}, y: {}", x, y);
201 }
202}
203"#,
204 )
205 }
206
207 #[test]
208 fn test_for_each_without_braces_stmt() {
209 check_assist_with_fixtures(
210 r#"
211use empty_iter::*;
212fn main() {
213 let x = Empty;
214 x.iter().$0for_each(|(x, y)| println!("x: {}, y: {}", x, y));
215}"#,
216 r#"
217use empty_iter::*;
218fn main() {
219 let x = Empty;
220 for (x, y) in x.iter() {
221 println!("x: {}, y: {}", x, y)
222 }
223}
224"#,
225 )
226 }
227
228 #[test]
229 fn test_for_each_not_applicable() {
230 check_assist_not_applicable(
231 r#"
232fn main() {
233 ().$0for_each(|x| println!("{}", x));
234}"#,
235 )
236 }
237
238 #[test]
239 fn test_for_each_not_applicable_invalid_cursor_pos() {
240 check_assist_not_applicable(
241 r#"
242use empty_iter::*;
243fn main() {
244 Empty.iter().for_each(|(x, y)| $0println!("x: {}, y: {}", x, y));
245}"#,
246 )
247 }
248}
diff --git a/crates/ide_assists/src/lib.rs b/crates/ide_assists/src/lib.rs
index ea62d5f5d..f1aab74d4 100644
--- a/crates/ide_assists/src/lib.rs
+++ b/crates/ide_assists/src/lib.rs
@@ -116,6 +116,7 @@ mod handlers {
116 mod change_visibility; 116 mod change_visibility;
117 mod convert_integer_literal; 117 mod convert_integer_literal;
118 mod convert_comment_block; 118 mod convert_comment_block;
119 mod convert_iter_for_each_to_for;
119 mod early_return; 120 mod early_return;
120 mod expand_glob_import; 121 mod expand_glob_import;
121 mod extract_function; 122 mod extract_function;
@@ -181,6 +182,7 @@ mod handlers {
181 change_visibility::change_visibility, 182 change_visibility::change_visibility,
182 convert_integer_literal::convert_integer_literal, 183 convert_integer_literal::convert_integer_literal,
183 convert_comment_block::convert_comment_block, 184 convert_comment_block::convert_comment_block,
185 convert_iter_for_each_to_for::convert_iter_for_each_to_for,
184 early_return::convert_to_guarded_return, 186 early_return::convert_to_guarded_return,
185 expand_glob_import::expand_glob_import, 187 expand_glob_import::expand_glob_import,
186 extract_struct_from_enum_variant::extract_struct_from_enum_variant, 188 extract_struct_from_enum_variant::extract_struct_from_enum_variant,
diff --git a/crates/ide_assists/src/tests/generated.rs b/crates/ide_assists/src/tests/generated.rs
index 304b5798f..3f77edd8d 100644
--- a/crates/ide_assists/src/tests/generated.rs
+++ b/crates/ide_assists/src/tests/generated.rs
@@ -206,6 +206,36 @@ const _: i32 = 0b1010;
206} 206}
207 207
208#[test] 208#[test]
209fn doctest_convert_iter_for_each_to_for() {
210 check_doc_test(
211 "convert_iter_for_each_to_for",
212 r#####"
213//- /lib.rs crate:core
214pub mod iter { pub mod traits { pub mod iterator { pub trait Iterator {} } } }
215pub struct SomeIter;
216impl self::iter::traits::iterator::Iterator for SomeIter {}
217//- /lib.rs crate:main deps:core
218use core::SomeIter;
219fn main() {
220 let iter = SomeIter;
221 iter.for_each$0(|(x, y)| {
222 println!("x: {}, y: {}", x, y);
223 });
224}
225"#####,
226 r#####"
227use core::SomeIter;
228fn main() {
229 let iter = SomeIter;
230 for (x, y) in iter {
231 println!("x: {}, y: {}", x, y);
232 }
233}
234"#####,
235 )
236}
237
238#[test]
209fn doctest_convert_to_guarded_return() { 239fn doctest_convert_to_guarded_return() {
210 check_doc_test( 240 check_doc_test(
211 "convert_to_guarded_return", 241 "convert_to_guarded_return",
diff --git a/crates/ide_completion/src/completions/attribute.rs b/crates/ide_completion/src/completions/attribute.rs
index cb05e85fc..e846678b4 100644
--- a/crates/ide_completion/src/completions/attribute.rs
+++ b/crates/ide_completion/src/completions/attribute.rs
@@ -45,15 +45,15 @@ fn complete_attribute_start(acc: &mut Completions, ctx: &CompletionContext, attr
45 CompletionKind::Attribute, 45 CompletionKind::Attribute,
46 ctx.source_range(), 46 ctx.source_range(),
47 attr_completion.label, 47 attr_completion.label,
48 ) 48 );
49 .kind(CompletionItemKind::Attribute); 49 item.kind(CompletionItemKind::Attribute);
50 50
51 if let Some(lookup) = attr_completion.lookup { 51 if let Some(lookup) = attr_completion.lookup {
52 item = item.lookup_by(lookup); 52 item.lookup_by(lookup);
53 } 53 }
54 54
55 if let Some((snippet, cap)) = attr_completion.snippet.zip(ctx.config.snippet_cap) { 55 if let Some((snippet, cap)) = attr_completion.snippet.zip(ctx.config.snippet_cap) {
56 item = item.insert_snippet(cap, snippet); 56 item.insert_snippet(cap, snippet);
57 } 57 }
58 58
59 if attribute.kind() == ast::AttrKind::Inner || !attr_completion.prefer_inner { 59 if attribute.kind() == ast::AttrKind::Inner || !attr_completion.prefer_inner {
@@ -168,16 +168,20 @@ fn complete_derive(acc: &mut Completions, ctx: &CompletionContext, derive_input:
168 ); 168 );
169 let lookup = components.join(", "); 169 let lookup = components.join(", ");
170 let label = components.iter().rev().join(", "); 170 let label = components.iter().rev().join(", ");
171 CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), label) 171 let mut item =
172 .lookup_by(lookup) 172 CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), label);
173 .kind(CompletionItemKind::Attribute) 173 item.lookup_by(lookup).kind(CompletionItemKind::Attribute);
174 .add_to(acc) 174 item.add_to(acc);
175 } 175 }
176 176
177 for custom_derive_name in get_derive_names_in_scope(ctx).difference(&existing_derives) { 177 for custom_derive_name in get_derive_names_in_scope(ctx).difference(&existing_derives) {
178 CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), custom_derive_name) 178 let mut item = CompletionItem::new(
179 .kind(CompletionItemKind::Attribute) 179 CompletionKind::Attribute,
180 .add_to(acc) 180 ctx.source_range(),
181 custom_derive_name,
182 );
183 item.kind(CompletionItemKind::Attribute);
184 item.add_to(acc);
181 } 185 }
182 } 186 }
183} 187}
@@ -193,14 +197,13 @@ fn complete_lint(
193 .into_iter() 197 .into_iter()
194 .filter(|completion| !existing_lints.contains(completion.label)) 198 .filter(|completion| !existing_lints.contains(completion.label))
195 { 199 {
196 CompletionItem::new( 200 let mut item = CompletionItem::new(
197 CompletionKind::Attribute, 201 CompletionKind::Attribute,
198 ctx.source_range(), 202 ctx.source_range(),
199 lint_completion.label, 203 lint_completion.label,
200 ) 204 );
201 .kind(CompletionItemKind::Attribute) 205 item.kind(CompletionItemKind::Attribute).detail(lint_completion.description);
202 .detail(lint_completion.description) 206 item.add_to(acc)
203 .add_to(acc)
204 } 207 }
205 } 208 }
206} 209}
diff --git a/crates/ide_completion/src/completions/fn_param.rs b/crates/ide_completion/src/completions/fn_param.rs
index 1bcc8727f..0243dce56 100644
--- a/crates/ide_completion/src/completions/fn_param.rs
+++ b/crates/ide_completion/src/completions/fn_param.rs
@@ -54,10 +54,9 @@ pub(crate) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext)
54 } 54 }
55 55
56 params.into_iter().for_each(|(label, lookup)| { 56 params.into_iter().for_each(|(label, lookup)| {
57 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), label) 57 let mut item = CompletionItem::new(CompletionKind::Magic, ctx.source_range(), label);
58 .kind(CompletionItemKind::Binding) 58 item.kind(CompletionItemKind::Binding).lookup_by(lookup);
59 .lookup_by(lookup) 59 item.add_to(acc)
60 .add_to(acc)
61 }); 60 });
62} 61}
63 62
diff --git a/crates/ide_completion/src/completions/keyword.rs b/crates/ide_completion/src/completions/keyword.rs
index 80aa9fb06..b635e0ca3 100644
--- a/crates/ide_completion/src/completions/keyword.rs
+++ b/crates/ide_completion/src/completions/keyword.rs
@@ -12,21 +12,19 @@ pub(crate) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionC
12 12
13 if ctx.use_item_syntax.is_some() { 13 if ctx.use_item_syntax.is_some() {
14 if ctx.path_qual.is_none() { 14 if ctx.path_qual.is_none() {
15 CompletionItem::new(CompletionKind::Keyword, source_range, "crate::") 15 let mut item = CompletionItem::new(CompletionKind::Keyword, source_range, "crate::");
16 .kind(CompletionItemKind::Keyword) 16 item.kind(CompletionItemKind::Keyword).insert_text("crate::");
17 .insert_text("crate::") 17 item.add_to(acc);
18 .add_to(acc);
19 } 18 }
20 CompletionItem::new(CompletionKind::Keyword, source_range, "self") 19 let mut item = CompletionItem::new(CompletionKind::Keyword, source_range, "self");
21 .kind(CompletionItemKind::Keyword) 20 item.kind(CompletionItemKind::Keyword);
22 .add_to(acc); 21 item.add_to(acc);
23 if iter::successors(ctx.path_qual.clone(), |p| p.qualifier()) 22 if iter::successors(ctx.path_qual.clone(), |p| p.qualifier())
24 .all(|p| p.segment().and_then(|s| s.super_token()).is_some()) 23 .all(|p| p.segment().and_then(|s| s.super_token()).is_some())
25 { 24 {
26 CompletionItem::new(CompletionKind::Keyword, source_range, "super::") 25 let mut item = CompletionItem::new(CompletionKind::Keyword, source_range, "super::");
27 .kind(CompletionItemKind::Keyword) 26 item.kind(CompletionItemKind::Keyword).insert_text("super::");
28 .insert_text("super::") 27 item.add_to(acc);
29 .add_to(acc);
30 } 28 }
31 } 29 }
32 30
@@ -34,11 +32,10 @@ pub(crate) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionC
34 if let Some(receiver) = &ctx.dot_receiver { 32 if let Some(receiver) = &ctx.dot_receiver {
35 if let Some(ty) = ctx.sema.type_of_expr(receiver) { 33 if let Some(ty) = ctx.sema.type_of_expr(receiver) {
36 if ty.impls_future(ctx.db) { 34 if ty.impls_future(ctx.db) {
37 CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await") 35 let mut item =
38 .kind(CompletionItemKind::Keyword) 36 CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await");
39 .detail("expr.await") 37 item.kind(CompletionItemKind::Keyword).detail("expr.await").insert_text("await");
40 .insert_text("await") 38 item.add_to(acc);
41 .add_to(acc);
42 } 39 }
43 }; 40 };
44 } 41 }
@@ -165,9 +162,10 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
165} 162}
166 163
167fn add_keyword(ctx: &CompletionContext, acc: &mut Completions, kw: &str, snippet: &str) { 164fn add_keyword(ctx: &CompletionContext, acc: &mut Completions, kw: &str, snippet: &str) {
168 let builder = CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), kw) 165 let mut item = CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), kw);
169 .kind(CompletionItemKind::Keyword); 166 item.kind(CompletionItemKind::Keyword);
170 let builder = match ctx.config.snippet_cap { 167
168 match ctx.config.snippet_cap {
171 Some(cap) => { 169 Some(cap) => {
172 let tmp; 170 let tmp;
173 let snippet = if snippet.ends_with('}') && ctx.incomplete_let { 171 let snippet = if snippet.ends_with('}') && ctx.incomplete_let {
@@ -177,11 +175,13 @@ fn add_keyword(ctx: &CompletionContext, acc: &mut Completions, kw: &str, snippet
177 } else { 175 } else {
178 snippet 176 snippet
179 }; 177 };
180 builder.insert_snippet(cap, snippet) 178 item.insert_snippet(cap, snippet);
179 }
180 None => {
181 item.insert_text(if snippet.contains('$') { kw } else { snippet });
181 } 182 }
182 None => builder.insert_text(if snippet.contains('$') { kw } else { snippet }),
183 }; 183 };
184 acc.add(builder.build()); 184 item.add_to(acc);
185} 185}
186 186
187#[cfg(test)] 187#[cfg(test)]
diff --git a/crates/ide_completion/src/completions/mod_.rs b/crates/ide_completion/src/completions/mod_.rs
index 352fc7c77..4f9415736 100644
--- a/crates/ide_completion/src/completions/mod_.rs
+++ b/crates/ide_completion/src/completions/mod_.rs
@@ -80,9 +80,9 @@ pub(crate) fn complete_mod(acc: &mut Completions, ctx: &CompletionContext) -> Op
80 if mod_under_caret.semicolon_token().is_none() { 80 if mod_under_caret.semicolon_token().is_none() {
81 label.push(';'); 81 label.push(';');
82 } 82 }
83 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), &label) 83 let mut item = CompletionItem::new(CompletionKind::Magic, ctx.source_range(), &label);
84 .kind(SymbolKind::Module) 84 item.kind(SymbolKind::Module);
85 .add_to(acc) 85 item.add_to(acc)
86 }); 86 });
87 87
88 Some(()) 88 Some(())
diff --git a/crates/ide_completion/src/completions/postfix.rs b/crates/ide_completion/src/completions/postfix.rs
index d45ad7944..ac69b720a 100644
--- a/crates/ide_completion/src/completions/postfix.rs
+++ b/crates/ide_completion/src/completions/postfix.rs
@@ -297,10 +297,9 @@ fn postfix_snippet(
297 let delete_range = TextRange::new(receiver_range.start(), ctx.source_range().end()); 297 let delete_range = TextRange::new(receiver_range.start(), ctx.source_range().end());
298 TextEdit::replace(delete_range, snippet.to_string()) 298 TextEdit::replace(delete_range, snippet.to_string())
299 }; 299 };
300 CompletionItem::new(CompletionKind::Postfix, ctx.source_range(), label) 300 let mut item = CompletionItem::new(CompletionKind::Postfix, ctx.source_range(), label);
301 .detail(detail) 301 item.detail(detail).kind(CompletionItemKind::Snippet).snippet_edit(cap, edit);
302 .kind(CompletionItemKind::Snippet) 302 item
303 .snippet_edit(cap, edit)
304} 303}
305 304
306#[cfg(test)] 305#[cfg(test)]
diff --git a/crates/ide_completion/src/completions/record.rs b/crates/ide_completion/src/completions/record.rs
index 0a7927eb8..2f95b8687 100644
--- a/crates/ide_completion/src/completions/record.rs
+++ b/crates/ide_completion/src/completions/record.rs
@@ -22,16 +22,13 @@ pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) ->
22 let completion_text = completion_text 22 let completion_text = completion_text
23 .strip_prefix(ctx.token.to_string().as_str()) 23 .strip_prefix(ctx.token.to_string().as_str())
24 .unwrap_or(completion_text); 24 .unwrap_or(completion_text);
25 acc.add( 25 let mut item = CompletionItem::new(
26 CompletionItem::new( 26 CompletionKind::Snippet,
27 CompletionKind::Snippet, 27 ctx.source_range(),
28 ctx.source_range(), 28 "..Default::default()",
29 "..Default::default()",
30 )
31 .insert_text(completion_text)
32 .kind(SymbolKind::Field)
33 .build(),
34 ); 29 );
30 item.insert_text(completion_text).kind(SymbolKind::Field);
31 item.add_to(acc);
35 } 32 }
36 33
37 missing_fields 34 missing_fields
diff --git a/crates/ide_completion/src/completions/snippet.rs b/crates/ide_completion/src/completions/snippet.rs
index df17a15c5..7f7830976 100644
--- a/crates/ide_completion/src/completions/snippet.rs
+++ b/crates/ide_completion/src/completions/snippet.rs
@@ -8,9 +8,9 @@ use crate::{
8}; 8};
9 9
10fn snippet(ctx: &CompletionContext, cap: SnippetCap, label: &str, snippet: &str) -> Builder { 10fn snippet(ctx: &CompletionContext, cap: SnippetCap, label: &str, snippet: &str) -> Builder {
11 CompletionItem::new(CompletionKind::Snippet, ctx.source_range(), label) 11 let mut item = CompletionItem::new(CompletionKind::Snippet, ctx.source_range(), label);
12 .insert_snippet(cap, snippet) 12 item.insert_snippet(cap, snippet).kind(CompletionItemKind::Snippet);
13 .kind(CompletionItemKind::Snippet) 13 item
14} 14}
15 15
16pub(crate) fn complete_expr_snippet(acc: &mut Completions, ctx: &CompletionContext) { 16pub(crate) fn complete_expr_snippet(acc: &mut Completions, ctx: &CompletionContext) {
@@ -35,7 +35,7 @@ pub(crate) fn complete_item_snippet(acc: &mut Completions, ctx: &CompletionConte
35 None => return, 35 None => return,
36 }; 36 };
37 37
38 snippet( 38 let mut item = snippet(
39 ctx, 39 ctx,
40 cap, 40 cap,
41 "tmod (Test module)", 41 "tmod (Test module)",
@@ -49,11 +49,11 @@ mod tests {
49 $0 49 $0
50 } 50 }
51}", 51}",
52 ) 52 );
53 .lookup_by("tmod") 53 item.lookup_by("tmod");
54 .add_to(acc); 54 item.add_to(acc);
55 55
56 snippet( 56 let mut item = snippet(
57 ctx, 57 ctx,
58 cap, 58 cap,
59 "tfn (Test function)", 59 "tfn (Test function)",
@@ -62,11 +62,12 @@ mod tests {
62fn ${1:feature}() { 62fn ${1:feature}() {
63 $0 63 $0
64}", 64}",
65 ) 65 );
66 .lookup_by("tfn") 66 item.lookup_by("tfn");
67 .add_to(acc); 67 item.add_to(acc);
68 68
69 snippet(ctx, cap, "macro_rules", "macro_rules! $1 {\n\t($2) => {\n\t\t$0\n\t};\n}").add_to(acc); 69 let item = snippet(ctx, cap, "macro_rules", "macro_rules! $1 {\n\t($2) => {\n\t\t$0\n\t};\n}");
70 item.add_to(acc);
70} 71}
71 72
72#[cfg(test)] 73#[cfg(test)]
diff --git a/crates/ide_completion/src/completions/trait_impl.rs b/crates/ide_completion/src/completions/trait_impl.rs
index b999540b8..5a7361f8e 100644
--- a/crates/ide_completion/src/completions/trait_impl.rs
+++ b/crates/ide_completion/src/completions/trait_impl.rs
@@ -145,9 +145,8 @@ fn add_function_impl(
145 format!("fn {}(..)", fn_name) 145 format!("fn {}(..)", fn_name)
146 }; 146 };
147 147
148 let builder = CompletionItem::new(CompletionKind::Magic, ctx.source_range(), label) 148 let mut item = CompletionItem::new(CompletionKind::Magic, ctx.source_range(), label);
149 .lookup_by(fn_name) 149 item.lookup_by(fn_name).set_documentation(func.docs(ctx.db));
150 .set_documentation(func.docs(ctx.db));
151 150
152 let completion_kind = if func.self_param(ctx.db).is_some() { 151 let completion_kind = if func.self_param(ctx.db).is_some() {
153 CompletionItemKind::Method 152 CompletionItemKind::Method
@@ -161,15 +160,15 @@ fn add_function_impl(
161 match ctx.config.snippet_cap { 160 match ctx.config.snippet_cap {
162 Some(cap) => { 161 Some(cap) => {
163 let snippet = format!("{} {{\n $0\n}}", function_decl); 162 let snippet = format!("{} {{\n $0\n}}", function_decl);
164 builder.snippet_edit(cap, TextEdit::replace(range, snippet)) 163 item.snippet_edit(cap, TextEdit::replace(range, snippet));
165 } 164 }
166 None => { 165 None => {
167 let header = format!("{} {{", function_decl); 166 let header = format!("{} {{", function_decl);
168 builder.text_edit(TextEdit::replace(range, header)) 167 item.text_edit(TextEdit::replace(range, header));
169 } 168 }
170 } 169 };
171 .kind(completion_kind) 170 item.kind(completion_kind);
172 .add_to(acc); 171 item.add_to(acc);
173 } 172 }
174} 173}
175 174
@@ -185,12 +184,12 @@ fn add_type_alias_impl(
185 184
186 let range = TextRange::new(type_def_node.text_range().start(), ctx.source_range().end()); 185 let range = TextRange::new(type_def_node.text_range().start(), ctx.source_range().end());
187 186
188 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone()) 187 let mut item = CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone());
189 .text_edit(TextEdit::replace(range, snippet)) 188 item.text_edit(TextEdit::replace(range, snippet))
190 .lookup_by(alias_name) 189 .lookup_by(alias_name)
191 .kind(SymbolKind::TypeAlias) 190 .kind(SymbolKind::TypeAlias)
192 .set_documentation(type_alias.docs(ctx.db)) 191 .set_documentation(type_alias.docs(ctx.db));
193 .add_to(acc); 192 item.add_to(acc);
194} 193}
195 194
196fn add_const_impl( 195fn add_const_impl(
@@ -208,12 +207,13 @@ fn add_const_impl(
208 let range = 207 let range =
209 TextRange::new(const_def_node.text_range().start(), ctx.source_range().end()); 208 TextRange::new(const_def_node.text_range().start(), ctx.source_range().end());
210 209
211 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone()) 210 let mut item =
212 .text_edit(TextEdit::replace(range, snippet)) 211 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone());
212 item.text_edit(TextEdit::replace(range, snippet))
213 .lookup_by(const_name) 213 .lookup_by(const_name)
214 .kind(SymbolKind::Const) 214 .kind(SymbolKind::Const)
215 .set_documentation(const_.docs(ctx.db)) 215 .set_documentation(const_.docs(ctx.db));
216 .add_to(acc); 216 item.add_to(acc);
217 } 217 }
218 } 218 }
219} 219}
diff --git a/crates/ide_completion/src/item.rs b/crates/ide_completion/src/item.rs
index 14afec603..9a4b5217a 100644
--- a/crates/ide_completion/src/item.rs
+++ b/crates/ide_completion/src/item.rs
@@ -70,7 +70,7 @@ pub struct CompletionItem {
70 /// Note that Relevance ignores fuzzy match score. We compute Relevance for 70 /// Note that Relevance ignores fuzzy match score. We compute Relevance for
71 /// all possible items, and then separately build an ordered completion list 71 /// all possible items, and then separately build an ordered completion list
72 /// based on relevance and fuzzy matching with the already typed identifier. 72 /// based on relevance and fuzzy matching with the already typed identifier.
73 relevance: Relevance, 73 relevance: CompletionRelevance,
74 74
75 /// Indicates that a reference or mutable reference to this variable is a 75 /// Indicates that a reference or mutable reference to this variable is a
76 /// possible match. 76 /// possible match.
@@ -107,9 +107,11 @@ impl fmt::Debug for CompletionItem {
107 if self.deprecated { 107 if self.deprecated {
108 s.field("deprecated", &true); 108 s.field("deprecated", &true);
109 } 109 }
110 if self.relevance.is_relevant() { 110
111 if self.relevance != CompletionRelevance::default() {
111 s.field("relevance", &self.relevance); 112 s.field("relevance", &self.relevance);
112 } 113 }
114
113 if let Some(mutability) = &self.ref_match { 115 if let Some(mutability) = &self.ref_match {
114 s.field("ref_match", &format!("&{}", mutability.as_keyword_for_ref())); 116 s.field("ref_match", &format!("&{}", mutability.as_keyword_for_ref()));
115 } 117 }
@@ -120,16 +122,8 @@ impl fmt::Debug for CompletionItem {
120 } 122 }
121} 123}
122 124
123#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq)]
124pub enum CompletionScore {
125 /// If only type match
126 TypeMatch,
127 /// If type and name match
128 TypeAndNameMatch,
129}
130
131#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Default)] 125#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Default)]
132pub struct Relevance { 126pub struct CompletionRelevance {
133 /// This is set in cases like these: 127 /// This is set in cases like these:
134 /// 128 ///
135 /// ``` 129 /// ```
@@ -150,11 +144,54 @@ pub struct Relevance {
150 /// } 144 /// }
151 /// ``` 145 /// ```
152 pub exact_type_match: bool, 146 pub exact_type_match: bool,
147 /// This is set in cases like these:
148 ///
149 /// ```
150 /// fn foo(bar: u32) {
151 /// $0 // `bar` is local
152 /// }
153 /// ```
154 ///
155 /// ```
156 /// fn foo() {
157 /// let bar = 0;
158 /// $0 // `bar` is local
159 /// }
160 /// ```
161 pub is_local: bool,
153} 162}
154 163
155impl Relevance { 164impl CompletionRelevance {
165 /// Provides a relevance score. Higher values are more relevant.
166 ///
167 /// The absolute value of the relevance score is not meaningful, for
168 /// example a value of 0 doesn't mean "not relevant", rather
169 /// it means "least relevant". The score value should only be used
170 /// for relative ordering.
171 ///
172 /// See is_relevant if you need to make some judgement about score
173 /// in an absolute sense.
174 pub fn score(&self) -> u32 {
175 let mut score = 0;
176
177 if self.exact_name_match {
178 score += 1;
179 }
180 if self.exact_type_match {
181 score += 3;
182 }
183 if self.is_local {
184 score += 1;
185 }
186
187 score
188 }
189
190 /// Returns true when the score for this threshold is above
191 /// some threshold such that we think it is especially likely
192 /// to be relevant.
156 pub fn is_relevant(&self) -> bool { 193 pub fn is_relevant(&self) -> bool {
157 self != &Relevance::default() 194 self.score() > 0
158 } 195 }
159} 196}
160 197
@@ -249,7 +286,7 @@ impl CompletionItem {
249 text_edit: None, 286 text_edit: None,
250 deprecated: false, 287 deprecated: false,
251 trigger_call_info: None, 288 trigger_call_info: None,
252 relevance: Relevance::default(), 289 relevance: CompletionRelevance::default(),
253 ref_match: None, 290 ref_match: None,
254 import_to_add: None, 291 import_to_add: None,
255 } 292 }
@@ -292,7 +329,7 @@ impl CompletionItem {
292 self.deprecated 329 self.deprecated
293 } 330 }
294 331
295 pub fn relevance(&self) -> Relevance { 332 pub fn relevance(&self) -> CompletionRelevance {
296 self.relevance 333 self.relevance
297 } 334 }
298 335
@@ -300,8 +337,14 @@ impl CompletionItem {
300 self.trigger_call_info 337 self.trigger_call_info
301 } 338 }
302 339
303 pub fn ref_match(&self) -> Option<Mutability> { 340 pub fn ref_match(&self) -> Option<(Mutability, CompletionRelevance)> {
304 self.ref_match 341 // Relevance of the ref match should be the same as the original
342 // match, but with exact type match set because self.ref_match
343 // is only set if there is an exact type match.
344 let mut relevance = self.relevance;
345 relevance.exact_type_match = true;
346
347 self.ref_match.map(|mutability| (mutability, relevance))
305 } 348 }
306 349
307 pub fn import_to_add(&self) -> Option<&ImportEdit> { 350 pub fn import_to_add(&self) -> Option<&ImportEdit> {
@@ -349,7 +392,7 @@ pub(crate) struct Builder {
349 text_edit: Option<TextEdit>, 392 text_edit: Option<TextEdit>,
350 deprecated: bool, 393 deprecated: bool,
351 trigger_call_info: Option<bool>, 394 trigger_call_info: Option<bool>,
352 relevance: Relevance, 395 relevance: CompletionRelevance,
353 ref_match: Option<Mutability>, 396 ref_match: Option<Mutability>,
354} 397}
355 398
@@ -401,42 +444,42 @@ impl Builder {
401 import_to_add: self.import_to_add, 444 import_to_add: self.import_to_add,
402 } 445 }
403 } 446 }
404 pub(crate) fn lookup_by(mut self, lookup: impl Into<String>) -> Builder { 447 pub(crate) fn lookup_by(&mut self, lookup: impl Into<String>) -> &mut Builder {
405 self.lookup = Some(lookup.into()); 448 self.lookup = Some(lookup.into());
406 self 449 self
407 } 450 }
408 pub(crate) fn label(mut self, label: impl Into<String>) -> Builder { 451 pub(crate) fn label(&mut self, label: impl Into<String>) -> &mut Builder {
409 self.label = label.into(); 452 self.label = label.into();
410 self 453 self
411 } 454 }
412 pub(crate) fn insert_text(mut self, insert_text: impl Into<String>) -> Builder { 455 pub(crate) fn insert_text(&mut self, insert_text: impl Into<String>) -> &mut Builder {
413 self.insert_text = Some(insert_text.into()); 456 self.insert_text = Some(insert_text.into());
414 self 457 self
415 } 458 }
416 pub(crate) fn insert_snippet( 459 pub(crate) fn insert_snippet(
417 mut self, 460 &mut self,
418 _cap: SnippetCap, 461 _cap: SnippetCap,
419 snippet: impl Into<String>, 462 snippet: impl Into<String>,
420 ) -> Builder { 463 ) -> &mut Builder {
421 self.insert_text_format = InsertTextFormat::Snippet; 464 self.insert_text_format = InsertTextFormat::Snippet;
422 self.insert_text(snippet) 465 self.insert_text(snippet)
423 } 466 }
424 pub(crate) fn kind(mut self, kind: impl Into<CompletionItemKind>) -> Builder { 467 pub(crate) fn kind(&mut self, kind: impl Into<CompletionItemKind>) -> &mut Builder {
425 self.kind = Some(kind.into()); 468 self.kind = Some(kind.into());
426 self 469 self
427 } 470 }
428 pub(crate) fn text_edit(mut self, edit: TextEdit) -> Builder { 471 pub(crate) fn text_edit(&mut self, edit: TextEdit) -> &mut Builder {
429 self.text_edit = Some(edit); 472 self.text_edit = Some(edit);
430 self 473 self
431 } 474 }
432 pub(crate) fn snippet_edit(mut self, _cap: SnippetCap, edit: TextEdit) -> Builder { 475 pub(crate) fn snippet_edit(&mut self, _cap: SnippetCap, edit: TextEdit) -> &mut Builder {
433 self.insert_text_format = InsertTextFormat::Snippet; 476 self.insert_text_format = InsertTextFormat::Snippet;
434 self.text_edit(edit) 477 self.text_edit(edit)
435 } 478 }
436 pub(crate) fn detail(self, detail: impl Into<String>) -> Builder { 479 pub(crate) fn detail(&mut self, detail: impl Into<String>) -> &mut Builder {
437 self.set_detail(Some(detail)) 480 self.set_detail(Some(detail))
438 } 481 }
439 pub(crate) fn set_detail(mut self, detail: Option<impl Into<String>>) -> Builder { 482 pub(crate) fn set_detail(&mut self, detail: Option<impl Into<String>>) -> &mut Builder {
440 self.detail = detail.map(Into::into); 483 self.detail = detail.map(Into::into);
441 if let Some(detail) = &self.detail { 484 if let Some(detail) = &self.detail {
442 if never!(detail.contains('\n'), "multiline detail:\n{}", detail) { 485 if never!(detail.contains('\n'), "multiline detail:\n{}", detail) {
@@ -446,31 +489,106 @@ impl Builder {
446 self 489 self
447 } 490 }
448 #[allow(unused)] 491 #[allow(unused)]
449 pub(crate) fn documentation(self, docs: Documentation) -> Builder { 492 pub(crate) fn documentation(&mut self, docs: Documentation) -> &mut Builder {
450 self.set_documentation(Some(docs)) 493 self.set_documentation(Some(docs))
451 } 494 }
452 pub(crate) fn set_documentation(mut self, docs: Option<Documentation>) -> Builder { 495 pub(crate) fn set_documentation(&mut self, docs: Option<Documentation>) -> &mut Builder {
453 self.documentation = docs.map(Into::into); 496 self.documentation = docs.map(Into::into);
454 self 497 self
455 } 498 }
456 pub(crate) fn set_deprecated(mut self, deprecated: bool) -> Builder { 499 pub(crate) fn set_deprecated(&mut self, deprecated: bool) -> &mut Builder {
457 self.deprecated = deprecated; 500 self.deprecated = deprecated;
458 self 501 self
459 } 502 }
460 pub(crate) fn set_relevance(mut self, relevance: Relevance) -> Builder { 503 pub(crate) fn set_relevance(&mut self, relevance: CompletionRelevance) -> &mut Builder {
461 self.relevance = relevance; 504 self.relevance = relevance;
462 self 505 self
463 } 506 }
464 pub(crate) fn trigger_call_info(mut self) -> Builder { 507 pub(crate) fn trigger_call_info(&mut self) -> &mut Builder {
465 self.trigger_call_info = Some(true); 508 self.trigger_call_info = Some(true);
466 self 509 self
467 } 510 }
468 pub(crate) fn add_import(mut self, import_to_add: Option<ImportEdit>) -> Builder { 511 pub(crate) fn add_import(&mut self, import_to_add: Option<ImportEdit>) -> &mut Builder {
469 self.import_to_add = import_to_add; 512 self.import_to_add = import_to_add;
470 self 513 self
471 } 514 }
472 pub(crate) fn ref_match(mut self, mutability: Mutability) -> Builder { 515 pub(crate) fn ref_match(&mut self, mutability: Mutability) -> &mut Builder {
473 self.ref_match = Some(mutability); 516 self.ref_match = Some(mutability);
474 self 517 self
475 } 518 }
476} 519}
520
521#[cfg(test)]
522mod tests {
523 use itertools::Itertools;
524 use test_utils::assert_eq_text;
525
526 use super::CompletionRelevance;
527
528 /// Check that these are CompletionRelevance are sorted in ascending order
529 /// by their relevance score.
530 ///
531 /// We want to avoid making assertions about the absolute score of any
532 /// item, but we do want to assert whether each is >, <, or == to the
533 /// others.
534 ///
535 /// If provided vec![vec![a], vec![b, c], vec![d]], then this will assert:
536 /// a.score < b.score == c.score < d.score
537 fn check_relevance_score_ordered(expected_relevance_order: Vec<Vec<CompletionRelevance>>) {
538 let expected = format!("{:#?}", &expected_relevance_order);
539
540 let actual_relevance_order = expected_relevance_order
541 .into_iter()
542 .flatten()
543 .map(|r| (r.score(), r))
544 .sorted_by_key(|(score, _r)| *score)
545 .fold(
546 (u32::MIN, vec![vec![]]),
547 |(mut currently_collecting_score, mut out), (score, r)| {
548 if currently_collecting_score == score {
549 out.last_mut().unwrap().push(r);
550 } else {
551 currently_collecting_score = score;
552 out.push(vec![r]);
553 }
554 (currently_collecting_score, out)
555 },
556 )
557 .1;
558
559 let actual = format!("{:#?}", &actual_relevance_order);
560
561 assert_eq_text!(&expected, &actual);
562 }
563
564 #[test]
565 fn relevance_score() {
566 // This test asserts that the relevance score for these items is ascending, and
567 // that any items in the same vec have the same score.
568 let expected_relevance_order = vec![
569 vec![CompletionRelevance::default()],
570 vec![
571 CompletionRelevance { exact_name_match: true, ..CompletionRelevance::default() },
572 CompletionRelevance { is_local: true, ..CompletionRelevance::default() },
573 ],
574 vec![CompletionRelevance {
575 exact_name_match: true,
576 is_local: true,
577 ..CompletionRelevance::default()
578 }],
579 vec![CompletionRelevance { exact_type_match: true, ..CompletionRelevance::default() }],
580 vec![CompletionRelevance {
581 exact_name_match: true,
582 exact_type_match: true,
583 ..CompletionRelevance::default()
584 }],
585 vec![CompletionRelevance {
586 exact_name_match: true,
587 exact_type_match: true,
588 is_local: true,
589 }],
590 ];
591
592 check_relevance_score_ordered(expected_relevance_order);
593 }
594}
diff --git a/crates/ide_completion/src/lib.rs b/crates/ide_completion/src/lib.rs
index d46f521a0..263554ecf 100644
--- a/crates/ide_completion/src/lib.rs
+++ b/crates/ide_completion/src/lib.rs
@@ -23,10 +23,7 @@ use crate::{completions::Completions, context::CompletionContext, item::Completi
23 23
24pub use crate::{ 24pub use crate::{
25 config::CompletionConfig, 25 config::CompletionConfig,
26 item::{ 26 item::{CompletionItem, CompletionItemKind, CompletionRelevance, ImportEdit, InsertTextFormat},
27 CompletionItem, CompletionItemKind, CompletionScore, ImportEdit, InsertTextFormat,
28 Relevance,
29 },
30}; 27};
31 28
32//FIXME: split the following feature into fine-grained features. 29//FIXME: split the following feature into fine-grained features.
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs
index 8c8b149a1..905f0b197 100644
--- a/crates/ide_completion/src/render.rs
+++ b/crates/ide_completion/src/render.rs
@@ -10,8 +10,10 @@ pub(crate) mod type_alias;
10 10
11mod builder_ext; 11mod builder_ext;
12 12
13use base_db::Upcast;
13use hir::{ 14use hir::{
14 AsAssocItem, Documentation, HasAttrs, HirDisplay, ModuleDef, Mutability, ScopeDef, Type, 15 db::HirDatabase, AsAssocItem, Documentation, HasAttrs, HirDisplay, ModuleDef, Mutability,
16 ScopeDef, Type,
15}; 17};
16use ide_db::{ 18use ide_db::{
17 helpers::{item_name, SnippetCap}, 19 helpers::{item_name, SnippetCap},
@@ -20,7 +22,7 @@ use ide_db::{
20use syntax::TextRange; 22use syntax::TextRange;
21 23
22use crate::{ 24use crate::{
23 item::{ImportEdit, Relevance}, 25 item::{CompletionRelevance, ImportEdit},
24 CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, 26 CompletionContext, CompletionItem, CompletionItemKind, CompletionKind,
25}; 27};
26 28
@@ -149,24 +151,27 @@ impl<'a> Render<'a> {
149 CompletionKind::Reference, 151 CompletionKind::Reference,
150 self.ctx.source_range(), 152 self.ctx.source_range(),
151 name.to_string(), 153 name.to_string(),
152 ) 154 );
153 .kind(SymbolKind::Field) 155 item.kind(SymbolKind::Field)
154 .detail(ty.display(self.ctx.db()).to_string()) 156 .detail(ty.display(self.ctx.db()).to_string())
155 .set_documentation(field.docs(self.ctx.db())) 157 .set_documentation(field.docs(self.ctx.db()))
156 .set_deprecated(is_deprecated); 158 .set_deprecated(is_deprecated);
157 159
158 if let Some(relevance) = compute_relevance(&self.ctx, &ty, &name.to_string()) { 160 item.set_relevance(compute_relevance(&self.ctx, &ty, &name.to_string()));
159 item = item.set_relevance(relevance);
160 }
161 161
162 item.build() 162 item.build()
163 } 163 }
164 164
165 fn add_tuple_field(&mut self, field: usize, ty: &Type) -> CompletionItem { 165 fn add_tuple_field(&mut self, field: usize, ty: &Type) -> CompletionItem {
166 CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), field.to_string()) 166 let mut item = CompletionItem::new(
167 .kind(SymbolKind::Field) 167 CompletionKind::Reference,
168 .detail(ty.display(self.ctx.db()).to_string()) 168 self.ctx.source_range(),
169 .build() 169 field.to_string(),
170 );
171
172 item.kind(SymbolKind::Field).detail(ty.display(self.ctx.db()).to_string());
173
174 item.build()
170 } 175 }
171 176
172 fn render_resolution( 177 fn render_resolution(
@@ -225,15 +230,13 @@ impl<'a> Render<'a> {
225 CompletionItemKind::SymbolKind(SymbolKind::SelfParam) 230 CompletionItemKind::SymbolKind(SymbolKind::SelfParam)
226 } 231 }
227 ScopeDef::Unknown => { 232 ScopeDef::Unknown => {
228 let item = CompletionItem::new( 233 let mut item = CompletionItem::new(
229 CompletionKind::Reference, 234 CompletionKind::Reference,
230 self.ctx.source_range(), 235 self.ctx.source_range(),
231 local_name, 236 local_name,
232 ) 237 );
233 .kind(CompletionItemKind::UnresolvedReference) 238 item.kind(CompletionItemKind::UnresolvedReference).add_import(import_to_add);
234 .add_import(import_to_add) 239 return Some(item.build());
235 .build();
236 return Some(item);
237 } 240 }
238 }; 241 };
239 242
@@ -242,25 +245,29 @@ impl<'a> Render<'a> {
242 if let ScopeDef::Local(local) = resolution { 245 if let ScopeDef::Local(local) = resolution {
243 let ty = local.ty(self.ctx.db()); 246 let ty = local.ty(self.ctx.db());
244 if !ty.is_unknown() { 247 if !ty.is_unknown() {
245 item = item.detail(ty.display(self.ctx.db()).to_string()); 248 item.detail(ty.display(self.ctx.db()).to_string());
246 } 249 }
247 }; 250 };
248 251
249 if let ScopeDef::Local(local) = resolution { 252 if let ScopeDef::Local(local) = resolution {
250 let ty = local.ty(self.ctx.db()); 253 let ty = local.ty(self.ctx.db());
251 if let Some(relevance) = compute_relevance(&self.ctx, &ty, &local_name) { 254
252 item = item.set_relevance(relevance) 255 let mut relevance = compute_relevance(&self.ctx, &ty, &local_name);
253 } 256 relevance.is_local = true;
257 item.set_relevance(relevance);
258
254 if let Some((_expected_name, expected_type)) = self.ctx.expected_name_and_type() { 259 if let Some((_expected_name, expected_type)) = self.ctx.expected_name_and_type() {
255 if let Some(ty_without_ref) = expected_type.remove_ref() { 260 if ty != expected_type {
256 if ty_without_ref == ty { 261 if let Some(ty_without_ref) = expected_type.remove_ref() {
257 cov_mark::hit!(suggest_ref); 262 if relevance_type_match(self.ctx.db().upcast(), &ty, &ty_without_ref) {
258 let mutability = if expected_type.is_mutable_reference() { 263 cov_mark::hit!(suggest_ref);
259 Mutability::Mut 264 let mutability = if expected_type.is_mutable_reference() {
260 } else { 265 Mutability::Mut
261 Mutability::Shared 266 } else {
262 }; 267 Mutability::Shared
263 item = item.ref_match(mutability) 268 };
269 item.ref_match(mutability);
270 }
264 } 271 }
265 } 272 }
266 } 273 }
@@ -281,21 +288,17 @@ impl<'a> Render<'a> {
281 }; 288 };
282 if has_non_default_type_params { 289 if has_non_default_type_params {
283 cov_mark::hit!(inserts_angle_brackets_for_generics); 290 cov_mark::hit!(inserts_angle_brackets_for_generics);
284 item = item 291 item.lookup_by(local_name.clone())
285 .lookup_by(local_name.clone())
286 .label(format!("{}<…>", local_name)) 292 .label(format!("{}<…>", local_name))
287 .insert_snippet(cap, format!("{}<$0>", local_name)); 293 .insert_snippet(cap, format!("{}<$0>", local_name));
288 } 294 }
289 } 295 }
290 } 296 }
291 297 item.kind(kind)
292 Some( 298 .add_import(import_to_add)
293 item.kind(kind) 299 .set_documentation(self.docs(resolution))
294 .add_import(import_to_add) 300 .set_deprecated(self.is_deprecated(resolution));
295 .set_documentation(self.docs(resolution)) 301 Some(item.build())
296 .set_deprecated(self.is_deprecated(resolution))
297 .build(),
298 )
299 } 302 }
300 303
301 fn docs(&self, resolution: &ScopeDef) -> Option<Documentation> { 304 fn docs(&self, resolution: &ScopeDef) -> Option<Documentation> {
@@ -323,23 +326,29 @@ impl<'a> Render<'a> {
323 } 326 }
324} 327}
325 328
326fn compute_relevance(ctx: &RenderContext, ty: &Type, name: &str) -> Option<Relevance> { 329fn compute_relevance(ctx: &RenderContext, ty: &Type, name: &str) -> CompletionRelevance {
327 let (expected_name, expected_type) = ctx.expected_name_and_type()?; 330 let mut res = CompletionRelevance::default();
328 let mut res = Relevance::default(); 331
329 res.exact_type_match = ty == &expected_type; 332 if let Some((expected_name, expected_type)) = ctx.expected_name_and_type() {
330 res.exact_name_match = name == &expected_name; 333 res.exact_type_match = ty == &expected_type;
331 Some(res) 334 res.exact_name_match = name == &expected_name;
335 }
336
337 res
338}
339
340fn relevance_type_match(db: &dyn HirDatabase, ty: &Type, expected_type: &Type) -> bool {
341 ty == expected_type || ty.autoderef(db).any(|deref_ty| &deref_ty == expected_type)
332} 342}
333 343
334#[cfg(test)] 344#[cfg(test)]
335mod tests { 345mod tests {
336 use std::cmp::Reverse;
337
338 use expect_test::{expect, Expect}; 346 use expect_test::{expect, Expect};
347 use itertools::Itertools;
339 348
340 use crate::{ 349 use crate::{
341 test_utils::{check_edit, do_completion, get_all_items, TEST_CONFIG}, 350 test_utils::{check_edit, do_completion, get_all_items, TEST_CONFIG},
342 CompletionKind, Relevance, 351 CompletionKind, CompletionRelevance,
343 }; 352 };
344 353
345 fn check(ra_fixture: &str, expect: Expect) { 354 fn check(ra_fixture: &str, expect: Expect) {
@@ -348,26 +357,40 @@ mod tests {
348 } 357 }
349 358
350 fn check_relevance(ra_fixture: &str, expect: Expect) { 359 fn check_relevance(ra_fixture: &str, expect: Expect) {
351 fn display_relevance(relevance: Relevance) -> &'static str { 360 fn display_relevance(relevance: CompletionRelevance) -> String {
352 match relevance { 361 let relevance_factors = vec![
353 Relevance { exact_type_match: true, exact_name_match: true } => "[type+name]", 362 (relevance.exact_type_match, "type"),
354 Relevance { exact_type_match: true, exact_name_match: false } => "[type]", 363 (relevance.exact_name_match, "name"),
355 Relevance { exact_type_match: false, exact_name_match: true } => "[name]", 364 (relevance.is_local, "local"),
356 Relevance { exact_type_match: false, exact_name_match: false } => "[]", 365 ]
357 } 366 .into_iter()
367 .filter_map(|(cond, desc)| if cond { Some(desc) } else { None })
368 .join("+");
369
370 format!("[{}]", relevance_factors)
358 } 371 }
359 372
360 let mut completions = get_all_items(TEST_CONFIG, ra_fixture); 373 let actual = get_all_items(TEST_CONFIG, ra_fixture)
361 completions.sort_by_key(|it| (Reverse(it.relevance()), it.label().to_string()));
362 let actual = completions
363 .into_iter() 374 .into_iter()
364 .filter(|it| it.completion_kind == CompletionKind::Reference) 375 .filter(|it| it.completion_kind == CompletionKind::Reference)
365 .map(|it| { 376 .flat_map(|it| {
377 let mut items = vec![];
378
366 let tag = it.kind().unwrap().tag(); 379 let tag = it.kind().unwrap().tag();
367 let relevance = display_relevance(it.relevance()); 380 let relevance = display_relevance(it.relevance());
368 format!("{} {} {}\n", tag, it.label(), relevance) 381 items.push(format!("{} {} {}\n", tag, it.label(), relevance));
382
383 if let Some((mutability, relevance)) = it.ref_match() {
384 let label = format!("&{}{}", mutability.as_keyword_for_ref(), it.label());
385 let relevance = display_relevance(relevance);
386
387 items.push(format!("{} {} {}\n", tag, label, relevance));
388 }
389
390 items
369 }) 391 })
370 .collect::<String>(); 392 .collect::<String>();
393
371 expect.assert_eq(&actual); 394 expect.assert_eq(&actual);
372 } 395 }
373 396
@@ -837,9 +860,9 @@ fn test(bar: u32) { }
837fn foo(s: S) { test(s.$0) } 860fn foo(s: S) { test(s.$0) }
838"#, 861"#,
839 expect![[r#" 862 expect![[r#"
863 fd foo []
840 fd bar [type+name] 864 fd bar [type+name]
841 fd baz [type] 865 fd baz [type]
842 fd foo []
843 "#]], 866 "#]],
844 ); 867 );
845 } 868 }
@@ -854,9 +877,9 @@ struct B { x: (), y: f32, bar: u32 }
854fn foo(a: A) { B { bar: a.$0 }; } 877fn foo(a: A) { B { bar: a.$0 }; }
855"#, 878"#,
856 expect![[r#" 879 expect![[r#"
880 fd foo []
857 fd bar [type+name] 881 fd bar [type+name]
858 fd baz [type] 882 fd baz [type]
859 fd foo []
860 "#]], 883 "#]],
861 ) 884 )
862 } 885 }
@@ -884,9 +907,9 @@ fn f(foo: i64) { }
884fn foo(a: A) { f(B { bar: a.$0 }); } 907fn foo(a: A) { f(B { bar: a.$0 }); }
885"#, 908"#,
886 expect![[r#" 909 expect![[r#"
910 fd foo []
887 fd bar [type+name] 911 fd bar [type+name]
888 fd baz [type] 912 fd baz [type]
889 fd foo []
890 "#]], 913 "#]],
891 ); 914 );
892 } 915 }
@@ -899,7 +922,7 @@ struct WorldSnapshot { _f: () };
899fn go(world: &WorldSnapshot) { go(w$0) } 922fn go(world: &WorldSnapshot) { go(w$0) }
900"#, 923"#,
901 expect![[r#" 924 expect![[r#"
902 lc world [type+name] 925 lc world [type+name+local]
903 st WorldSnapshot [] 926 st WorldSnapshot []
904 fn go(…) [] 927 fn go(…) []
905 "#]], 928 "#]],
@@ -914,9 +937,9 @@ struct Foo;
914fn f(foo: &Foo) { f(foo, w$0) } 937fn f(foo: &Foo) { f(foo, w$0) }
915"#, 938"#,
916 expect![[r#" 939 expect![[r#"
940 lc foo [local]
917 st Foo [] 941 st Foo []
918 fn f(…) [] 942 fn f(…) []
919 lc foo []
920 "#]], 943 "#]],
921 ); 944 );
922 } 945 }
@@ -976,9 +999,10 @@ fn main() {
976 Local, 999 Local,
977 ), 1000 ),
978 detail: "S", 1001 detail: "S",
979 relevance: Relevance { 1002 relevance: CompletionRelevance {
980 exact_name_match: true, 1003 exact_name_match: true,
981 exact_type_match: false, 1004 exact_type_match: false,
1005 is_local: true,
982 }, 1006 },
983 ref_match: "&mut ", 1007 ref_match: "&mut ",
984 }, 1008 },
@@ -986,4 +1010,120 @@ fn main() {
986 "#]], 1010 "#]],
987 ) 1011 )
988 } 1012 }
1013
1014 #[test]
1015 fn suggest_deref() {
1016 check_relevance(
1017 r#"
1018#[lang = "deref"]
1019trait Deref {
1020 type Target;
1021 fn deref(&self) -> &Self::Target;
1022}
1023
1024struct S;
1025struct T(S);
1026
1027impl Deref for T {
1028 type Target = S;
1029
1030 fn deref(&self) -> &Self::Target {
1031 &self.0
1032 }
1033}
1034
1035fn foo(s: &S) {}
1036
1037fn main() {
1038 let t = T(S);
1039 let m = 123;
1040
1041 foo($0);
1042}
1043 "#,
1044 expect![[r#"
1045 lc m [local]
1046 lc t [local]
1047 lc &t [type+local]
1048 st T []
1049 st S []
1050 fn main() []
1051 tt Deref []
1052 fn foo(…) []
1053 "#]],
1054 )
1055 }
1056
1057 #[test]
1058 fn suggest_deref_mut() {
1059 check_relevance(
1060 r#"
1061#[lang = "deref"]
1062trait Deref {
1063 type Target;
1064 fn deref(&self) -> &Self::Target;
1065}
1066
1067#[lang = "deref_mut"]
1068pub trait DerefMut: Deref {
1069 fn deref_mut(&mut self) -> &mut Self::Target;
1070}
1071
1072struct S;
1073struct T(S);
1074
1075impl Deref for T {
1076 type Target = S;
1077
1078 fn deref(&self) -> &Self::Target {
1079 &self.0
1080 }
1081}
1082
1083impl DerefMut for T {
1084 fn deref_mut(&mut self) -> &mut Self::Target {
1085 &mut self.0
1086 }
1087}
1088
1089fn foo(s: &mut S) {}
1090
1091fn main() {
1092 let t = T(S);
1093 let m = 123;
1094
1095 foo($0);
1096}
1097 "#,
1098 expect![[r#"
1099 lc m [local]
1100 lc t [local]
1101 lc &mut t [type+local]
1102 tt DerefMut []
1103 tt Deref []
1104 fn foo(…) []
1105 st T []
1106 st S []
1107 fn main() []
1108 "#]],
1109 )
1110 }
1111
1112 #[test]
1113 fn locals() {
1114 check_relevance(
1115 r#"
1116fn foo(bar: u32) {
1117 let baz = 0;
1118
1119 f$0
1120}
1121"#,
1122 expect![[r#"
1123 lc baz [local]
1124 lc bar [local]
1125 fn foo(…) []
1126 "#]],
1127 );
1128 }
989} 1129}
diff --git a/crates/ide_completion/src/render/builder_ext.rs b/crates/ide_completion/src/render/builder_ext.rs
index 95a7596c1..6d062b3b9 100644
--- a/crates/ide_completion/src/render/builder_ext.rs
+++ b/crates/ide_completion/src/render/builder_ext.rs
@@ -52,11 +52,11 @@ impl Builder {
52 } 52 }
53 53
54 pub(super) fn add_call_parens( 54 pub(super) fn add_call_parens(
55 mut self, 55 &mut self,
56 ctx: &CompletionContext, 56 ctx: &CompletionContext,
57 name: String, 57 name: String,
58 params: Params, 58 params: Params,
59 ) -> Builder { 59 ) -> &mut Builder {
60 if !self.should_add_parens(ctx) { 60 if !self.should_add_parens(ctx) {
61 return self; 61 return self;
62 } 62 }
@@ -71,7 +71,7 @@ impl Builder {
71 let (snippet, label) = if params.is_empty() { 71 let (snippet, label) = if params.is_empty() {
72 (format!("{}()$0", name), format!("{}()", name)) 72 (format!("{}()$0", name), format!("{}()", name))
73 } else { 73 } else {
74 self = self.trigger_call_info(); 74 self.trigger_call_info();
75 let snippet = match (ctx.config.add_call_argument_snippets, params) { 75 let snippet = match (ctx.config.add_call_argument_snippets, params) {
76 (true, Params::Named(params)) => { 76 (true, Params::Named(params)) => {
77 let function_params_snippet = 77 let function_params_snippet =
diff --git a/crates/ide_completion/src/render/const_.rs b/crates/ide_completion/src/render/const_.rs
index 5010b642a..8add369e4 100644
--- a/crates/ide_completion/src/render/const_.rs
+++ b/crates/ide_completion/src/render/const_.rs
@@ -36,17 +36,17 @@ impl<'a> ConstRender<'a> {
36 let name = self.name()?; 36 let name = self.name()?;
37 let detail = self.detail(); 37 let detail = self.detail();
38 38
39 let item = CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), name) 39 let mut item =
40 .kind(SymbolKind::Const) 40 CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), name);
41 item.kind(SymbolKind::Const)
41 .set_documentation(self.ctx.docs(self.const_)) 42 .set_documentation(self.ctx.docs(self.const_))
42 .set_deprecated( 43 .set_deprecated(
43 self.ctx.is_deprecated(self.const_) 44 self.ctx.is_deprecated(self.const_)
44 || self.ctx.is_deprecated_assoc_item(self.const_), 45 || self.ctx.is_deprecated_assoc_item(self.const_),
45 ) 46 )
46 .detail(detail) 47 .detail(detail);
47 .build();
48 48
49 Some(item) 49 Some(item.build())
50 } 50 }
51 51
52 fn name(&self) -> Option<String> { 52 fn name(&self) -> Option<String> {
diff --git a/crates/ide_completion/src/render/enum_variant.rs b/crates/ide_completion/src/render/enum_variant.rs
index ed055c1fb..e8cfcc0c7 100644
--- a/crates/ide_completion/src/render/enum_variant.rs
+++ b/crates/ide_completion/src/render/enum_variant.rs
@@ -55,27 +55,26 @@ impl<'a> EnumRender<'a> {
55 } 55 }
56 56
57 fn render(self, import_to_add: Option<ImportEdit>) -> CompletionItem { 57 fn render(self, import_to_add: Option<ImportEdit>) -> CompletionItem {
58 let mut builder = CompletionItem::new( 58 let mut item = CompletionItem::new(
59 CompletionKind::Reference, 59 CompletionKind::Reference,
60 self.ctx.source_range(), 60 self.ctx.source_range(),
61 self.qualified_name.clone(), 61 self.qualified_name.clone(),
62 ) 62 );
63 .kind(SymbolKind::Variant) 63 item.kind(SymbolKind::Variant)
64 .set_documentation(self.variant.docs(self.ctx.db())) 64 .set_documentation(self.variant.docs(self.ctx.db()))
65 .set_deprecated(self.ctx.is_deprecated(self.variant)) 65 .set_deprecated(self.ctx.is_deprecated(self.variant))
66 .add_import(import_to_add) 66 .add_import(import_to_add)
67 .detail(self.detail()); 67 .detail(self.detail());
68 68
69 if self.variant_kind == StructKind::Tuple { 69 if self.variant_kind == StructKind::Tuple {
70 cov_mark::hit!(inserts_parens_for_tuple_enums); 70 cov_mark::hit!(inserts_parens_for_tuple_enums);
71 let params = Params::Anonymous(self.variant.fields(self.ctx.db()).len()); 71 let params = Params::Anonymous(self.variant.fields(self.ctx.db()).len());
72 builder = 72 item.add_call_parens(self.ctx.completion, self.short_qualified_name, params);
73 builder.add_call_parens(self.ctx.completion, self.short_qualified_name, params);
74 } else if self.path.is_some() { 73 } else if self.path.is_some() {
75 builder = builder.lookup_by(self.short_qualified_name); 74 item.lookup_by(self.short_qualified_name);
76 } 75 }
77 76
78 builder.build() 77 item.build()
79 } 78 }
80 79
81 fn detail(&self) -> String { 80 fn detail(&self) -> String {
diff --git a/crates/ide_completion/src/render/function.rs b/crates/ide_completion/src/render/function.rs
index 5931945a8..f4dabe3d1 100644
--- a/crates/ide_completion/src/render/function.rs
+++ b/crates/ide_completion/src/render/function.rs
@@ -41,16 +41,21 @@ impl<'a> FunctionRender<'a> {
41 41
42 fn render(self, import_to_add: Option<ImportEdit>) -> CompletionItem { 42 fn render(self, import_to_add: Option<ImportEdit>) -> CompletionItem {
43 let params = self.params(); 43 let params = self.params();
44 CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), self.name.clone()) 44 let mut item = CompletionItem::new(
45 .kind(self.kind()) 45 CompletionKind::Reference,
46 self.ctx.source_range(),
47 self.name.clone(),
48 );
49 item.kind(self.kind())
46 .set_documentation(self.ctx.docs(self.func)) 50 .set_documentation(self.ctx.docs(self.func))
47 .set_deprecated( 51 .set_deprecated(
48 self.ctx.is_deprecated(self.func) || self.ctx.is_deprecated_assoc_item(self.func), 52 self.ctx.is_deprecated(self.func) || self.ctx.is_deprecated_assoc_item(self.func),
49 ) 53 )
50 .detail(self.detail()) 54 .detail(self.detail())
51 .add_call_parens(self.ctx.completion, self.name, params) 55 .add_call_parens(self.ctx.completion, self.name, params)
52 .add_import(import_to_add) 56 .add_import(import_to_add);
53 .build() 57
58 item.build()
54 } 59 }
55 60
56 fn detail(&self) -> String { 61 fn detail(&self) -> String {
diff --git a/crates/ide_completion/src/render/macro_.rs b/crates/ide_completion/src/render/macro_.rs
index a6cf3e479..3fa21ba7c 100644
--- a/crates/ide_completion/src/render/macro_.rs
+++ b/crates/ide_completion/src/render/macro_.rs
@@ -39,29 +39,31 @@ impl<'a> MacroRender<'a> {
39 } 39 }
40 40
41 fn render(&self, import_to_add: Option<ImportEdit>) -> Option<CompletionItem> { 41 fn render(&self, import_to_add: Option<ImportEdit>) -> Option<CompletionItem> {
42 let mut builder = 42 let mut item =
43 CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), &self.label()) 43 CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), &self.label());
44 .kind(SymbolKind::Macro) 44 item.kind(SymbolKind::Macro)
45 .set_documentation(self.docs.clone()) 45 .set_documentation(self.docs.clone())
46 .set_deprecated(self.ctx.is_deprecated(self.macro_)) 46 .set_deprecated(self.ctx.is_deprecated(self.macro_))
47 .add_import(import_to_add) 47 .add_import(import_to_add)
48 .set_detail(self.detail()); 48 .set_detail(self.detail());
49 49
50 let needs_bang = self.needs_bang(); 50 let needs_bang = self.needs_bang();
51 builder = match self.ctx.snippet_cap() { 51 match self.ctx.snippet_cap() {
52 Some(cap) if needs_bang => { 52 Some(cap) if needs_bang => {
53 let snippet = self.snippet(); 53 let snippet = self.snippet();
54 let lookup = self.lookup(); 54 let lookup = self.lookup();
55 builder.insert_snippet(cap, snippet).lookup_by(lookup) 55 item.insert_snippet(cap, snippet).lookup_by(lookup);
56 }
57 None if needs_bang => {
58 item.insert_text(self.banged_name());
56 } 59 }
57 None if needs_bang => builder.insert_text(self.banged_name()),
58 _ => { 60 _ => {
59 cov_mark::hit!(dont_insert_macro_call_parens_unncessary); 61 cov_mark::hit!(dont_insert_macro_call_parens_unncessary);
60 builder.insert_text(&self.name) 62 item.insert_text(&self.name);
61 } 63 }
62 }; 64 };
63 65
64 Some(builder.build()) 66 Some(item.build())
65 } 67 }
66 68
67 fn needs_bang(&self) -> bool { 69 fn needs_bang(&self) -> bool {
diff --git a/crates/ide_completion/src/render/pattern.rs b/crates/ide_completion/src/render/pattern.rs
index 465dfe00c..ca2926125 100644
--- a/crates/ide_completion/src/render/pattern.rs
+++ b/crates/ide_completion/src/render/pattern.rs
@@ -69,19 +69,19 @@ fn build_completion(
69 ctx: RenderContext<'_>, 69 ctx: RenderContext<'_>,
70 name: String, 70 name: String,
71 pat: String, 71 pat: String,
72 item: impl HasAttrs + Copy, 72 def: impl HasAttrs + Copy,
73) -> CompletionItem { 73) -> CompletionItem {
74 let completion = CompletionItem::new(CompletionKind::Snippet, ctx.source_range(), name) 74 let mut item = CompletionItem::new(CompletionKind::Snippet, ctx.source_range(), name);
75 .kind(CompletionItemKind::Binding) 75 item.kind(CompletionItemKind::Binding)
76 .set_documentation(ctx.docs(item)) 76 .set_documentation(ctx.docs(def))
77 .set_deprecated(ctx.is_deprecated(item)) 77 .set_deprecated(ctx.is_deprecated(def))
78 .detail(&pat); 78 .detail(&pat);
79 let completion = if let Some(snippet_cap) = ctx.snippet_cap() { 79 if let Some(snippet_cap) = ctx.snippet_cap() {
80 completion.insert_snippet(snippet_cap, pat) 80 item.insert_snippet(snippet_cap, pat);
81 } else { 81 } else {
82 completion.insert_text(pat) 82 item.insert_text(pat);
83 }; 83 };
84 completion.build() 84 item.build()
85} 85}
86 86
87fn render_pat( 87fn render_pat(
diff --git a/crates/ide_completion/src/render/type_alias.rs b/crates/ide_completion/src/render/type_alias.rs
index bd97c3692..e47b4c745 100644
--- a/crates/ide_completion/src/render/type_alias.rs
+++ b/crates/ide_completion/src/render/type_alias.rs
@@ -36,17 +36,17 @@ impl<'a> TypeAliasRender<'a> {
36 let name = self.name()?; 36 let name = self.name()?;
37 let detail = self.detail(); 37 let detail = self.detail();
38 38
39 let item = CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), name) 39 let mut item =
40 .kind(SymbolKind::TypeAlias) 40 CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), name);
41 item.kind(SymbolKind::TypeAlias)
41 .set_documentation(self.ctx.docs(self.type_alias)) 42 .set_documentation(self.ctx.docs(self.type_alias))
42 .set_deprecated( 43 .set_deprecated(
43 self.ctx.is_deprecated(self.type_alias) 44 self.ctx.is_deprecated(self.type_alias)
44 || self.ctx.is_deprecated_assoc_item(self.type_alias), 45 || self.ctx.is_deprecated_assoc_item(self.type_alias),
45 ) 46 )
46 .detail(detail) 47 .detail(detail);
47 .build();
48 48
49 Some(item) 49 Some(item.build())
50 } 50 }
51 51
52 fn name(&self) -> Option<String> { 52 fn name(&self) -> Option<String> {
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs
index ddcfbd3f3..fa18703e1 100644
--- a/crates/ide_db/src/search.rs
+++ b/crates/ide_db/src/search.rs
@@ -86,6 +86,10 @@ impl SearchScope {
86 SearchScope::new(std::iter::once((file, None)).collect()) 86 SearchScope::new(std::iter::once((file, None)).collect())
87 } 87 }
88 88
89 pub fn file_range(range: FileRange) -> SearchScope {
90 SearchScope::new(std::iter::once((range.file_id, Some(range.range))).collect())
91 }
92
89 pub fn files(files: &[FileId]) -> SearchScope { 93 pub fn files(files: &[FileId]) -> SearchScope {
90 SearchScope::new(files.iter().map(|f| (*f, None)).collect()) 94 SearchScope::new(files.iter().map(|f| (*f, None)).collect())
91 } 95 }
diff --git a/crates/mbe/src/expander.rs b/crates/mbe/src/expander.rs
index 2efff8f52..3197c834c 100644
--- a/crates/mbe/src/expander.rs
+++ b/crates/mbe/src/expander.rs
@@ -5,7 +5,7 @@
5mod matcher; 5mod matcher;
6mod transcriber; 6mod transcriber;
7 7
8use smallvec::SmallVec; 8use rustc_hash::FxHashMap;
9use syntax::SmolStr; 9use syntax::SmolStr;
10 10
11use crate::{ExpandError, ExpandResult}; 11use crate::{ExpandError, ExpandResult};
@@ -96,7 +96,7 @@ pub(crate) fn expand_rules(
96/// many is not a plain `usize`, but an `&[usize]`. 96/// many is not a plain `usize`, but an `&[usize]`.
97#[derive(Debug, Default, Clone, PartialEq, Eq)] 97#[derive(Debug, Default, Clone, PartialEq, Eq)]
98struct Bindings { 98struct Bindings {
99 inner: SmallVec<[(SmolStr, Binding); 4]>, 99 inner: FxHashMap<SmolStr, Binding>,
100} 100}
101 101
102#[derive(Debug, Clone, PartialEq, Eq)] 102#[derive(Debug, Clone, PartialEq, Eq)]
diff --git a/crates/mbe/src/expander/matcher.rs b/crates/mbe/src/expander/matcher.rs
index 9d3d28055..2c69e8968 100644
--- a/crates/mbe/src/expander/matcher.rs
+++ b/crates/mbe/src/expander/matcher.rs
@@ -59,6 +59,8 @@
59//! eof: [a $( a )* a b ·] 59//! eof: [a $( a )* a b ·]
60//! ``` 60//! ```
61 61
62use std::rc::Rc;
63
62use crate::{ 64use crate::{
63 expander::{Binding, Bindings, Fragment}, 65 expander::{Binding, Bindings, Fragment},
64 parser::{Op, OpDelimited, OpDelimitedIter, RepeatKind, Separator}, 66 parser::{Op, OpDelimited, OpDelimitedIter, RepeatKind, Separator},
@@ -76,43 +78,15 @@ impl Bindings {
76 // FIXME: Do we have a better way to represent an empty token ? 78 // FIXME: Do we have a better way to represent an empty token ?
77 // Insert an empty subtree for empty token 79 // Insert an empty subtree for empty token
78 let tt = tt::Subtree::default().into(); 80 let tt = tt::Subtree::default().into();
79 self.inner.push((name.clone(), Binding::Fragment(Fragment::Tokens(tt)))); 81 self.inner.insert(name.clone(), Binding::Fragment(Fragment::Tokens(tt)));
80 } 82 }
81 83
82 fn push_empty(&mut self, name: &SmolStr) { 84 fn push_empty(&mut self, name: &SmolStr) {
83 self.inner.push((name.clone(), Binding::Empty)); 85 self.inner.insert(name.clone(), Binding::Empty);
84 }
85
86 fn push_nested(&mut self, idx: usize, nested: Bindings) -> Result<(), ExpandError> {
87 for (key, value) in nested.inner {
88 if self.get_mut(&key).is_none() {
89 self.inner.push((key.clone(), Binding::Nested(Vec::new())));
90 }
91 match self.get_mut(&key) {
92 Some(Binding::Nested(it)) => {
93 // insert empty nested bindings before this one
94 while it.len() < idx {
95 it.push(Binding::Nested(vec![]));
96 }
97 it.push(value);
98 }
99 _ => {
100 return Err(ExpandError::BindingError(format!(
101 "could not find binding `{}`",
102 key
103 )));
104 }
105 }
106 }
107 Ok(())
108 }
109
110 fn get_mut(&mut self, name: &str) -> Option<&mut Binding> {
111 self.inner.iter_mut().find_map(|(n, b)| if n == name { Some(b) } else { None })
112 } 86 }
113 87
114 fn bindings(&self) -> impl Iterator<Item = &Binding> { 88 fn bindings(&self) -> impl Iterator<Item = &Binding> {
115 self.inner.iter().map(|(_, b)| b) 89 self.inner.values()
116 } 90 }
117} 91}
118 92
@@ -163,6 +137,181 @@ pub(super) fn match_(pattern: &MetaTemplate, input: &tt::Subtree) -> Match {
163} 137}
164 138
165#[derive(Debug, Clone)] 139#[derive(Debug, Clone)]
140enum BindingKind {
141 Empty(SmolStr),
142 Optional(SmolStr),
143 Fragment(SmolStr, Fragment),
144 Nested(usize, usize),
145}
146
147#[derive(Debug, Clone)]
148struct BindingsIdx(usize, usize);
149
150#[derive(Debug, Clone)]
151enum LinkNode<T> {
152 Node(T),
153 Parent { idx: usize, len: usize },
154}
155
156#[derive(Default)]
157struct BindingsBuilder {
158 nodes: Vec<Vec<LinkNode<Rc<BindingKind>>>>,
159 nested: Vec<Vec<LinkNode<usize>>>,
160}
161
162impl BindingsBuilder {
163 fn alloc(&mut self) -> BindingsIdx {
164 let idx = self.nodes.len();
165 self.nodes.push(Vec::new());
166 let nidx = self.nested.len();
167 self.nested.push(Vec::new());
168 BindingsIdx(idx, nidx)
169 }
170
171 fn copy(&mut self, bindings: &BindingsIdx) -> BindingsIdx {
172 let idx = copy_parent(bindings.0, &mut self.nodes);
173 let nidx = copy_parent(bindings.1, &mut self.nested);
174 return BindingsIdx(idx, nidx);
175
176 fn copy_parent<T>(idx: usize, target: &mut Vec<Vec<LinkNode<T>>>) -> usize
177 where
178 T: Clone,
179 {
180 let new_idx = target.len();
181 let len = target[idx].len();
182 if len < 4 {
183 target.push(target[idx].clone())
184 } else {
185 target.push(vec![LinkNode::Parent { idx, len }]);
186 }
187 new_idx
188 }
189 }
190
191 fn push_empty(&mut self, idx: &mut BindingsIdx, var: &SmolStr) {
192 self.nodes[idx.0].push(LinkNode::Node(Rc::new(BindingKind::Empty(var.clone()))));
193 }
194
195 fn push_optional(&mut self, idx: &mut BindingsIdx, var: &SmolStr) {
196 self.nodes[idx.0].push(LinkNode::Node(Rc::new(BindingKind::Optional(var.clone()))));
197 }
198
199 fn push_fragment(&mut self, idx: &mut BindingsIdx, var: &SmolStr, fragment: Fragment) {
200 self.nodes[idx.0]
201 .push(LinkNode::Node(Rc::new(BindingKind::Fragment(var.clone(), fragment))));
202 }
203
204 fn push_nested(&mut self, parent: &mut BindingsIdx, child: &BindingsIdx) {
205 let BindingsIdx(idx, nidx) = self.copy(&child);
206 self.nodes[parent.0].push(LinkNode::Node(Rc::new(BindingKind::Nested(idx, nidx))));
207 }
208
209 fn push_default(&mut self, idx: &mut BindingsIdx) {
210 self.nested[idx.1].push(LinkNode::Node(idx.0));
211 let new_idx = self.nodes.len();
212 self.nodes.push(Vec::new());
213 idx.0 = new_idx;
214 }
215
216 fn build(self, idx: &BindingsIdx) -> Bindings {
217 let mut bindings = Bindings::default();
218 self.build_inner(&mut bindings, &self.nodes[idx.0]);
219 bindings
220 }
221
222 fn build_inner(&self, bindings: &mut Bindings, link_nodes: &Vec<LinkNode<Rc<BindingKind>>>) {
223 let mut nodes = Vec::new();
224 self.collect_nodes(&link_nodes, &mut nodes);
225
226 for cmd in nodes {
227 match &**cmd {
228 BindingKind::Empty(name) => {
229 bindings.push_empty(name);
230 }
231 BindingKind::Optional(name) => {
232 bindings.push_optional(name);
233 }
234 BindingKind::Fragment(name, fragment) => {
235 bindings.inner.insert(name.clone(), Binding::Fragment(fragment.clone()));
236 }
237 BindingKind::Nested(idx, nested_idx) => {
238 let mut nested_nodes = Vec::new();
239 self.collect_nested(*idx, *nested_idx, &mut nested_nodes);
240
241 for (idx, iter) in nested_nodes.into_iter().enumerate() {
242 for (key, value) in &iter.inner {
243 let bindings = bindings
244 .inner
245 .entry(key.clone())
246 .or_insert_with(|| Binding::Nested(Vec::new()));
247
248 if let Binding::Nested(it) = bindings {
249 // insert empty nested bindings before this one
250 while it.len() < idx {
251 it.push(Binding::Nested(Vec::new()));
252 }
253 it.push(value.clone());
254 }
255 }
256 }
257 }
258 }
259 }
260 }
261
262 fn collect_nested_ref<'a>(
263 &'a self,
264 id: usize,
265 len: usize,
266 nested_refs: &mut Vec<&'a Vec<LinkNode<Rc<BindingKind>>>>,
267 ) {
268 self.nested[id].iter().take(len).for_each(|it| match it {
269 LinkNode::Node(id) => nested_refs.push(&self.nodes[*id]),
270 LinkNode::Parent { idx, len } => self.collect_nested_ref(*idx, *len, nested_refs),
271 });
272 }
273
274 fn collect_nested(&self, idx: usize, nested_idx: usize, nested: &mut Vec<Bindings>) {
275 let last = &self.nodes[idx];
276 let mut nested_refs = Vec::new();
277 self.nested[nested_idx].iter().for_each(|it| match *it {
278 LinkNode::Node(idx) => nested_refs.push(&self.nodes[idx]),
279 LinkNode::Parent { idx, len } => self.collect_nested_ref(idx, len, &mut nested_refs),
280 });
281 nested_refs.push(last);
282
283 nested_refs.into_iter().for_each(|iter| {
284 let mut child_bindings = Bindings::default();
285 self.build_inner(&mut child_bindings, &iter);
286 nested.push(child_bindings)
287 })
288 }
289
290 fn collect_nodes_ref<'a>(
291 &'a self,
292 id: usize,
293 len: usize,
294 nodes: &mut Vec<&'a Rc<BindingKind>>,
295 ) {
296 self.nodes[id].iter().take(len).for_each(|it| match it {
297 LinkNode::Node(it) => nodes.push(it),
298 LinkNode::Parent { idx, len } => self.collect_nodes_ref(*idx, *len, nodes),
299 });
300 }
301
302 fn collect_nodes<'a>(
303 &'a self,
304 link_nodes: &'a Vec<LinkNode<Rc<BindingKind>>>,
305 nodes: &mut Vec<&'a Rc<BindingKind>>,
306 ) {
307 link_nodes.into_iter().for_each(|it| match it {
308 LinkNode::Node(it) => nodes.push(it),
309 LinkNode::Parent { idx, len } => self.collect_nodes_ref(*idx, *len, nodes),
310 });
311 }
312}
313
314#[derive(Debug, Clone)]
166struct MatchState<'t> { 315struct MatchState<'t> {
167 /// The position of the "dot" in this matcher 316 /// The position of the "dot" in this matcher
168 dot: OpDelimitedIter<'t>, 317 dot: OpDelimitedIter<'t>,
@@ -187,7 +336,7 @@ struct MatchState<'t> {
187 sep_parsed: Option<usize>, 336 sep_parsed: Option<usize>,
188 337
189 /// Matched meta variables bindings 338 /// Matched meta variables bindings
190 bindings: SmallVec<[Bindings; 4]>, 339 bindings: BindingsIdx,
191 340
192 /// Cached result of meta variable parsing 341 /// Cached result of meta variable parsing
193 meta_result: Option<(TtIter<'t>, ExpandResult<Option<Fragment>>)>, 342 meta_result: Option<(TtIter<'t>, ExpandResult<Option<Fragment>>)>,
@@ -218,6 +367,7 @@ fn match_loop_inner<'t>(
218 src: TtIter<'t>, 367 src: TtIter<'t>,
219 stack: &[TtIter<'t>], 368 stack: &[TtIter<'t>],
220 res: &mut Match, 369 res: &mut Match,
370 bindings_builder: &mut BindingsBuilder,
221 cur_items: &mut SmallVec<[MatchState<'t>; 1]>, 371 cur_items: &mut SmallVec<[MatchState<'t>; 1]>,
222 bb_items: &mut SmallVec<[MatchState<'t>; 1]>, 372 bb_items: &mut SmallVec<[MatchState<'t>; 1]>,
223 next_items: &mut Vec<MatchState<'t>>, 373 next_items: &mut Vec<MatchState<'t>>,
@@ -251,12 +401,10 @@ fn match_loop_inner<'t>(
251 if item.sep_parsed.is_none() { 401 if item.sep_parsed.is_none() {
252 // Get the `up` matcher 402 // Get the `up` matcher
253 let mut new_pos = *item.up.clone().unwrap(); 403 let mut new_pos = *item.up.clone().unwrap();
404 new_pos.bindings = bindings_builder.copy(&new_pos.bindings);
254 // Add matches from this repetition to the `matches` of `up` 405 // Add matches from this repetition to the `matches` of `up`
255 if let Some(bindings) = new_pos.bindings.last_mut() { 406 bindings_builder.push_nested(&mut new_pos.bindings, &item.bindings);
256 for (i, b) in item.bindings.iter_mut().enumerate() { 407
257 bindings.push_nested(i, b.clone()).unwrap();
258 }
259 }
260 // Move the "dot" past the repetition in `up` 408 // Move the "dot" past the repetition in `up`
261 new_pos.dot.next(); 409 new_pos.dot.next();
262 new_pos.is_error = new_pos.is_error || item.is_error; 410 new_pos.is_error = new_pos.is_error || item.is_error;
@@ -280,7 +428,7 @@ fn match_loop_inner<'t>(
280 else if item.sep_kind != Some(RepeatKind::ZeroOrOne) { 428 else if item.sep_kind != Some(RepeatKind::ZeroOrOne) {
281 item.dot = item.dot.reset(); 429 item.dot = item.dot.reset();
282 item.sep_parsed = None; 430 item.sep_parsed = None;
283 item.bindings.push(Bindings::default()); 431 bindings_builder.push_default(&mut item.bindings);
284 cur_items.push(item); 432 cur_items.push(item);
285 } 433 }
286 } else { 434 } else {
@@ -298,12 +446,12 @@ fn match_loop_inner<'t>(
298 OpDelimited::Op(Op::Repeat { tokens, kind, separator }) => { 446 OpDelimited::Op(Op::Repeat { tokens, kind, separator }) => {
299 if matches!(kind, RepeatKind::ZeroOrMore | RepeatKind::ZeroOrOne) { 447 if matches!(kind, RepeatKind::ZeroOrMore | RepeatKind::ZeroOrOne) {
300 let mut new_item = item.clone(); 448 let mut new_item = item.clone();
449 new_item.bindings = bindings_builder.copy(&new_item.bindings);
301 new_item.dot.next(); 450 new_item.dot.next();
302 let mut vars = Vec::new(); 451 let mut vars = Vec::new();
303 let bindings = new_item.bindings.last_mut().unwrap();
304 collect_vars(&mut vars, tokens); 452 collect_vars(&mut vars, tokens);
305 for var in vars { 453 for var in vars {
306 bindings.push_empty(&var); 454 bindings_builder.push_empty(&mut new_item.bindings, &var);
307 } 455 }
308 cur_items.push(new_item); 456 cur_items.push(new_item);
309 } 457 }
@@ -314,7 +462,7 @@ fn match_loop_inner<'t>(
314 sep: separator.clone(), 462 sep: separator.clone(),
315 sep_kind: Some(*kind), 463 sep_kind: Some(*kind),
316 sep_parsed: None, 464 sep_parsed: None,
317 bindings: smallvec![Bindings::default()], 465 bindings: bindings_builder.alloc(),
318 meta_result: None, 466 meta_result: None,
319 is_error: false, 467 is_error: false,
320 }) 468 })
@@ -339,7 +487,7 @@ fn match_loop_inner<'t>(
339 item.meta_result = Some((fork, match_res)); 487 item.meta_result = Some((fork, match_res));
340 try_push!(bb_items, item); 488 try_push!(bb_items, item);
341 } else { 489 } else {
342 item.bindings.last_mut().unwrap().push_optional(name); 490 bindings_builder.push_optional(&mut item.bindings, &name);
343 item.dot.next(); 491 item.dot.next();
344 cur_items.push(item); 492 cur_items.push(item);
345 } 493 }
@@ -348,11 +496,11 @@ fn match_loop_inner<'t>(
348 res.add_err(err); 496 res.add_err(err);
349 match match_res.value { 497 match match_res.value {
350 Some(fragment) => { 498 Some(fragment) => {
351 item.bindings 499 bindings_builder.push_fragment(
352 .last_mut() 500 &mut item.bindings,
353 .unwrap() 501 &name,
354 .inner 502 fragment,
355 .push((name.clone(), Binding::Fragment(fragment))); 503 );
356 } 504 }
357 _ => {} 505 _ => {}
358 } 506 }
@@ -394,6 +542,8 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match {
394 let mut res = Match::default(); 542 let mut res = Match::default();
395 let mut error_reover_item = None; 543 let mut error_reover_item = None;
396 544
545 let mut bindings_builder = BindingsBuilder::default();
546
397 let mut cur_items = smallvec![MatchState { 547 let mut cur_items = smallvec![MatchState {
398 dot: pattern.iter_delimited(None), 548 dot: pattern.iter_delimited(None),
399 stack: Default::default(), 549 stack: Default::default(),
@@ -401,7 +551,7 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match {
401 sep: None, 551 sep: None,
402 sep_kind: None, 552 sep_kind: None,
403 sep_parsed: None, 553 sep_parsed: None,
404 bindings: smallvec![Bindings::default()], 554 bindings: bindings_builder.alloc(),
405 is_error: false, 555 is_error: false,
406 meta_result: None, 556 meta_result: None,
407 }]; 557 }];
@@ -419,6 +569,7 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match {
419 src.clone(), 569 src.clone(),
420 &stack, 570 &stack,
421 &mut res, 571 &mut res,
572 &mut bindings_builder,
422 &mut cur_items, 573 &mut cur_items,
423 &mut bb_items, 574 &mut bb_items,
424 &mut next_items, 575 &mut next_items,
@@ -428,9 +579,9 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match {
428 stdx::always!(cur_items.is_empty()); 579 stdx::always!(cur_items.is_empty());
429 580
430 if error_items.len() > 0 { 581 if error_items.len() > 0 {
431 error_reover_item = error_items.pop(); 582 error_reover_item = error_items.pop().map(|it| it.bindings);
432 } else if eof_items.len() > 0 { 583 } else if eof_items.len() > 0 {
433 error_reover_item = Some(eof_items[0].clone()); 584 error_reover_item = Some(eof_items[0].bindings.clone());
434 } 585 }
435 586
436 // We need to do some post processing after the `match_loop_inner`. 587 // We need to do some post processing after the `match_loop_inner`.
@@ -440,11 +591,11 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match {
440 if eof_items.len() == 1 { 591 if eof_items.len() == 1 {
441 // remove all errors, because it is the correct answer ! 592 // remove all errors, because it is the correct answer !
442 res = Match::default(); 593 res = Match::default();
443 res.bindings = eof_items[0].bindings[0].clone(); 594 res.bindings = bindings_builder.build(&eof_items[0].bindings);
444 } else { 595 } else {
445 // Error recovery 596 // Error recovery
446 if error_reover_item.is_some() { 597 if error_reover_item.is_some() {
447 res.bindings = error_reover_item.unwrap().bindings[0].clone(); 598 res.bindings = bindings_builder.build(&error_reover_item.unwrap());
448 } 599 }
449 res.add_err(ExpandError::UnexpectedToken); 600 res.add_err(ExpandError::UnexpectedToken);
450 } 601 }
@@ -467,8 +618,8 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match {
467 } 618 }
468 res.add_err(err!("leftover tokens")); 619 res.add_err(err!("leftover tokens"));
469 620
470 if let Some(mut error_reover_item) = error_reover_item { 621 if let Some(error_reover_item) = error_reover_item {
471 res.bindings = error_reover_item.bindings.remove(0); 622 res.bindings = bindings_builder.build(&error_reover_item);
472 } 623 }
473 return res; 624 return res;
474 } 625 }
@@ -494,12 +645,13 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match {
494 645
495 if let Some(OpDelimited::Op(Op::Var { name, .. })) = item.dot.peek() { 646 if let Some(OpDelimited::Op(Op::Var { name, .. })) = item.dot.peek() {
496 let (iter, match_res) = item.meta_result.take().unwrap(); 647 let (iter, match_res) = item.meta_result.take().unwrap();
497 let bindings = item.bindings.last_mut().unwrap();
498 match match_res.value { 648 match match_res.value {
499 Some(fragment) => { 649 Some(fragment) => {
500 bindings.inner.push((name.clone(), Binding::Fragment(fragment))); 650 bindings_builder.push_fragment(&mut item.bindings, &name, fragment);
651 }
652 None if match_res.err.is_none() => {
653 bindings_builder.push_optional(&mut item.bindings, &name);
501 } 654 }
502 None if match_res.err.is_none() => bindings.push_optional(name),
503 _ => {} 655 _ => {}
504 } 656 }
505 if let Some(err) = match_res.err { 657 if let Some(err) = match_res.err {
diff --git a/crates/mbe/src/expander/transcriber.rs b/crates/mbe/src/expander/transcriber.rs
index ad9953a7d..dd7fa97d7 100644
--- a/crates/mbe/src/expander/transcriber.rs
+++ b/crates/mbe/src/expander/transcriber.rs
@@ -2,7 +2,7 @@
2//! `$ident => foo`, interpolates variables in the template, to get `fn foo() {}` 2//! `$ident => foo`, interpolates variables in the template, to get `fn foo() {}`
3 3
4use syntax::SmolStr; 4use syntax::SmolStr;
5use tt::Delimiter; 5use tt::{Delimiter, Subtree};
6 6
7use super::ExpandResult; 7use super::ExpandResult;
8use crate::{ 8use crate::{
@@ -13,17 +13,13 @@ use crate::{
13 13
14impl Bindings { 14impl Bindings {
15 fn contains(&self, name: &str) -> bool { 15 fn contains(&self, name: &str) -> bool {
16 self.inner.iter().any(|(n, _)| n == name) 16 self.inner.contains_key(name)
17 } 17 }
18 18
19 fn get(&self, name: &str, nesting: &mut [NestingState]) -> Result<&Fragment, ExpandError> { 19 fn get(&self, name: &str, nesting: &mut [NestingState]) -> Result<&Fragment, ExpandError> {
20 let mut b: &Binding = self 20 let mut b: &Binding = self.inner.get(name).ok_or_else(|| {
21 .inner 21 ExpandError::BindingError(format!("could not find binding `{}`", name))
22 .iter() 22 })?;
23 .find_map(|(n, b)| if n == name { Some(b) } else { None })
24 .ok_or_else(|| {
25 ExpandError::BindingError(format!("could not find binding `{}`", name))
26 })?;
27 for nesting_state in nesting.iter_mut() { 23 for nesting_state in nesting.iter_mut() {
28 nesting_state.hit = true; 24 nesting_state.hit = true;
29 b = match b { 25 b = match b {
@@ -179,7 +175,10 @@ fn expand_repeat(
179 counter += 1; 175 counter += 1;
180 if counter == limit { 176 if counter == limit {
181 log::warn!("expand_tt in repeat pattern exceed limit => {:#?}\n{:#?}", template, ctx); 177 log::warn!("expand_tt in repeat pattern exceed limit => {:#?}\n{:#?}", template, ctx);
182 break; 178 return ExpandResult {
179 value: Fragment::Tokens(Subtree::default().into()),
180 err: Some(ExpandError::Other("Expand exceed limit".to_string())),
181 };
183 } 182 }
184 183
185 if e.is_some() { 184 if e.is_some() {
diff --git a/crates/parser/src/grammar.rs b/crates/parser/src/grammar.rs
index 6159d064c..6c0e22722 100644
--- a/crates/parser/src/grammar.rs
+++ b/crates/parser/src/grammar.rs
@@ -18,7 +18,7 @@
18//! // fn foo() {} 18//! // fn foo() {}
19//! ``` 19//! ```
20//! 20//!
21//! After adding a new inline-test, run `cargo xtask codegen` to 21//! After adding a new inline-test, run `cargo test -p xtask` to
22//! extract it as a standalone text-fixture into 22//! extract it as a standalone text-fixture into
23//! `crates/syntax/test_data/parser/`, and run `cargo test` once to 23//! `crates/syntax/test_data/parser/`, and run `cargo test` once to
24//! create the "gold" value. 24//! create the "gold" value.
diff --git a/crates/rust-analyzer/build.rs b/crates/rust-analyzer/build.rs
index 5ae76ba30..999dc5928 100644
--- a/crates/rust-analyzer/build.rs
+++ b/crates/rust-analyzer/build.rs
@@ -39,8 +39,7 @@ fn set_rerun() {
39} 39}
40 40
41fn rev() -> Option<String> { 41fn rev() -> Option<String> {
42 let output = Command::new("git").args(&["rev-parse", "HEAD"]).output().ok()?; 42 let output = Command::new("git").args(&["describe", "--tags"]).output().ok()?;
43 let stdout = String::from_utf8(output.stdout).ok()?; 43 let stdout = String::from_utf8(output.stdout).ok()?;
44 let short_hash = stdout.get(0..7)?; 44 Some(stdout)
45 Some(short_hash.to_owned())
46} 45}
diff --git a/crates/rust-analyzer/src/bin/flags.rs b/crates/rust-analyzer/src/bin/flags.rs
index 3a7caaf3f..d8987633d 100644
--- a/crates/rust-analyzer/src/bin/flags.rs
+++ b/crates/rust-analyzer/src/bin/flags.rs
@@ -65,6 +65,8 @@ xflags::xflags! {
65 optional -o, --only path: String 65 optional -o, --only path: String
66 /// Also analyze all dependencies. 66 /// Also analyze all dependencies.
67 optional --with-deps 67 optional --with-deps
68 /// Don't load sysroot crates (`std`, `core` & friends).
69 optional --no-sysroot
68 70
69 /// Load OUT_DIR values by running `cargo check` before analysis. 71 /// Load OUT_DIR values by running `cargo check` before analysis.
70 optional --load-output-dirs 72 optional --load-output-dirs
@@ -176,6 +178,7 @@ pub struct AnalysisStats {
176 pub memory_usage: bool, 178 pub memory_usage: bool,
177 pub only: Option<String>, 179 pub only: Option<String>,
178 pub with_deps: bool, 180 pub with_deps: bool,
181 pub no_sysroot: bool,
179 pub load_output_dirs: bool, 182 pub load_output_dirs: bool,
180 pub with_proc_macro: bool, 183 pub with_proc_macro: bool,
181} 184}
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs
index 288847980..a0b611bff 100644
--- a/crates/rust-analyzer/src/bin/main.rs
+++ b/crates/rust-analyzer/src/bin/main.rs
@@ -74,6 +74,7 @@ fn try_main() -> Result<()> {
74 memory_usage: cmd.memory_usage, 74 memory_usage: cmd.memory_usage,
75 only: cmd.only, 75 only: cmd.only,
76 with_deps: cmd.with_deps, 76 with_deps: cmd.with_deps,
77 no_sysroot: cmd.no_sysroot,
77 path: cmd.path, 78 path: cmd.path,
78 load_output_dirs: cmd.load_output_dirs, 79 load_output_dirs: cmd.load_output_dirs,
79 with_proc_macro: cmd.with_proc_macro, 80 with_proc_macro: cmd.with_proc_macro,
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index ad0759bda..9c59e7ee4 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -12,13 +12,14 @@ use hir::{
12 AssocItem, Crate, HasSource, HirDisplay, ModuleDef, 12 AssocItem, Crate, HasSource, HirDisplay, ModuleDef,
13}; 13};
14use hir_def::FunctionId; 14use hir_def::FunctionId;
15use hir_ty::{Ty, TypeWalk}; 15use hir_ty::TypeWalk;
16use ide_db::base_db::{ 16use ide_db::base_db::{
17 salsa::{self, ParallelDatabase}, 17 salsa::{self, ParallelDatabase},
18 SourceDatabaseExt, 18 SourceDatabaseExt,
19}; 19};
20use itertools::Itertools; 20use itertools::Itertools;
21use oorandom::Rand32; 21use oorandom::Rand32;
22use project_model::CargoConfig;
22use rayon::prelude::*; 23use rayon::prelude::*;
23use rustc_hash::FxHashSet; 24use rustc_hash::FxHashSet;
24use stdx::format_to; 25use stdx::format_to;
@@ -46,6 +47,7 @@ pub struct AnalysisStatsCmd {
46 pub memory_usage: bool, 47 pub memory_usage: bool,
47 pub only: Option<String>, 48 pub only: Option<String>,
48 pub with_deps: bool, 49 pub with_deps: bool,
50 pub no_sysroot: bool,
49 pub path: PathBuf, 51 pub path: PathBuf,
50 pub load_output_dirs: bool, 52 pub load_output_dirs: bool,
51 pub with_proc_macro: bool, 53 pub with_proc_macro: bool,
@@ -59,7 +61,8 @@ impl AnalysisStatsCmd {
59 }; 61 };
60 62
61 let mut db_load_sw = self.stop_watch(); 63 let mut db_load_sw = self.stop_watch();
62 let cargo_config = Default::default(); 64 let mut cargo_config = CargoConfig::default();
65 cargo_config.no_sysroot = self.no_sysroot;
63 let load_cargo_config = LoadCargoConfig { 66 let load_cargo_config = LoadCargoConfig {
64 load_out_dirs_from_check: self.load_output_dirs, 67 load_out_dirs_from_check: self.load_output_dirs,
65 with_proc_macro: self.with_proc_macro, 68 with_proc_macro: self.with_proc_macro,
@@ -187,12 +190,12 @@ impl AnalysisStatsCmd {
187 for (expr_id, _) in body.exprs.iter() { 190 for (expr_id, _) in body.exprs.iter() {
188 let ty = &inference_result[expr_id]; 191 let ty = &inference_result[expr_id];
189 num_exprs += 1; 192 num_exprs += 1;
190 if let Ty::Unknown = ty { 193 if ty.is_unknown() {
191 num_exprs_unknown += 1; 194 num_exprs_unknown += 1;
192 } else { 195 } else {
193 let mut is_partially_unknown = false; 196 let mut is_partially_unknown = false;
194 ty.walk(&mut |ty| { 197 ty.walk(&mut |ty| {
195 if let Ty::Unknown = ty { 198 if ty.is_unknown() {
196 is_partially_unknown = true; 199 is_partially_unknown = true;
197 } 200 }
198 }); 201 });
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 6cc433cb8..706a39dab 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -555,7 +555,7 @@ pub(crate) fn handle_runnables(
555 if should_skip_target(&runnable, cargo_spec.as_ref()) { 555 if should_skip_target(&runnable, cargo_spec.as_ref()) {
556 continue; 556 continue;
557 } 557 }
558 let mut runnable = to_proto::runnable(&snap, file_id, runnable)?; 558 let mut runnable = to_proto::runnable(&snap, runnable)?;
559 if expect_test { 559 if expect_test {
560 runnable.label = format!("{} + expect", runnable.label); 560 runnable.label = format!("{} + expect", runnable.label);
561 runnable.args.expect_test = Some(true); 561 runnable.args.expect_test = Some(true);
@@ -607,6 +607,24 @@ pub(crate) fn handle_runnables(
607 Ok(res) 607 Ok(res)
608} 608}
609 609
610pub(crate) fn handle_related_tests(
611 snap: GlobalStateSnapshot,
612 params: lsp_types::TextDocumentPositionParams,
613) -> Result<Vec<lsp_ext::TestInfo>> {
614 let _p = profile::span("handle_related_tests");
615 let position = from_proto::file_position(&snap, params)?;
616
617 let tests = snap.analysis.related_tests(position, None)?;
618 let mut res = Vec::new();
619 for it in tests {
620 if let Ok(runnable) = to_proto::runnable(&snap, it) {
621 res.push(lsp_ext::TestInfo { runnable })
622 }
623 }
624
625 Ok(res)
626}
627
610pub(crate) fn handle_completion( 628pub(crate) fn handle_completion(
611 snap: GlobalStateSnapshot, 629 snap: GlobalStateSnapshot,
612 params: lsp_types::CompletionParams, 630 params: lsp_types::CompletionParams,
@@ -772,7 +790,7 @@ pub(crate) fn handle_hover(
772 contents: HoverContents::Markup(to_proto::markup_content(info.info.markup)), 790 contents: HoverContents::Markup(to_proto::markup_content(info.info.markup)),
773 range: Some(range), 791 range: Some(range),
774 }, 792 },
775 actions: prepare_hover_actions(&snap, position.file_id, &info.info.actions), 793 actions: prepare_hover_actions(&snap, &info.info.actions),
776 }; 794 };
777 795
778 Ok(Some(hover)) 796 Ok(Some(hover))
@@ -1440,17 +1458,16 @@ fn show_impl_command_link(
1440 1458
1441fn runnable_action_links( 1459fn runnable_action_links(
1442 snap: &GlobalStateSnapshot, 1460 snap: &GlobalStateSnapshot,
1443 file_id: FileId,
1444 runnable: Runnable, 1461 runnable: Runnable,
1445) -> Option<lsp_ext::CommandLinkGroup> { 1462) -> Option<lsp_ext::CommandLinkGroup> {
1446 let cargo_spec = CargoTargetSpec::for_file(&snap, file_id).ok()?; 1463 let cargo_spec = CargoTargetSpec::for_file(&snap, runnable.nav.file_id).ok()?;
1447 let hover_config = snap.config.hover(); 1464 let hover_config = snap.config.hover();
1448 if !hover_config.runnable() || should_skip_target(&runnable, cargo_spec.as_ref()) { 1465 if !hover_config.runnable() || should_skip_target(&runnable, cargo_spec.as_ref()) {
1449 return None; 1466 return None;
1450 } 1467 }
1451 1468
1452 let action: &'static _ = runnable.action(); 1469 let action: &'static _ = runnable.action();
1453 to_proto::runnable(snap, file_id, runnable).ok().map(|r| { 1470 to_proto::runnable(snap, runnable).ok().map(|r| {
1454 let mut group = lsp_ext::CommandLinkGroup::default(); 1471 let mut group = lsp_ext::CommandLinkGroup::default();
1455 1472
1456 if hover_config.run { 1473 if hover_config.run {
@@ -1489,7 +1506,6 @@ fn goto_type_action_links(
1489 1506
1490fn prepare_hover_actions( 1507fn prepare_hover_actions(
1491 snap: &GlobalStateSnapshot, 1508 snap: &GlobalStateSnapshot,
1492 file_id: FileId,
1493 actions: &[HoverAction], 1509 actions: &[HoverAction],
1494) -> Vec<lsp_ext::CommandLinkGroup> { 1510) -> Vec<lsp_ext::CommandLinkGroup> {
1495 if snap.config.hover().none() || !snap.config.hover_actions() { 1511 if snap.config.hover().none() || !snap.config.hover_actions() {
@@ -1500,7 +1516,7 @@ fn prepare_hover_actions(
1500 .iter() 1516 .iter()
1501 .filter_map(|it| match it { 1517 .filter_map(|it| match it {
1502 HoverAction::Implementation(position) => show_impl_command_link(snap, position), 1518 HoverAction::Implementation(position) => show_impl_command_link(snap, position),
1503 HoverAction::Runnable(r) => runnable_action_links(snap, file_id, r.clone()), 1519 HoverAction::Runnable(r) => runnable_action_links(snap, r.clone()),
1504 HoverAction::GoToType(targets) => goto_type_action_links(snap, targets), 1520 HoverAction::GoToType(targets) => goto_type_action_links(snap, targets),
1505 }) 1521 })
1506 .collect() 1522 .collect()
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs
index 0d2c8f7ff..efcdcd1d9 100644
--- a/crates/rust-analyzer/src/lsp_ext.rs
+++ b/crates/rust-analyzer/src/lsp_ext.rs
@@ -177,6 +177,19 @@ pub struct CargoRunnable {
177 pub expect_test: Option<bool>, 177 pub expect_test: Option<bool>,
178} 178}
179 179
180pub enum RelatedTests {}
181
182impl Request for RelatedTests {
183 type Params = lsp_types::TextDocumentPositionParams;
184 type Result = Vec<TestInfo>;
185 const METHOD: &'static str = "rust-analyzer/relatedTests";
186}
187
188#[derive(Debug, Deserialize, Serialize)]
189pub struct TestInfo {
190 pub runnable: Runnable,
191}
192
180pub enum InlayHints {} 193pub enum InlayHints {}
181 194
182impl Request for InlayHints { 195impl Request for InlayHints {
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index f0cb309e4..984790d35 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -500,6 +500,7 @@ impl GlobalState {
500 .on::<lsp_ext::ExpandMacro>(handlers::handle_expand_macro) 500 .on::<lsp_ext::ExpandMacro>(handlers::handle_expand_macro)
501 .on::<lsp_ext::ParentModule>(handlers::handle_parent_module) 501 .on::<lsp_ext::ParentModule>(handlers::handle_parent_module)
502 .on::<lsp_ext::Runnables>(handlers::handle_runnables) 502 .on::<lsp_ext::Runnables>(handlers::handle_runnables)
503 .on::<lsp_ext::RelatedTests>(handlers::handle_related_tests)
503 .on::<lsp_ext::InlayHints>(handlers::handle_inlay_hints) 504 .on::<lsp_ext::InlayHints>(handlers::handle_inlay_hints)
504 .on::<lsp_ext::CodeActionRequest>(handlers::handle_code_action) 505 .on::<lsp_ext::CodeActionRequest>(handlers::handle_code_action)
505 .on::<lsp_ext::CodeActionResolveRequest>(handlers::handle_code_action_resolve) 506 .on::<lsp_ext::CodeActionResolveRequest>(handlers::handle_code_action_resolve)
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index a9846fa70..d415ed4d3 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -6,9 +6,10 @@ use std::{
6 6
7use ide::{ 7use ide::{
8 Annotation, AnnotationKind, Assist, AssistKind, CallInfo, CompletionItem, CompletionItemKind, 8 Annotation, AnnotationKind, Assist, AssistKind, CallInfo, CompletionItem, CompletionItemKind,
9 Documentation, FileId, FileRange, FileSystemEdit, Fold, FoldKind, Highlight, HlMod, HlPunct, 9 CompletionRelevance, Documentation, FileId, FileRange, FileSystemEdit, Fold, FoldKind,
10 HlRange, HlTag, Indel, InlayHint, InlayKind, InsertTextFormat, Markup, NavigationTarget, 10 Highlight, HlMod, HlPunct, HlRange, HlTag, Indel, InlayHint, InlayKind, InsertTextFormat,
11 ReferenceAccess, RenameError, Runnable, Severity, SourceChange, TextEdit, TextRange, TextSize, 11 Markup, NavigationTarget, ReferenceAccess, RenameError, Runnable, Severity, SourceChange,
12 TextEdit, TextRange, TextSize,
12}; 13};
13use ide_db::SymbolKind; 14use ide_db::SymbolKind;
14use itertools::Itertools; 15use itertools::Itertools;
@@ -213,12 +214,22 @@ pub(crate) fn completion_item(
213 ..Default::default() 214 ..Default::default()
214 }; 215 };
215 216
216 if item.relevance().is_relevant() { 217 fn set_score(res: &mut lsp_types::CompletionItem, relevance: CompletionRelevance) {
217 lsp_item.preselect = Some(true); 218 if relevance.is_relevant() {
218 // HACK: sort preselect items first 219 res.preselect = Some(true);
219 lsp_item.sort_text = Some(format!(" {}", item.label())); 220 }
221 // The relevance needs to be inverted to come up with a sort score
222 // because the client will sort ascending.
223 let sort_score = relevance.score() ^ 0xFF_FF_FF_FF;
224 // Zero pad the string to ensure values can be properly sorted
225 // by the client. Hex format is used because it is easier to
226 // visually compare very large values, which the sort text
227 // tends to be since it is the opposite of the score.
228 res.sort_text = Some(format!("{:08x}", sort_score));
220 } 229 }
221 230
231 set_score(&mut lsp_item, item.relevance());
232
222 if item.deprecated() { 233 if item.deprecated() {
223 lsp_item.tags = Some(vec![lsp_types::CompletionItemTag::Deprecated]) 234 lsp_item.tags = Some(vec![lsp_types::CompletionItemTag::Deprecated])
224 } 235 }
@@ -228,10 +239,9 @@ pub(crate) fn completion_item(
228 } 239 }
229 240
230 let mut res = match item.ref_match() { 241 let mut res = match item.ref_match() {
231 Some(mutability) => { 242 Some((mutability, relevance)) => {
232 let mut lsp_item_with_ref = lsp_item.clone(); 243 let mut lsp_item_with_ref = lsp_item.clone();
233 lsp_item.preselect = Some(true); 244 set_score(&mut lsp_item_with_ref, relevance);
234 lsp_item.sort_text = Some(format!(" {}", item.label()));
235 lsp_item_with_ref.label = 245 lsp_item_with_ref.label =
236 format!("&{}{}", mutability.as_keyword_for_ref(), lsp_item_with_ref.label); 246 format!("&{}{}", mutability.as_keyword_for_ref(), lsp_item_with_ref.label);
237 if let Some(lsp_types::CompletionTextEdit::Edit(it)) = &mut lsp_item_with_ref.text_edit 247 if let Some(lsp_types::CompletionTextEdit::Edit(it)) = &mut lsp_item_with_ref.text_edit
@@ -474,7 +484,8 @@ pub(crate) fn folding_range(
474 let kind = match fold.kind { 484 let kind = match fold.kind {
475 FoldKind::Comment => Some(lsp_types::FoldingRangeKind::Comment), 485 FoldKind::Comment => Some(lsp_types::FoldingRangeKind::Comment),
476 FoldKind::Imports => Some(lsp_types::FoldingRangeKind::Imports), 486 FoldKind::Imports => Some(lsp_types::FoldingRangeKind::Imports),
477 FoldKind::Mods | FoldKind::Block | FoldKind::ArgList | FoldKind::Region => None, 487 FoldKind::Region => Some(lsp_types::FoldingRangeKind::Region),
488 FoldKind::Mods | FoldKind::Block | FoldKind::ArgList => None,
478 }; 489 };
479 490
480 let range = range(line_index, fold.range); 491 let range = range(line_index, fold.range);
@@ -828,11 +839,10 @@ pub(crate) fn resolved_code_action(
828 839
829pub(crate) fn runnable( 840pub(crate) fn runnable(
830 snap: &GlobalStateSnapshot, 841 snap: &GlobalStateSnapshot,
831 file_id: FileId,
832 runnable: Runnable, 842 runnable: Runnable,
833) -> Result<lsp_ext::Runnable> { 843) -> Result<lsp_ext::Runnable> {
834 let config = snap.config.runnables(); 844 let config = snap.config.runnables();
835 let spec = CargoTargetSpec::for_file(snap, file_id)?; 845 let spec = CargoTargetSpec::for_file(snap, runnable.nav.file_id)?;
836 let workspace_root = spec.as_ref().map(|it| it.workspace_root.clone()); 846 let workspace_root = spec.as_ref().map(|it| it.workspace_root.clone());
837 let target = spec.as_ref().map(|s| s.target.clone()); 847 let target = spec.as_ref().map(|s| s.target.clone());
838 let (cargo_args, executable_args) = 848 let (cargo_args, executable_args) =
@@ -865,7 +875,7 @@ pub(crate) fn code_lens(
865 let annotation_range = range(&line_index, annotation.range); 875 let annotation_range = range(&line_index, annotation.range);
866 876
867 let action = run.action(); 877 let action = run.action();
868 let r = runnable(&snap, run.nav.file_id, run)?; 878 let r = runnable(&snap, run)?;
869 879
870 let command = if debug { 880 let command = if debug {
871 command::debug_single(&r) 881 command::debug_single(&r)
@@ -1107,13 +1117,13 @@ mod tests {
1107 ( 1117 (
1108 "&arg", 1118 "&arg",
1109 Some( 1119 Some(
1110 " arg", 1120 "fffffffa",
1111 ), 1121 ),
1112 ), 1122 ),
1113 ( 1123 (
1114 "arg", 1124 "arg",
1115 Some( 1125 Some(
1116 " arg", 1126 "fffffffd",
1117 ), 1127 ),
1118 ), 1128 ),
1119 ] 1129 ]
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
index 70ba8adb4..05a6b0b25 100644
--- a/crates/syntax/src/ast/make.rs
+++ b/crates/syntax/src/ast/make.rs
@@ -222,6 +222,9 @@ pub fn expr_if(
222 }; 222 };
223 expr_from_text(&format!("if {} {} {}", condition, then_branch, else_branch)) 223 expr_from_text(&format!("if {} {} {}", condition, then_branch, else_branch))
224} 224}
225pub fn expr_for_loop(pat: ast::Pat, expr: ast::Expr, block: ast::BlockExpr) -> ast::Expr {
226 expr_from_text(&format!("for {} in {} {}", pat, expr, block))
227}
225pub fn expr_prefix(op: SyntaxKind, expr: ast::Expr) -> ast::Expr { 228pub fn expr_prefix(op: SyntaxKind, expr: ast::Expr) -> ast::Expr {
226 let token = token(op); 229 let token = token(op);
227 expr_from_text(&format!("{}{}", token, expr)) 230 expr_from_text(&format!("{}{}", token, expr))
diff --git a/crates/syntax/src/parsing/text_tree_sink.rs b/crates/syntax/src/parsing/text_tree_sink.rs
index d5ddc076f..bb10f20c9 100644
--- a/crates/syntax/src/parsing/text_tree_sink.rs
+++ b/crates/syntax/src/parsing/text_tree_sink.rs
@@ -147,8 +147,8 @@ fn n_attached_trivias<'a>(
147 trivias: impl Iterator<Item = (SyntaxKind, &'a str)>, 147 trivias: impl Iterator<Item = (SyntaxKind, &'a str)>,
148) -> usize { 148) -> usize {
149 match kind { 149 match kind {
150 MACRO_CALL | MACRO_RULES | CONST | TYPE_ALIAS | STRUCT | ENUM | VARIANT | FN | TRAIT 150 MACRO_CALL | MACRO_RULES | CONST | TYPE_ALIAS | STRUCT | UNION | ENUM | VARIANT | FN
151 | MODULE | RECORD_FIELD | STATIC | USE => { 151 | TRAIT | MODULE | RECORD_FIELD | STATIC | USE => {
152 let mut res = 0; 152 let mut res = 0;
153 let mut trivias = trivias.enumerate().peekable(); 153 let mut trivias = trivias.enumerate().peekable();
154 154
diff --git a/crates/tt/src/lib.rs b/crates/tt/src/lib.rs
index 8301dc28a..9d9a01e30 100644
--- a/crates/tt/src/lib.rs
+++ b/crates/tt/src/lib.rs
@@ -227,6 +227,53 @@ impl Subtree {
227 } 227 }
228} 228}
229 229
230impl Subtree {
231 /// A simple line string used for debugging
232 pub fn as_debug_string(&self) -> String {
233 let delim = match self.delimiter_kind() {
234 Some(DelimiterKind::Brace) => ("{", "}"),
235 Some(DelimiterKind::Bracket) => ("[", "]"),
236 Some(DelimiterKind::Parenthesis) => ("(", ")"),
237 None => (" ", " "),
238 };
239
240 let mut res = String::new();
241 res.push_str(delim.0);
242 let mut iter = self.token_trees.iter();
243 let mut last = None;
244 while let Some(child) = iter.next() {
245 let s = match child {
246 TokenTree::Leaf(it) => {
247 let s = match it {
248 Leaf::Literal(it) => it.text.to_string(),
249 Leaf::Punct(it) => it.char.to_string(),
250 Leaf::Ident(it) => it.text.to_string(),
251 };
252 match (it, last) {
253 (Leaf::Ident(_), Some(&TokenTree::Leaf(Leaf::Ident(_)))) => {
254 " ".to_string() + &s
255 }
256 (Leaf::Punct(_), Some(&TokenTree::Leaf(Leaf::Punct(punct)))) => {
257 if punct.spacing == Spacing::Alone {
258 " ".to_string() + &s
259 } else {
260 s
261 }
262 }
263 _ => s,
264 }
265 }
266 TokenTree::Subtree(it) => it.as_debug_string(),
267 };
268 res.push_str(&s);
269 last = Some(child);
270 }
271
272 res.push_str(delim.1);
273 res
274 }
275}
276
230pub mod buffer; 277pub mod buffer;
231 278
232#[derive(Debug, PartialEq, Eq, Clone)] 279#[derive(Debug, PartialEq, Eq, Clone)]