diff options
Diffstat (limited to 'crates')
69 files changed, 9208 insertions, 1770 deletions
diff --git a/crates/base_db/src/change.rs b/crates/base_db/src/change.rs index 043e03bba..04e294e41 100644 --- a/crates/base_db/src/change.rs +++ b/crates/base_db/src/change.rs | |||
@@ -19,7 +19,7 @@ pub struct Change { | |||
19 | 19 | ||
20 | impl fmt::Debug for Change { | 20 | impl fmt::Debug for Change { |
21 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | 21 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
22 | let mut d = fmt.debug_struct("AnalysisChange"); | 22 | let mut d = fmt.debug_struct("Change"); |
23 | if let Some(roots) = &self.roots { | 23 | if let Some(roots) = &self.roots { |
24 | d.field("roots", roots); | 24 | d.field("roots", roots); |
25 | } | 25 | } |
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs index b3218833d..00b0dc082 100644 --- a/crates/hir/src/code_model.rs +++ b/crates/hir/src/code_model.rs | |||
@@ -31,9 +31,9 @@ use hir_ty::{ | |||
31 | display::{write_bounds_like_dyn_trait_with_prefix, HirDisplayError, HirFormatter}, | 31 | display::{write_bounds_like_dyn_trait_with_prefix, HirDisplayError, HirFormatter}, |
32 | method_resolution, | 32 | method_resolution, |
33 | traits::{FnTrait, Solution, SolutionVariables}, | 33 | traits::{FnTrait, Solution, SolutionVariables}, |
34 | ApplicationTy, BoundVar, CallableDefId, Canonical, DebruijnIndex, FnSig, GenericPredicate, | 34 | AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate, |
35 | InEnvironment, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, Ty, | 35 | InEnvironment, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, TraitEnvironment, |
36 | TyDefId, TyKind, TypeCtor, | 36 | Ty, TyDefId, TyVariableKind, |
37 | }; | 37 | }; |
38 | use rustc_hash::FxHashSet; | 38 | use rustc_hash::FxHashSet; |
39 | use stdx::{format_to, impl_from}; | 39 | use stdx::{format_to, impl_from}; |
@@ -1547,25 +1547,19 @@ impl Type { | |||
1547 | } | 1547 | } |
1548 | 1548 | ||
1549 | pub fn is_unit(&self) -> bool { | 1549 | pub fn is_unit(&self) -> bool { |
1550 | matches!( | 1550 | matches!(self.ty.value, Ty::Tuple(0, ..)) |
1551 | self.ty.value, | ||
1552 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Tuple { cardinality: 0 }, .. }) | ||
1553 | ) | ||
1554 | } | 1551 | } |
1555 | pub fn is_bool(&self) -> bool { | 1552 | pub fn is_bool(&self) -> bool { |
1556 | matches!(self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. })) | 1553 | matches!(self.ty.value, Ty::Scalar(Scalar::Bool)) |
1557 | } | 1554 | } |
1558 | 1555 | ||
1559 | pub fn is_mutable_reference(&self) -> bool { | 1556 | pub fn is_mutable_reference(&self) -> bool { |
1560 | matches!( | 1557 | matches!(self.ty.value, Ty::Ref(Mutability::Mut, ..)) |
1561 | self.ty.value, | ||
1562 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(Mutability::Mut), .. }) | ||
1563 | ) | ||
1564 | } | 1558 | } |
1565 | 1559 | ||
1566 | pub fn remove_ref(&self) -> Option<Type> { | 1560 | pub fn remove_ref(&self) -> Option<Type> { |
1567 | if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(_), .. }) = self.ty.value { | 1561 | if let Ty::Ref(.., substs) = &self.ty.value { |
1568 | self.ty.value.substs().map(|substs| self.derived(substs[0].clone())) | 1562 | Some(self.derived(substs[0].clone())) |
1569 | } else { | 1563 | } else { |
1570 | None | 1564 | None |
1571 | } | 1565 | } |
@@ -1654,14 +1648,14 @@ impl Type { | |||
1654 | .build(); | 1648 | .build(); |
1655 | let predicate = ProjectionPredicate { | 1649 | let predicate = ProjectionPredicate { |
1656 | projection_ty: ProjectionTy { associated_ty: alias.id, parameters: subst }, | 1650 | projection_ty: ProjectionTy { associated_ty: alias.id, parameters: subst }, |
1657 | ty: Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)), | 1651 | ty: Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)), |
1658 | }; | 1652 | }; |
1659 | let goal = Canonical { | 1653 | let goal = Canonical { |
1660 | value: InEnvironment::new( | 1654 | value: InEnvironment::new( |
1661 | self.ty.environment.clone(), | 1655 | self.ty.environment.clone(), |
1662 | Obligation::Projection(predicate), | 1656 | Obligation::Projection(predicate), |
1663 | ), | 1657 | ), |
1664 | kinds: Arc::new([TyKind::General]), | 1658 | kinds: Arc::new([TyVariableKind::General]), |
1665 | }; | 1659 | }; |
1666 | 1660 | ||
1667 | match db.trait_solve(self.krate, goal)? { | 1661 | match db.trait_solve(self.krate, goal)? { |
@@ -1685,7 +1679,7 @@ impl Type { | |||
1685 | 1679 | ||
1686 | pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> { | 1680 | pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> { |
1687 | let def = match self.ty.value { | 1681 | let def = match self.ty.value { |
1688 | Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(def), parameters: _ }) => Some(def), | 1682 | Ty::FnDef(def, _) => Some(def), |
1689 | _ => None, | 1683 | _ => None, |
1690 | }; | 1684 | }; |
1691 | 1685 | ||
@@ -1694,20 +1688,16 @@ impl Type { | |||
1694 | } | 1688 | } |
1695 | 1689 | ||
1696 | pub fn is_closure(&self) -> bool { | 1690 | pub fn is_closure(&self) -> bool { |
1697 | matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { .. }, .. })) | 1691 | matches!(&self.ty.value, Ty::Closure { .. }) |
1698 | } | 1692 | } |
1699 | 1693 | ||
1700 | pub fn is_fn(&self) -> bool { | 1694 | pub fn is_fn(&self) -> bool { |
1701 | matches!( | 1695 | matches!(&self.ty.value, Ty::FnDef(..) | Ty::Function { .. }) |
1702 | &self.ty.value, | ||
1703 | Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(..), .. }) | ||
1704 | | Ty::Apply(ApplicationTy { ctor: TypeCtor::FnPtr { .. }, .. }) | ||
1705 | ) | ||
1706 | } | 1696 | } |
1707 | 1697 | ||
1708 | pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { | 1698 | pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { |
1709 | let adt_id = match self.ty.value { | 1699 | let adt_id = match self.ty.value { |
1710 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(adt_id), .. }) => adt_id, | 1700 | Ty::Adt(adt_id, ..) => adt_id, |
1711 | _ => return false, | 1701 | _ => return false, |
1712 | }; | 1702 | }; |
1713 | 1703 | ||
@@ -1719,7 +1709,7 @@ impl Type { | |||
1719 | } | 1709 | } |
1720 | 1710 | ||
1721 | pub fn is_raw_ptr(&self) -> bool { | 1711 | pub fn is_raw_ptr(&self) -> bool { |
1722 | matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. })) | 1712 | matches!(&self.ty.value, Ty::Raw(..)) |
1723 | } | 1713 | } |
1724 | 1714 | ||
1725 | pub fn contains_unknown(&self) -> bool { | 1715 | pub fn contains_unknown(&self) -> bool { |
@@ -1728,44 +1718,34 @@ impl Type { | |||
1728 | fn go(ty: &Ty) -> bool { | 1718 | fn go(ty: &Ty) -> bool { |
1729 | match ty { | 1719 | match ty { |
1730 | Ty::Unknown => true, | 1720 | Ty::Unknown => true, |
1731 | Ty::Apply(a_ty) => a_ty.parameters.iter().any(go), | 1721 | _ => ty.substs().map_or(false, |substs| substs.iter().any(go)), |
1732 | _ => false, | ||
1733 | } | 1722 | } |
1734 | } | 1723 | } |
1735 | } | 1724 | } |
1736 | 1725 | ||
1737 | pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> { | 1726 | pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> { |
1738 | if let Ty::Apply(a_ty) = &self.ty.value { | 1727 | let (variant_id, substs) = match self.ty.value { |
1739 | let variant_id = match a_ty.ctor { | 1728 | Ty::Adt(AdtId::StructId(s), ref substs) => (s.into(), substs), |
1740 | TypeCtor::Adt(AdtId::StructId(s)) => s.into(), | 1729 | Ty::Adt(AdtId::UnionId(u), ref substs) => (u.into(), substs), |
1741 | TypeCtor::Adt(AdtId::UnionId(u)) => u.into(), | 1730 | _ => return Vec::new(), |
1742 | _ => return Vec::new(), | ||
1743 | }; | ||
1744 | |||
1745 | return db | ||
1746 | .field_types(variant_id) | ||
1747 | .iter() | ||
1748 | .map(|(local_id, ty)| { | ||
1749 | let def = Field { parent: variant_id.into(), id: local_id }; | ||
1750 | let ty = ty.clone().subst(&a_ty.parameters); | ||
1751 | (def, self.derived(ty)) | ||
1752 | }) | ||
1753 | .collect(); | ||
1754 | }; | 1731 | }; |
1755 | Vec::new() | 1732 | |
1733 | db.field_types(variant_id) | ||
1734 | .iter() | ||
1735 | .map(|(local_id, ty)| { | ||
1736 | let def = Field { parent: variant_id.into(), id: local_id }; | ||
1737 | let ty = ty.clone().subst(substs); | ||
1738 | (def, self.derived(ty)) | ||
1739 | }) | ||
1740 | .collect() | ||
1756 | } | 1741 | } |
1757 | 1742 | ||
1758 | pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> { | 1743 | pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> { |
1759 | let mut res = Vec::new(); | 1744 | if let Ty::Tuple(_, substs) = &self.ty.value { |
1760 | if let Ty::Apply(a_ty) = &self.ty.value { | 1745 | substs.iter().map(|ty| self.derived(ty.clone())).collect() |
1761 | if let TypeCtor::Tuple { .. } = a_ty.ctor { | 1746 | } else { |
1762 | for ty in a_ty.parameters.iter() { | 1747 | Vec::new() |
1763 | let ty = ty.clone(); | 1748 | } |
1764 | res.push(self.derived(ty)); | ||
1765 | } | ||
1766 | } | ||
1767 | }; | ||
1768 | res | ||
1769 | } | 1749 | } |
1770 | 1750 | ||
1771 | pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a { | 1751 | pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a { |
@@ -1802,15 +1782,13 @@ impl Type { | |||
1802 | } | 1782 | } |
1803 | 1783 | ||
1804 | pub fn type_parameters(&self) -> impl Iterator<Item = Type> + '_ { | 1784 | pub fn type_parameters(&self) -> impl Iterator<Item = Type> + '_ { |
1805 | let ty = self.ty.value.strip_references(); | 1785 | self.ty |
1806 | let substs = match ty { | 1786 | .value |
1807 | Ty::Apply(apply_ty) => &apply_ty.parameters, | 1787 | .strip_references() |
1808 | Ty::Opaque(opaque_ty) => &opaque_ty.parameters, | 1788 | .substs() |
1809 | _ => return Either::Left(iter::empty()), | 1789 | .into_iter() |
1810 | }; | 1790 | .flat_map(|substs| substs.iter()) |
1811 | 1791 | .map(move |ty| self.derived(ty.clone())) | |
1812 | let iter = substs.iter().map(move |ty| self.derived(ty.clone())); | ||
1813 | Either::Right(iter) | ||
1814 | } | 1792 | } |
1815 | 1793 | ||
1816 | pub fn iterate_method_candidates<T>( | 1794 | pub fn iterate_method_candidates<T>( |
@@ -1900,17 +1878,8 @@ impl Type { | |||
1900 | 1878 | ||
1901 | // FIXME: provide required accessors such that it becomes implementable from outside. | 1879 | // FIXME: provide required accessors such that it becomes implementable from outside. |
1902 | pub fn is_equal_for_find_impls(&self, other: &Type) -> bool { | 1880 | pub fn is_equal_for_find_impls(&self, other: &Type) -> bool { |
1903 | match (&self.ty.value, &other.ty.value) { | 1881 | let rref = other.remove_ref(); |
1904 | (Ty::Apply(a_original_ty), Ty::Apply(ApplicationTy { ctor, parameters })) => match ctor | 1882 | self.ty.value.equals_ctor(rref.as_ref().map_or(&other.ty.value, |it| &it.ty.value)) |
1905 | { | ||
1906 | TypeCtor::Ref(..) => match parameters.as_single() { | ||
1907 | Ty::Apply(a_ty) => a_original_ty.ctor == a_ty.ctor, | ||
1908 | _ => false, | ||
1909 | }, | ||
1910 | _ => a_original_ty.ctor == *ctor, | ||
1911 | }, | ||
1912 | _ => false, | ||
1913 | } | ||
1914 | } | 1883 | } |
1915 | 1884 | ||
1916 | fn derived(&self, ty: Ty) -> Type { | 1885 | fn derived(&self, ty: Ty) -> Type { |
@@ -1955,28 +1924,20 @@ impl Type { | |||
1955 | fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) { | 1924 | fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) { |
1956 | let ty = type_.ty.value.strip_references(); | 1925 | let ty = type_.ty.value.strip_references(); |
1957 | match ty { | 1926 | match ty { |
1958 | Ty::Apply(ApplicationTy { ctor, parameters }) => { | 1927 | Ty::Adt(..) => { |
1959 | match ctor { | 1928 | cb(type_.derived(ty.clone())); |
1960 | TypeCtor::Adt(_) => { | 1929 | } |
1961 | cb(type_.derived(ty.clone())); | 1930 | Ty::AssociatedType(..) => { |
1962 | } | 1931 | if let Some(_) = ty.associated_type_parent_trait(db) { |
1963 | TypeCtor::AssociatedType(_) => { | 1932 | cb(type_.derived(ty.clone())); |
1964 | if let Some(_) = ty.associated_type_parent_trait(db) { | ||
1965 | cb(type_.derived(ty.clone())); | ||
1966 | } | ||
1967 | } | ||
1968 | TypeCtor::OpaqueType(..) => { | ||
1969 | if let Some(bounds) = ty.impl_trait_bounds(db) { | ||
1970 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); | ||
1971 | } | ||
1972 | } | ||
1973 | _ => (), | ||
1974 | } | 1933 | } |
1975 | |||
1976 | // adt params, tuples, etc... | ||
1977 | walk_substs(db, type_, parameters, cb); | ||
1978 | } | 1934 | } |
1979 | Ty::Opaque(opaque_ty) => { | 1935 | Ty::OpaqueType(..) => { |
1936 | if let Some(bounds) = ty.impl_trait_bounds(db) { | ||
1937 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); | ||
1938 | } | ||
1939 | } | ||
1940 | Ty::Alias(AliasTy::Opaque(opaque_ty)) => { | ||
1980 | if let Some(bounds) = ty.impl_trait_bounds(db) { | 1941 | if let Some(bounds) = ty.impl_trait_bounds(db) { |
1981 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); | 1942 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); |
1982 | } | 1943 | } |
@@ -1992,7 +1953,10 @@ impl Type { | |||
1992 | walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb); | 1953 | walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb); |
1993 | } | 1954 | } |
1994 | 1955 | ||
1995 | _ => (), | 1956 | _ => {} |
1957 | } | ||
1958 | if let Some(substs) = ty.substs() { | ||
1959 | walk_substs(db, type_, &substs, cb); | ||
1996 | } | 1960 | } |
1997 | } | 1961 | } |
1998 | 1962 | ||
@@ -2010,7 +1974,7 @@ impl HirDisplay for Type { | |||
2010 | #[derive(Debug)] | 1974 | #[derive(Debug)] |
2011 | pub struct Callable { | 1975 | pub struct Callable { |
2012 | ty: Type, | 1976 | ty: Type, |
2013 | sig: FnSig, | 1977 | sig: CallableSig, |
2014 | def: Option<CallableDefId>, | 1978 | def: Option<CallableDefId>, |
2015 | pub(crate) is_bound_method: bool, | 1979 | pub(crate) is_bound_method: bool, |
2016 | } | 1980 | } |
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs index 5343a036c..b1ebba516 100644 --- a/crates/hir/src/diagnostics.rs +++ b/crates/hir/src/diagnostics.rs | |||
@@ -1,5 +1,7 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | pub use hir_def::diagnostics::{InactiveCode, UnresolvedModule, UnresolvedProcMacro}; | 2 | pub use hir_def::diagnostics::{ |
3 | InactiveCode, UnresolvedMacroCall, UnresolvedModule, UnresolvedProcMacro, | ||
4 | }; | ||
3 | pub use hir_expand::diagnostics::{ | 5 | pub use hir_expand::diagnostics::{ |
4 | Diagnostic, DiagnosticCode, DiagnosticSink, DiagnosticSinkBuilder, | 6 | Diagnostic, DiagnosticCode, DiagnosticSink, DiagnosticSinkBuilder, |
5 | }; | 7 | }; |
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 59292d5a2..144851f83 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs | |||
@@ -16,13 +16,12 @@ use rustc_hash::{FxHashMap, FxHashSet}; | |||
16 | use syntax::{ | 16 | use syntax::{ |
17 | algo::find_node_at_offset, | 17 | algo::find_node_at_offset, |
18 | ast::{self, GenericParamsOwner, LoopBodyOwner}, | 18 | ast::{self, GenericParamsOwner, LoopBodyOwner}, |
19 | match_ast, AstNode, SyntaxNode, SyntaxToken, TextSize, | 19 | match_ast, AstNode, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextSize, |
20 | }; | 20 | }; |
21 | 21 | ||
22 | use crate::{ | 22 | use crate::{ |
23 | code_model::Access, | 23 | code_model::Access, |
24 | db::HirDatabase, | 24 | db::HirDatabase, |
25 | diagnostics::Diagnostic, | ||
26 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, | 25 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, |
27 | source_analyzer::{resolve_hir_path, SourceAnalyzer}, | 26 | source_analyzer::{resolve_hir_path, SourceAnalyzer}, |
28 | AssocItem, Callable, ConstParam, Crate, Field, Function, HirFileId, Impl, InFile, Label, | 27 | AssocItem, Callable, ConstParam, Crate, Field, Function, HirFileId, Impl, InFile, Label, |
@@ -141,7 +140,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
141 | self.imp.original_range(node) | 140 | self.imp.original_range(node) |
142 | } | 141 | } |
143 | 142 | ||
144 | pub fn diagnostics_display_range(&self, diagnostics: &dyn Diagnostic) -> FileRange { | 143 | pub fn diagnostics_display_range(&self, diagnostics: InFile<SyntaxNodePtr>) -> FileRange { |
145 | self.imp.diagnostics_display_range(diagnostics) | 144 | self.imp.diagnostics_display_range(diagnostics) |
146 | } | 145 | } |
147 | 146 | ||
@@ -385,8 +384,7 @@ impl<'db> SemanticsImpl<'db> { | |||
385 | node.as_ref().original_file_range(self.db.upcast()) | 384 | node.as_ref().original_file_range(self.db.upcast()) |
386 | } | 385 | } |
387 | 386 | ||
388 | fn diagnostics_display_range(&self, diagnostics: &dyn Diagnostic) -> FileRange { | 387 | fn diagnostics_display_range(&self, src: InFile<SyntaxNodePtr>) -> FileRange { |
389 | let src = diagnostics.display_source(); | ||
390 | let root = self.db.parse_or_expand(src.file_id).unwrap(); | 388 | let root = self.db.parse_or_expand(src.file_id).unwrap(); |
391 | let node = src.value.to_node(&root); | 389 | let node = src.value.to_node(&root); |
392 | self.cache(root, src.file_id); | 390 | self.cache(root, src.file_id); |
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index dc21f6051..64ce4add1 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs | |||
@@ -20,7 +20,7 @@ use hir_def::{ | |||
20 | use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; | 20 | use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; |
21 | use hir_ty::{ | 21 | use hir_ty::{ |
22 | diagnostics::{record_literal_missing_fields, record_pattern_missing_fields}, | 22 | diagnostics::{record_literal_missing_fields, record_pattern_missing_fields}, |
23 | InferenceResult, Substs, Ty, | 23 | InferenceResult, Substs, |
24 | }; | 24 | }; |
25 | use syntax::{ | 25 | use syntax::{ |
26 | ast::{self, AstNode}, | 26 | ast::{self, AstNode}, |
@@ -299,14 +299,11 @@ impl SourceAnalyzer { | |||
299 | let infer = self.infer.as_ref()?; | 299 | let infer = self.infer.as_ref()?; |
300 | 300 | ||
301 | let expr_id = self.expr_id(db, &literal.clone().into())?; | 301 | let expr_id = self.expr_id(db, &literal.clone().into())?; |
302 | let substs = match &infer.type_of_expr[expr_id] { | 302 | let substs = infer.type_of_expr[expr_id].substs()?; |
303 | Ty::Apply(a_ty) => &a_ty.parameters, | ||
304 | _ => return None, | ||
305 | }; | ||
306 | 303 | ||
307 | let (variant, missing_fields, _exhaustive) = | 304 | let (variant, missing_fields, _exhaustive) = |
308 | record_literal_missing_fields(db, infer, expr_id, &body[expr_id])?; | 305 | record_literal_missing_fields(db, infer, expr_id, &body[expr_id])?; |
309 | let res = self.missing_fields(db, krate, substs, variant, missing_fields); | 306 | let res = self.missing_fields(db, krate, &substs, variant, missing_fields); |
310 | Some(res) | 307 | Some(res) |
311 | } | 308 | } |
312 | 309 | ||
@@ -320,14 +317,11 @@ impl SourceAnalyzer { | |||
320 | let infer = self.infer.as_ref()?; | 317 | let infer = self.infer.as_ref()?; |
321 | 318 | ||
322 | let pat_id = self.pat_id(&pattern.clone().into())?; | 319 | let pat_id = self.pat_id(&pattern.clone().into())?; |
323 | let substs = match &infer.type_of_pat[pat_id] { | 320 | let substs = infer.type_of_pat[pat_id].substs()?; |
324 | Ty::Apply(a_ty) => &a_ty.parameters, | ||
325 | _ => return None, | ||
326 | }; | ||
327 | 321 | ||
328 | let (variant, missing_fields, _exhaustive) = | 322 | let (variant, missing_fields, _exhaustive) = |
329 | record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?; | 323 | record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?; |
330 | let res = self.missing_fields(db, krate, substs, variant, missing_fields); | 324 | let res = self.missing_fields(db, krate, &substs, variant, missing_fields); |
331 | Some(res) | 325 | Some(res) |
332 | } | 326 | } |
333 | 327 | ||
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs index 9a432f7d1..ff4b4a0cf 100644 --- a/crates/hir_def/src/body.rs +++ b/crates/hir_def/src/body.rs | |||
@@ -123,7 +123,7 @@ impl Expander { | |||
123 | Some(it) => it, | 123 | Some(it) => it, |
124 | None => { | 124 | None => { |
125 | if err.is_none() { | 125 | if err.is_none() { |
126 | eprintln!("no error despite `as_call_id_with_errors` returning `None`"); | 126 | log::warn!("no error despite `as_call_id_with_errors` returning `None`"); |
127 | } | 127 | } |
128 | return ExpandResult { value: None, err }; | 128 | return ExpandResult { value: None, err }; |
129 | } | 129 | } |
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index c18001e15..40beb2f7a 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -24,7 +24,7 @@ use test_utils::mark; | |||
24 | use crate::{ | 24 | use crate::{ |
25 | adt::StructKind, | 25 | adt::StructKind, |
26 | body::{Body, BodySourceMap, Expander, LabelSource, PatPtr, SyntheticSyntax}, | 26 | body::{Body, BodySourceMap, Expander, LabelSource, PatPtr, SyntheticSyntax}, |
27 | builtin_type::{BuiltinFloat, BuiltinInt}, | 27 | builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint}, |
28 | db::DefDatabase, | 28 | db::DefDatabase, |
29 | diagnostics::{InactiveCode, MacroError, UnresolvedProcMacro}, | 29 | diagnostics::{InactiveCode, MacroError, UnresolvedProcMacro}, |
30 | expr::{ | 30 | expr::{ |
@@ -1065,11 +1065,16 @@ impl From<ast::LiteralKind> for Literal { | |||
1065 | fn from(ast_lit_kind: ast::LiteralKind) -> Self { | 1065 | fn from(ast_lit_kind: ast::LiteralKind) -> Self { |
1066 | match ast_lit_kind { | 1066 | match ast_lit_kind { |
1067 | LiteralKind::IntNumber(lit) => { | 1067 | LiteralKind::IntNumber(lit) => { |
1068 | if let Some(float_suffix) = lit.suffix().and_then(BuiltinFloat::from_suffix) { | 1068 | if let builtin @ Some(_) = lit.suffix().and_then(BuiltinFloat::from_suffix) { |
1069 | return Literal::Float(Default::default(), Some(float_suffix)); | 1069 | return Literal::Float(Default::default(), builtin); |
1070 | } else if let builtin @ Some(_) = | ||
1071 | lit.suffix().and_then(|it| BuiltinInt::from_suffix(&it)) | ||
1072 | { | ||
1073 | Literal::Int(Default::default(), builtin) | ||
1074 | } else { | ||
1075 | let builtin = lit.suffix().and_then(|it| BuiltinUint::from_suffix(&it)); | ||
1076 | Literal::Uint(Default::default(), builtin) | ||
1070 | } | 1077 | } |
1071 | let ty = lit.suffix().and_then(|it| BuiltinInt::from_suffix(&it)); | ||
1072 | Literal::Int(Default::default(), ty) | ||
1073 | } | 1078 | } |
1074 | LiteralKind::FloatNumber(lit) => { | 1079 | LiteralKind::FloatNumber(lit) => { |
1075 | let ty = lit.suffix().and_then(|it| BuiltinFloat::from_suffix(&it)); | 1080 | let ty = lit.suffix().and_then(|it| BuiltinFloat::from_suffix(&it)); |
@@ -1077,7 +1082,7 @@ impl From<ast::LiteralKind> for Literal { | |||
1077 | } | 1082 | } |
1078 | LiteralKind::ByteString(_) => Literal::ByteString(Default::default()), | 1083 | LiteralKind::ByteString(_) => Literal::ByteString(Default::default()), |
1079 | LiteralKind::String(_) => Literal::String(Default::default()), | 1084 | LiteralKind::String(_) => Literal::String(Default::default()), |
1080 | LiteralKind::Byte => Literal::Int(Default::default(), Some(BuiltinInt::U8)), | 1085 | LiteralKind::Byte => Literal::Uint(Default::default(), Some(BuiltinUint::U8)), |
1081 | LiteralKind::Bool(val) => Literal::Bool(val), | 1086 | LiteralKind::Bool(val) => Literal::Bool(val), |
1082 | LiteralKind::Char => Literal::Char(Default::default()), | 1087 | LiteralKind::Char => Literal::Char(Default::default()), |
1083 | } | 1088 | } |
diff --git a/crates/hir_def/src/body/tests/block.rs b/crates/hir_def/src/body/tests/block.rs index a5ec0883f..8bca72a17 100644 --- a/crates/hir_def/src/body/tests/block.rs +++ b/crates/hir_def/src/body/tests/block.rs | |||
@@ -259,3 +259,32 @@ fn main() { | |||
259 | "#]], | 259 | "#]], |
260 | ); | 260 | ); |
261 | } | 261 | } |
262 | |||
263 | #[test] | ||
264 | fn underscore_import() { | ||
265 | // This used to panic, because the default (private) visibility inside block expressions would | ||
266 | // point into the containing `DefMap`, which visibilities should never be able to do. | ||
267 | mark::check!(adjust_vis_in_block_def_map); | ||
268 | check_at( | ||
269 | r#" | ||
270 | mod m { | ||
271 | fn main() { | ||
272 | use Tr as _; | ||
273 | trait Tr {} | ||
274 | $0 | ||
275 | } | ||
276 | } | ||
277 | "#, | ||
278 | expect![[r#" | ||
279 | block scope | ||
280 | _: t | ||
281 | Tr: t | ||
282 | |||
283 | crate | ||
284 | m: t | ||
285 | |||
286 | crate::m | ||
287 | main: v | ||
288 | "#]], | ||
289 | ); | ||
290 | } | ||
diff --git a/crates/hir_def/src/builtin_type.rs b/crates/hir_def/src/builtin_type.rs index 0f872b5c0..7cbaf30b8 100644 --- a/crates/hir_def/src/builtin_type.rs +++ b/crates/hir_def/src/builtin_type.rs | |||
@@ -6,38 +6,32 @@ | |||
6 | use std::fmt; | 6 | use std::fmt; |
7 | 7 | ||
8 | use hir_expand::name::{name, AsName, Name}; | 8 | use hir_expand::name::{name, AsName, Name}; |
9 | 9 | /// Different signed int types. | |
10 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] | 10 | #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] |
11 | pub enum Signedness { | 11 | pub enum BuiltinInt { |
12 | Signed, | 12 | Isize, |
13 | Unsigned, | 13 | I8, |
14 | } | 14 | I16, |
15 | 15 | I32, | |
16 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] | 16 | I64, |
17 | pub enum IntBitness { | 17 | I128, |
18 | Xsize, | ||
19 | X8, | ||
20 | X16, | ||
21 | X32, | ||
22 | X64, | ||
23 | X128, | ||
24 | } | ||
25 | |||
26 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] | ||
27 | pub enum FloatBitness { | ||
28 | X32, | ||
29 | X64, | ||
30 | } | 18 | } |
31 | 19 | ||
32 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 20 | /// Different unsigned int types. |
33 | pub struct BuiltinInt { | 21 | #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] |
34 | pub signedness: Signedness, | 22 | pub enum BuiltinUint { |
35 | pub bitness: IntBitness, | 23 | Usize, |
24 | U8, | ||
25 | U16, | ||
26 | U32, | ||
27 | U64, | ||
28 | U128, | ||
36 | } | 29 | } |
37 | 30 | ||
38 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 31 | #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] |
39 | pub struct BuiltinFloat { | 32 | pub enum BuiltinFloat { |
40 | pub bitness: FloatBitness, | 33 | F32, |
34 | F64, | ||
41 | } | 35 | } |
42 | 36 | ||
43 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 37 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -46,6 +40,7 @@ pub enum BuiltinType { | |||
46 | Bool, | 40 | Bool, |
47 | Str, | 41 | Str, |
48 | Int(BuiltinInt), | 42 | Int(BuiltinInt), |
43 | Uint(BuiltinUint), | ||
49 | Float(BuiltinFloat), | 44 | Float(BuiltinFloat), |
50 | } | 45 | } |
51 | 46 | ||
@@ -56,19 +51,19 @@ impl BuiltinType { | |||
56 | (name![bool], BuiltinType::Bool), | 51 | (name![bool], BuiltinType::Bool), |
57 | (name![str], BuiltinType::Str), | 52 | (name![str], BuiltinType::Str), |
58 | 53 | ||
59 | (name![isize], BuiltinType::Int(BuiltinInt::ISIZE)), | 54 | (name![isize], BuiltinType::Int(BuiltinInt::Isize)), |
60 | (name![i8], BuiltinType::Int(BuiltinInt::I8)), | 55 | (name![i8], BuiltinType::Int(BuiltinInt::I8)), |
61 | (name![i16], BuiltinType::Int(BuiltinInt::I16)), | 56 | (name![i16], BuiltinType::Int(BuiltinInt::I16)), |
62 | (name![i32], BuiltinType::Int(BuiltinInt::I32)), | 57 | (name![i32], BuiltinType::Int(BuiltinInt::I32)), |
63 | (name![i64], BuiltinType::Int(BuiltinInt::I64)), | 58 | (name![i64], BuiltinType::Int(BuiltinInt::I64)), |
64 | (name![i128], BuiltinType::Int(BuiltinInt::I128)), | 59 | (name![i128], BuiltinType::Int(BuiltinInt::I128)), |
65 | 60 | ||
66 | (name![usize], BuiltinType::Int(BuiltinInt::USIZE)), | 61 | (name![usize], BuiltinType::Uint(BuiltinUint::Usize)), |
67 | (name![u8], BuiltinType::Int(BuiltinInt::U8)), | 62 | (name![u8], BuiltinType::Uint(BuiltinUint::U8)), |
68 | (name![u16], BuiltinType::Int(BuiltinInt::U16)), | 63 | (name![u16], BuiltinType::Uint(BuiltinUint::U16)), |
69 | (name![u32], BuiltinType::Int(BuiltinInt::U32)), | 64 | (name![u32], BuiltinType::Uint(BuiltinUint::U32)), |
70 | (name![u64], BuiltinType::Int(BuiltinInt::U64)), | 65 | (name![u64], BuiltinType::Uint(BuiltinUint::U64)), |
71 | (name![u128], BuiltinType::Int(BuiltinInt::U128)), | 66 | (name![u128], BuiltinType::Uint(BuiltinUint::U128)), |
72 | 67 | ||
73 | (name![f32], BuiltinType::Float(BuiltinFloat::F32)), | 68 | (name![f32], BuiltinType::Float(BuiltinFloat::F32)), |
74 | (name![f64], BuiltinType::Float(BuiltinFloat::F64)), | 69 | (name![f64], BuiltinType::Float(BuiltinFloat::F64)), |
@@ -81,24 +76,25 @@ impl AsName for BuiltinType { | |||
81 | BuiltinType::Char => name![char], | 76 | BuiltinType::Char => name![char], |
82 | BuiltinType::Bool => name![bool], | 77 | BuiltinType::Bool => name![bool], |
83 | BuiltinType::Str => name![str], | 78 | BuiltinType::Str => name![str], |
84 | BuiltinType::Int(BuiltinInt { signedness, bitness }) => match (signedness, bitness) { | 79 | BuiltinType::Int(it) => match it { |
85 | (Signedness::Signed, IntBitness::Xsize) => name![isize], | 80 | BuiltinInt::Isize => name![isize], |
86 | (Signedness::Signed, IntBitness::X8) => name![i8], | 81 | BuiltinInt::I8 => name![i8], |
87 | (Signedness::Signed, IntBitness::X16) => name![i16], | 82 | BuiltinInt::I16 => name![i16], |
88 | (Signedness::Signed, IntBitness::X32) => name![i32], | 83 | BuiltinInt::I32 => name![i32], |
89 | (Signedness::Signed, IntBitness::X64) => name![i64], | 84 | BuiltinInt::I64 => name![i64], |
90 | (Signedness::Signed, IntBitness::X128) => name![i128], | 85 | BuiltinInt::I128 => name![i128], |
91 | 86 | }, | |
92 | (Signedness::Unsigned, IntBitness::Xsize) => name![usize], | 87 | BuiltinType::Uint(it) => match it { |
93 | (Signedness::Unsigned, IntBitness::X8) => name![u8], | 88 | BuiltinUint::Usize => name![usize], |
94 | (Signedness::Unsigned, IntBitness::X16) => name![u16], | 89 | BuiltinUint::U8 => name![u8], |
95 | (Signedness::Unsigned, IntBitness::X32) => name![u32], | 90 | BuiltinUint::U16 => name![u16], |
96 | (Signedness::Unsigned, IntBitness::X64) => name![u64], | 91 | BuiltinUint::U32 => name![u32], |
97 | (Signedness::Unsigned, IntBitness::X128) => name![u128], | 92 | BuiltinUint::U64 => name![u64], |
93 | BuiltinUint::U128 => name![u128], | ||
98 | }, | 94 | }, |
99 | BuiltinType::Float(BuiltinFloat { bitness }) => match bitness { | 95 | BuiltinType::Float(it) => match it { |
100 | FloatBitness::X32 => name![f32], | 96 | BuiltinFloat::F32 => name![f32], |
101 | FloatBitness::X64 => name![f64], | 97 | BuiltinFloat::F64 => name![f64], |
102 | }, | 98 | }, |
103 | } | 99 | } |
104 | } | 100 | } |
@@ -113,31 +109,26 @@ impl fmt::Display for BuiltinType { | |||
113 | 109 | ||
114 | #[rustfmt::skip] | 110 | #[rustfmt::skip] |
115 | impl BuiltinInt { | 111 | impl BuiltinInt { |
116 | pub const ISIZE: BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::Xsize }; | ||
117 | pub const I8 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X8 }; | ||
118 | pub const I16 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X16 }; | ||
119 | pub const I32 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X32 }; | ||
120 | pub const I64 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X64 }; | ||
121 | pub const I128 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X128 }; | ||
122 | |||
123 | pub const USIZE: BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::Xsize }; | ||
124 | pub const U8 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X8 }; | ||
125 | pub const U16 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X16 }; | ||
126 | pub const U32 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X32 }; | ||
127 | pub const U64 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X64 }; | ||
128 | pub const U128 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X128 }; | ||
129 | |||
130 | |||
131 | pub fn from_suffix(suffix: &str) -> Option<BuiltinInt> { | 112 | pub fn from_suffix(suffix: &str) -> Option<BuiltinInt> { |
132 | let res = match suffix { | 113 | let res = match suffix { |
133 | "isize" => Self::ISIZE, | 114 | "isize" => Self::Isize, |
134 | "i8" => Self::I8, | 115 | "i8" => Self::I8, |
135 | "i16" => Self::I16, | 116 | "i16" => Self::I16, |
136 | "i32" => Self::I32, | 117 | "i32" => Self::I32, |
137 | "i64" => Self::I64, | 118 | "i64" => Self::I64, |
138 | "i128" => Self::I128, | 119 | "i128" => Self::I128, |
139 | 120 | ||
140 | "usize" => Self::USIZE, | 121 | _ => return None, |
122 | }; | ||
123 | Some(res) | ||
124 | } | ||
125 | } | ||
126 | |||
127 | #[rustfmt::skip] | ||
128 | impl BuiltinUint { | ||
129 | pub fn from_suffix(suffix: &str) -> Option<BuiltinUint> { | ||
130 | let res = match suffix { | ||
131 | "usize" => Self::Usize, | ||
141 | "u8" => Self::U8, | 132 | "u8" => Self::U8, |
142 | "u16" => Self::U16, | 133 | "u16" => Self::U16, |
143 | "u32" => Self::U32, | 134 | "u32" => Self::U32, |
@@ -152,9 +143,6 @@ impl BuiltinInt { | |||
152 | 143 | ||
153 | #[rustfmt::skip] | 144 | #[rustfmt::skip] |
154 | impl BuiltinFloat { | 145 | impl BuiltinFloat { |
155 | pub const F32: BuiltinFloat = BuiltinFloat { bitness: FloatBitness::X32 }; | ||
156 | pub const F64: BuiltinFloat = BuiltinFloat { bitness: FloatBitness::X64 }; | ||
157 | |||
158 | pub fn from_suffix(suffix: &str) -> Option<BuiltinFloat> { | 146 | pub fn from_suffix(suffix: &str) -> Option<BuiltinFloat> { |
159 | let res = match suffix { | 147 | let res = match suffix { |
160 | "f32" => BuiltinFloat::F32, | 148 | "f32" => BuiltinFloat::F32, |
diff --git a/crates/hir_def/src/diagnostics.rs b/crates/hir_def/src/diagnostics.rs index ab3f059ce..ac7474f63 100644 --- a/crates/hir_def/src/diagnostics.rs +++ b/crates/hir_def/src/diagnostics.rs | |||
@@ -95,6 +95,34 @@ impl Diagnostic for UnresolvedImport { | |||
95 | } | 95 | } |
96 | } | 96 | } |
97 | 97 | ||
98 | // Diagnostic: unresolved-macro-call | ||
99 | // | ||
100 | // This diagnostic is triggered if rust-analyzer is unable to resolove path to a | ||
101 | // macro in a macro invocation. | ||
102 | #[derive(Debug)] | ||
103 | pub struct UnresolvedMacroCall { | ||
104 | pub file: HirFileId, | ||
105 | pub node: AstPtr<ast::MacroCall>, | ||
106 | } | ||
107 | |||
108 | impl Diagnostic for UnresolvedMacroCall { | ||
109 | fn code(&self) -> DiagnosticCode { | ||
110 | DiagnosticCode("unresolved-macro-call") | ||
111 | } | ||
112 | fn message(&self) -> String { | ||
113 | "unresolved macro call".to_string() | ||
114 | } | ||
115 | fn display_source(&self) -> InFile<SyntaxNodePtr> { | ||
116 | InFile::new(self.file, self.node.clone().into()) | ||
117 | } | ||
118 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | ||
119 | self | ||
120 | } | ||
121 | fn is_experimental(&self) -> bool { | ||
122 | true | ||
123 | } | ||
124 | } | ||
125 | |||
98 | // Diagnostic: inactive-code | 126 | // Diagnostic: inactive-code |
99 | // | 127 | // |
100 | // This diagnostic is shown for code with inactive `#[cfg]` attributes. | 128 | // This diagnostic is shown for code with inactive `#[cfg]` attributes. |
diff --git a/crates/hir_def/src/expr.rs b/crates/hir_def/src/expr.rs index 4d72eaeaf..24be93773 100644 --- a/crates/hir_def/src/expr.rs +++ b/crates/hir_def/src/expr.rs | |||
@@ -17,7 +17,7 @@ use la_arena::{Idx, RawIdx}; | |||
17 | use syntax::ast::RangeOp; | 17 | use syntax::ast::RangeOp; |
18 | 18 | ||
19 | use crate::{ | 19 | use crate::{ |
20 | builtin_type::{BuiltinFloat, BuiltinInt}, | 20 | builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint}, |
21 | path::{GenericArgs, Path}, | 21 | path::{GenericArgs, Path}, |
22 | type_ref::{Mutability, Rawness, TypeRef}, | 22 | type_ref::{Mutability, Rawness, TypeRef}, |
23 | BlockId, | 23 | BlockId, |
@@ -43,6 +43,7 @@ pub enum Literal { | |||
43 | Char(char), | 43 | Char(char), |
44 | Bool(bool), | 44 | Bool(bool), |
45 | Int(u64, Option<BuiltinInt>), | 45 | Int(u64, Option<BuiltinInt>), |
46 | Uint(u64, Option<BuiltinUint>), | ||
46 | Float(u64, Option<BuiltinFloat>), // FIXME: f64 is not Eq | 47 | Float(u64, Option<BuiltinFloat>), // FIXME: f64 is not Eq |
47 | } | 48 | } |
48 | 49 | ||
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index b50923747..6802bc250 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs | |||
@@ -57,8 +57,10 @@ use std::{ | |||
57 | 57 | ||
58 | use base_db::{impl_intern_key, salsa, CrateId}; | 58 | use base_db::{impl_intern_key, salsa, CrateId}; |
59 | use hir_expand::{ | 59 | use hir_expand::{ |
60 | ast_id_map::FileAstId, eager::expand_eager_macro, hygiene::Hygiene, AstId, HirFileId, InFile, | 60 | ast_id_map::FileAstId, |
61 | MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, | 61 | eager::{expand_eager_macro, ErrorEmitted}, |
62 | hygiene::Hygiene, | ||
63 | AstId, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, | ||
62 | }; | 64 | }; |
63 | use la_arena::Idx; | 65 | use la_arena::Idx; |
64 | use nameres::DefMap; | 66 | use nameres::DefMap; |
@@ -592,8 +594,15 @@ impl AsMacroCall for InFile<&ast::MacroCall> { | |||
592 | error_sink(mbe::ExpandError::Other("malformed macro invocation".into())); | 594 | error_sink(mbe::ExpandError::Other("malformed macro invocation".into())); |
593 | } | 595 | } |
594 | 596 | ||
595 | AstIdWithPath::new(ast_id.file_id, ast_id.value, path?) | 597 | macro_call_as_call_id( |
596 | .as_call_id_with_errors(db, krate, resolver, error_sink) | 598 | &AstIdWithPath::new(ast_id.file_id, ast_id.value, path?), |
599 | db, | ||
600 | krate, | ||
601 | resolver, | ||
602 | error_sink, | ||
603 | ) | ||
604 | .ok()? | ||
605 | .ok() | ||
597 | } | 606 | } |
598 | } | 607 | } |
599 | 608 | ||
@@ -610,61 +619,50 @@ impl<T: ast::AstNode> AstIdWithPath<T> { | |||
610 | } | 619 | } |
611 | } | 620 | } |
612 | 621 | ||
613 | impl AsMacroCall for AstIdWithPath<ast::MacroCall> { | 622 | struct UnresolvedMacro; |
614 | fn as_call_id_with_errors( | 623 | |
615 | &self, | 624 | fn macro_call_as_call_id( |
616 | db: &dyn db::DefDatabase, | 625 | call: &AstIdWithPath<ast::MacroCall>, |
617 | krate: CrateId, | 626 | db: &dyn db::DefDatabase, |
618 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | 627 | krate: CrateId, |
619 | error_sink: &mut dyn FnMut(mbe::ExpandError), | 628 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, |
620 | ) -> Option<MacroCallId> { | 629 | error_sink: &mut dyn FnMut(mbe::ExpandError), |
621 | let def: MacroDefId = resolver(self.path.clone()).or_else(|| { | 630 | ) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> { |
622 | error_sink(mbe::ExpandError::Other(format!("could not resolve macro `{}`", self.path))); | 631 | let def: MacroDefId = resolver(call.path.clone()).ok_or(UnresolvedMacro)?; |
623 | None | 632 | |
624 | })?; | 633 | let res = if let MacroDefKind::BuiltInEager(_) = def.kind { |
625 | 634 | let macro_call = InFile::new(call.ast_id.file_id, call.ast_id.to_node(db.upcast())); | |
626 | if let MacroDefKind::BuiltInEager(_) = def.kind { | 635 | let hygiene = Hygiene::new(db.upcast(), call.ast_id.file_id); |
627 | let macro_call = InFile::new(self.ast_id.file_id, self.ast_id.to_node(db.upcast())); | 636 | |
628 | let hygiene = Hygiene::new(db.upcast(), self.ast_id.file_id); | 637 | expand_eager_macro( |
629 | 638 | db.upcast(), | |
630 | Some( | 639 | krate, |
631 | expand_eager_macro( | 640 | macro_call, |
632 | db.upcast(), | 641 | def, |
633 | krate, | 642 | &|path: ast::Path| resolver(path::ModPath::from_src(path, &hygiene)?), |
634 | macro_call, | 643 | error_sink, |
635 | def, | 644 | ) |
636 | &|path: ast::Path| resolver(path::ModPath::from_src(path, &hygiene)?), | 645 | .map(MacroCallId::from) |
637 | error_sink, | 646 | } else { |
638 | ) | 647 | Ok(def.as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike(call.ast_id)).into()) |
639 | .ok()? | 648 | }; |
640 | .into(), | 649 | Ok(res) |
641 | ) | ||
642 | } else { | ||
643 | Some(def.as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike(self.ast_id)).into()) | ||
644 | } | ||
645 | } | ||
646 | } | 650 | } |
647 | 651 | ||
648 | impl AsMacroCall for AstIdWithPath<ast::Item> { | 652 | fn item_attr_as_call_id( |
649 | fn as_call_id_with_errors( | 653 | item_attr: &AstIdWithPath<ast::Item>, |
650 | &self, | 654 | db: &dyn db::DefDatabase, |
651 | db: &dyn db::DefDatabase, | 655 | krate: CrateId, |
652 | krate: CrateId, | 656 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, |
653 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | 657 | ) -> Result<MacroCallId, UnresolvedMacro> { |
654 | error_sink: &mut dyn FnMut(mbe::ExpandError), | 658 | let def: MacroDefId = resolver(item_attr.path.clone()).ok_or(UnresolvedMacro)?; |
655 | ) -> Option<MacroCallId> { | 659 | let last_segment = item_attr.path.segments().last().ok_or(UnresolvedMacro)?; |
656 | let def: MacroDefId = resolver(self.path.clone()).or_else(|| { | 660 | let res = def |
657 | error_sink(mbe::ExpandError::Other(format!("could not resolve macro `{}`", self.path))); | 661 | .as_lazy_macro( |
658 | None | 662 | db.upcast(), |
659 | })?; | 663 | krate, |
660 | 664 | MacroCallKind::Attr(item_attr.ast_id, last_segment.to_string()), | |
661 | Some( | ||
662 | def.as_lazy_macro( | ||
663 | db.upcast(), | ||
664 | krate, | ||
665 | MacroCallKind::Attr(self.ast_id, self.path.segments().last()?.to_string()), | ||
666 | ) | ||
667 | .into(), | ||
668 | ) | 665 | ) |
669 | } | 666 | .into(); |
667 | Ok(res) | ||
670 | } | 668 | } |
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index f92232eb3..6a3456f2e 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs | |||
@@ -417,6 +417,8 @@ mod diagnostics { | |||
417 | 417 | ||
418 | UnresolvedProcMacro { ast: MacroCallKind }, | 418 | UnresolvedProcMacro { ast: MacroCallKind }, |
419 | 419 | ||
420 | UnresolvedMacroCall { ast: AstId<ast::MacroCall> }, | ||
421 | |||
420 | MacroError { ast: MacroCallKind, message: String }, | 422 | MacroError { ast: MacroCallKind, message: String }, |
421 | } | 423 | } |
422 | 424 | ||
@@ -477,6 +479,13 @@ mod diagnostics { | |||
477 | Self { in_module: container, kind: DiagnosticKind::MacroError { ast, message } } | 479 | Self { in_module: container, kind: DiagnosticKind::MacroError { ast, message } } |
478 | } | 480 | } |
479 | 481 | ||
482 | pub(super) fn unresolved_macro_call( | ||
483 | container: LocalModuleId, | ||
484 | ast: AstId<ast::MacroCall>, | ||
485 | ) -> Self { | ||
486 | Self { in_module: container, kind: DiagnosticKind::UnresolvedMacroCall { ast } } | ||
487 | } | ||
488 | |||
480 | pub(super) fn add_to( | 489 | pub(super) fn add_to( |
481 | &self, | 490 | &self, |
482 | db: &dyn DefDatabase, | 491 | db: &dyn DefDatabase, |
@@ -589,6 +598,11 @@ mod diagnostics { | |||
589 | }); | 598 | }); |
590 | } | 599 | } |
591 | 600 | ||
601 | DiagnosticKind::UnresolvedMacroCall { ast } => { | ||
602 | let node = ast.to_node(db.upcast()); | ||
603 | sink.push(UnresolvedMacroCall { file: ast.file_id, node: AstPtr::new(&node) }); | ||
604 | } | ||
605 | |||
592 | DiagnosticKind::MacroError { ast, message } => { | 606 | DiagnosticKind::MacroError { ast, message } => { |
593 | let (file, ast) = match ast { | 607 | let (file, ast) = match ast { |
594 | MacroCallKind::FnLike(ast) => { | 608 | MacroCallKind::FnLike(ast) => { |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 9996a0807..e51d89b43 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -13,7 +13,7 @@ use hir_expand::{ | |||
13 | builtin_macro::find_builtin_macro, | 13 | builtin_macro::find_builtin_macro, |
14 | name::{AsName, Name}, | 14 | name::{AsName, Name}, |
15 | proc_macro::ProcMacroExpander, | 15 | proc_macro::ProcMacroExpander, |
16 | HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, | 16 | HirFileId, MacroCallId, MacroDefId, MacroDefKind, |
17 | }; | 17 | }; |
18 | use hir_expand::{InFile, MacroCallLoc}; | 18 | use hir_expand::{InFile, MacroCallLoc}; |
19 | use rustc_hash::{FxHashMap, FxHashSet}; | 19 | use rustc_hash::{FxHashMap, FxHashSet}; |
@@ -24,11 +24,13 @@ use tt::{Leaf, TokenTree}; | |||
24 | use crate::{ | 24 | use crate::{ |
25 | attr::Attrs, | 25 | attr::Attrs, |
26 | db::DefDatabase, | 26 | db::DefDatabase, |
27 | item_attr_as_call_id, | ||
27 | item_scope::{ImportType, PerNsGlobImports}, | 28 | item_scope::{ImportType, PerNsGlobImports}, |
28 | item_tree::{ | 29 | item_tree::{ |
29 | self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind, | 30 | self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind, |
30 | StructDefKind, | 31 | StructDefKind, |
31 | }, | 32 | }, |
33 | macro_call_as_call_id, | ||
32 | nameres::{ | 34 | nameres::{ |
33 | diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, | 35 | diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, |
34 | BuiltinShadowMode, DefMap, ModuleData, ModuleOrigin, ResolveMode, | 36 | BuiltinShadowMode, DefMap, ModuleData, ModuleOrigin, ResolveMode, |
@@ -36,9 +38,9 @@ use crate::{ | |||
36 | path::{ImportAlias, ModPath, PathKind}, | 38 | path::{ImportAlias, ModPath, PathKind}, |
37 | per_ns::PerNs, | 39 | per_ns::PerNs, |
38 | visibility::{RawVisibility, Visibility}, | 40 | visibility::{RawVisibility, Visibility}, |
39 | AdtId, AsMacroCall, AstId, AstIdWithPath, ConstLoc, ContainerId, EnumLoc, EnumVariantId, | 41 | AdtId, AstId, AstIdWithPath, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, |
40 | FunctionLoc, ImplLoc, Intern, LocalModuleId, ModuleDefId, StaticLoc, StructLoc, TraitLoc, | 42 | ImplLoc, Intern, LocalModuleId, ModuleDefId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, |
41 | TypeAliasLoc, UnionLoc, | 43 | UnionLoc, UnresolvedMacro, |
42 | }; | 44 | }; |
43 | 45 | ||
44 | const GLOB_RECURSION_LIMIT: usize = 100; | 46 | const GLOB_RECURSION_LIMIT: usize = 100; |
@@ -790,8 +792,11 @@ impl DefCollector<'_> { | |||
790 | return false; | 792 | return false; |
791 | } | 793 | } |
792 | 794 | ||
793 | if let Some(call_id) = | 795 | match macro_call_as_call_id( |
794 | directive.ast_id.as_call_id(self.db, self.def_map.krate, |path| { | 796 | &directive.ast_id, |
797 | self.db, | ||
798 | self.def_map.krate, | ||
799 | |path| { | ||
795 | let resolved_res = self.def_map.resolve_path_fp_with_macro( | 800 | let resolved_res = self.def_map.resolve_path_fp_with_macro( |
796 | self.db, | 801 | self.db, |
797 | ResolveMode::Other, | 802 | ResolveMode::Other, |
@@ -800,24 +805,29 @@ impl DefCollector<'_> { | |||
800 | BuiltinShadowMode::Module, | 805 | BuiltinShadowMode::Module, |
801 | ); | 806 | ); |
802 | resolved_res.resolved_def.take_macros() | 807 | resolved_res.resolved_def.take_macros() |
803 | }) | 808 | }, |
804 | { | 809 | &mut |_err| (), |
805 | resolved.push((directive.module_id, call_id, directive.depth)); | 810 | ) { |
806 | res = ReachedFixedPoint::No; | 811 | Ok(Ok(call_id)) => { |
807 | return false; | 812 | resolved.push((directive.module_id, call_id, directive.depth)); |
813 | res = ReachedFixedPoint::No; | ||
814 | return false; | ||
815 | } | ||
816 | Err(UnresolvedMacro) | Ok(Err(_)) => {} | ||
808 | } | 817 | } |
809 | 818 | ||
810 | true | 819 | true |
811 | }); | 820 | }); |
812 | attribute_macros.retain(|directive| { | 821 | attribute_macros.retain(|directive| { |
813 | if let Some(call_id) = | 822 | match item_attr_as_call_id(&directive.ast_id, self.db, self.def_map.krate, |path| { |
814 | directive.ast_id.as_call_id(self.db, self.def_map.krate, |path| { | 823 | self.resolve_attribute_macro(&directive, &path) |
815 | self.resolve_attribute_macro(&directive, &path) | 824 | }) { |
816 | }) | 825 | Ok(call_id) => { |
817 | { | 826 | resolved.push((directive.module_id, call_id, 0)); |
818 | resolved.push((directive.module_id, call_id, 0)); | 827 | res = ReachedFixedPoint::No; |
819 | res = ReachedFixedPoint::No; | 828 | return false; |
820 | return false; | 829 | } |
830 | Err(UnresolvedMacro) => (), | ||
821 | } | 831 | } |
822 | 832 | ||
823 | true | 833 | true |
@@ -902,7 +912,8 @@ impl DefCollector<'_> { | |||
902 | 912 | ||
903 | for directive in &self.unexpanded_macros { | 913 | for directive in &self.unexpanded_macros { |
904 | let mut error = None; | 914 | let mut error = None; |
905 | directive.ast_id.as_call_id_with_errors( | 915 | match macro_call_as_call_id( |
916 | &directive.ast_id, | ||
906 | self.db, | 917 | self.db, |
907 | self.def_map.krate, | 918 | self.def_map.krate, |
908 | |path| { | 919 | |path| { |
@@ -918,15 +929,15 @@ impl DefCollector<'_> { | |||
918 | &mut |e| { | 929 | &mut |e| { |
919 | error.get_or_insert(e); | 930 | error.get_or_insert(e); |
920 | }, | 931 | }, |
921 | ); | 932 | ) { |
922 | 933 | Ok(_) => (), | |
923 | if let Some(err) = error { | 934 | Err(UnresolvedMacro) => { |
924 | self.def_map.diagnostics.push(DefDiagnostic::macro_error( | 935 | self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call( |
925 | directive.module_id, | 936 | directive.module_id, |
926 | MacroCallKind::FnLike(directive.ast_id.ast_id), | 937 | directive.ast_id.ast_id, |
927 | err.to_string(), | 938 | )); |
928 | )); | 939 | } |
929 | } | 940 | }; |
930 | } | 941 | } |
931 | 942 | ||
932 | // Emit diagnostics for all remaining unresolved imports. | 943 | // Emit diagnostics for all remaining unresolved imports. |
@@ -1446,8 +1457,11 @@ impl ModCollector<'_, '_> { | |||
1446 | let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); | 1457 | let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); |
1447 | 1458 | ||
1448 | // Case 1: try to resolve in legacy scope and expand macro_rules | 1459 | // Case 1: try to resolve in legacy scope and expand macro_rules |
1449 | if let Some(macro_call_id) = | 1460 | if let Ok(Ok(macro_call_id)) = macro_call_as_call_id( |
1450 | ast_id.as_call_id(self.def_collector.db, self.def_collector.def_map.krate, |path| { | 1461 | &ast_id, |
1462 | self.def_collector.db, | ||
1463 | self.def_collector.def_map.krate, | ||
1464 | |path| { | ||
1451 | path.as_ident().and_then(|name| { | 1465 | path.as_ident().and_then(|name| { |
1452 | self.def_collector.def_map.with_ancestor_maps( | 1466 | self.def_collector.def_map.with_ancestor_maps( |
1453 | self.def_collector.db, | 1467 | self.def_collector.db, |
@@ -1455,8 +1469,9 @@ impl ModCollector<'_, '_> { | |||
1455 | &mut |map, module| map[module].scope.get_legacy_macro(&name), | 1469 | &mut |map, module| map[module].scope.get_legacy_macro(&name), |
1456 | ) | 1470 | ) |
1457 | }) | 1471 | }) |
1458 | }) | 1472 | }, |
1459 | { | 1473 | &mut |_err| (), |
1474 | ) { | ||
1460 | self.def_collector.unexpanded_macros.push(MacroDirective { | 1475 | self.def_collector.unexpanded_macros.push(MacroDirective { |
1461 | module_id: self.module_id, | 1476 | module_id: self.module_id, |
1462 | ast_id, | 1477 | ast_id, |
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs index fdcdc23ae..dd1db0094 100644 --- a/crates/hir_def/src/nameres/path_resolution.rs +++ b/crates/hir_def/src/nameres/path_resolution.rs | |||
@@ -77,7 +77,7 @@ impl DefMap { | |||
77 | original_module: LocalModuleId, | 77 | original_module: LocalModuleId, |
78 | visibility: &RawVisibility, | 78 | visibility: &RawVisibility, |
79 | ) -> Option<Visibility> { | 79 | ) -> Option<Visibility> { |
80 | match visibility { | 80 | let mut vis = match visibility { |
81 | RawVisibility::Module(path) => { | 81 | RawVisibility::Module(path) => { |
82 | let (result, remaining) = | 82 | let (result, remaining) = |
83 | self.resolve_path(db, original_module, &path, BuiltinShadowMode::Module); | 83 | self.resolve_path(db, original_module, &path, BuiltinShadowMode::Module); |
@@ -86,15 +86,28 @@ impl DefMap { | |||
86 | } | 86 | } |
87 | let types = result.take_types()?; | 87 | let types = result.take_types()?; |
88 | match types { | 88 | match types { |
89 | ModuleDefId::ModuleId(m) => Some(Visibility::Module(m)), | 89 | ModuleDefId::ModuleId(m) => Visibility::Module(m), |
90 | _ => { | 90 | _ => { |
91 | // error: visibility needs to refer to module | 91 | // error: visibility needs to refer to module |
92 | None | 92 | return None; |
93 | } | 93 | } |
94 | } | 94 | } |
95 | } | 95 | } |
96 | RawVisibility::Public => Some(Visibility::Public), | 96 | RawVisibility::Public => Visibility::Public, |
97 | }; | ||
98 | |||
99 | // In block expressions, `self` normally refers to the containing non-block module, and | ||
100 | // `super` to its parent (etc.). However, visibilities must only refer to a module in the | ||
101 | // DefMap they're written in, so we restrict them when that happens. | ||
102 | if let Visibility::Module(m) = vis { | ||
103 | if self.block_id() != m.block { | ||
104 | mark::hit!(adjust_vis_in_block_def_map); | ||
105 | vis = Visibility::Module(self.module_id(self.root())); | ||
106 | log::debug!("visibility {:?} points outside DefMap, adjusting to {:?}", m, vis); | ||
107 | } | ||
97 | } | 108 | } |
109 | |||
110 | Some(vis) | ||
98 | } | 111 | } |
99 | 112 | ||
100 | // Returns Yes if we are sure that additions to `ItemMap` wouldn't change | 113 | // Returns Yes if we are sure that additions to `ItemMap` wouldn't change |
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index 57bc6fbd7..eb57ea7d6 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs | |||
@@ -6,7 +6,7 @@ use crate::{ | |||
6 | 6 | ||
7 | use base_db::{AnchoredPath, FileId}; | 7 | use base_db::{AnchoredPath, FileId}; |
8 | use either::Either; | 8 | use either::Either; |
9 | use mbe::{parse_to_token_tree, ExpandResult}; | 9 | use mbe::{parse_exprs_with_sep, parse_to_token_tree, ExpandResult}; |
10 | use parser::FragmentKind; | 10 | use parser::FragmentKind; |
11 | use syntax::ast::{self, AstToken}; | 11 | use syntax::ast::{self, AstToken}; |
12 | 12 | ||
@@ -182,25 +182,10 @@ fn assert_expand( | |||
182 | // ```, | 182 | // ```, |
183 | // which is wrong but useful. | 183 | // which is wrong but useful. |
184 | 184 | ||
185 | let mut args = Vec::new(); | 185 | let args = parse_exprs_with_sep(tt, ','); |
186 | let mut current = Vec::new(); | ||
187 | for tt in tt.token_trees.iter().cloned() { | ||
188 | match tt { | ||
189 | tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => { | ||
190 | args.push(current); | ||
191 | current = Vec::new(); | ||
192 | } | ||
193 | _ => { | ||
194 | current.push(tt); | ||
195 | } | ||
196 | } | ||
197 | } | ||
198 | if !current.is_empty() { | ||
199 | args.push(current); | ||
200 | } | ||
201 | 186 | ||
202 | let arg_tts = args.into_iter().flat_map(|arg| { | 187 | let arg_tts = args.into_iter().flat_map(|arg| { |
203 | quote! { &(##arg), } | 188 | quote! { &(#arg), } |
204 | }.token_trees).collect::<Vec<_>>(); | 189 | }.token_trees).collect::<Vec<_>>(); |
205 | 190 | ||
206 | let expanded = quote! { | 191 | let expanded = quote! { |
@@ -238,35 +223,21 @@ fn format_args_expand( | |||
238 | // ]) | 223 | // ]) |
239 | // ```, | 224 | // ```, |
240 | // which is still not really correct, but close enough for now | 225 | // which is still not really correct, but close enough for now |
241 | let mut args = Vec::new(); | 226 | let mut args = parse_exprs_with_sep(tt, ','); |
242 | let mut current = Vec::new(); | 227 | |
243 | for tt in tt.token_trees.iter().cloned() { | ||
244 | match tt { | ||
245 | tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => { | ||
246 | args.push(current); | ||
247 | current = Vec::new(); | ||
248 | } | ||
249 | _ => { | ||
250 | current.push(tt); | ||
251 | } | ||
252 | } | ||
253 | } | ||
254 | if !current.is_empty() { | ||
255 | args.push(current); | ||
256 | } | ||
257 | if args.is_empty() { | 228 | if args.is_empty() { |
258 | return ExpandResult::only_err(mbe::ExpandError::NoMatchingRule); | 229 | return ExpandResult::only_err(mbe::ExpandError::NoMatchingRule); |
259 | } | 230 | } |
260 | for arg in &mut args { | 231 | for arg in &mut args { |
261 | // Remove `key =`. | 232 | // Remove `key =`. |
262 | if matches!(arg.get(1), Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p))) if p.char == '=' && p.spacing != tt::Spacing::Joint) | 233 | if matches!(arg.token_trees.get(1), Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p))) if p.char == '=' && p.spacing != tt::Spacing::Joint) |
263 | { | 234 | { |
264 | arg.drain(..2); | 235 | arg.token_trees.drain(..2); |
265 | } | 236 | } |
266 | } | 237 | } |
267 | let _format_string = args.remove(0); | 238 | let _format_string = args.remove(0); |
268 | let arg_tts = args.into_iter().flat_map(|arg| { | 239 | let arg_tts = args.into_iter().flat_map(|arg| { |
269 | quote! { std::fmt::ArgumentV1::new(&(##arg), std::fmt::Display::fmt), } | 240 | quote! { std::fmt::ArgumentV1::new(&(#arg), std::fmt::Display::fmt), } |
270 | }.token_trees).collect::<Vec<_>>(); | 241 | }.token_trees).collect::<Vec<_>>(); |
271 | let expanded = quote! { | 242 | let expanded = quote! { |
272 | std::fmt::Arguments::new_v1(&[], &[##arg_tts]) | 243 | std::fmt::Arguments::new_v1(&[], &[##arg_tts]) |
@@ -720,6 +691,25 @@ mod tests { | |||
720 | } | 691 | } |
721 | 692 | ||
722 | #[test] | 693 | #[test] |
694 | fn test_format_args_expand_with_comma_exprs() { | ||
695 | let expanded = expand_builtin_macro( | ||
696 | r#" | ||
697 | #[rustc_builtin_macro] | ||
698 | macro_rules! format_args { | ||
699 | ($fmt:expr) => ({ /* compiler built-in */ }); | ||
700 | ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) | ||
701 | } | ||
702 | format_args!("{} {:?}", a::<A,B>(), b); | ||
703 | "#, | ||
704 | ); | ||
705 | |||
706 | assert_eq!( | ||
707 | expanded, | ||
708 | 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),])"# | ||
709 | ); | ||
710 | } | ||
711 | |||
712 | #[test] | ||
723 | fn test_include_bytes_expand() { | 713 | fn test_include_bytes_expand() { |
724 | let expanded = expand_builtin_macro( | 714 | let expanded = expand_builtin_macro( |
725 | r#" | 715 | r#" |
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs index c7609e90d..c94fb580a 100644 --- a/crates/hir_expand/src/name.rs +++ b/crates/hir_expand/src/name.rs | |||
@@ -189,6 +189,7 @@ pub mod known { | |||
189 | // Components of known path (function name) | 189 | // Components of known path (function name) |
190 | filter_map, | 190 | filter_map, |
191 | next, | 191 | next, |
192 | iter_mut, | ||
192 | // Builtin macros | 193 | // Builtin macros |
193 | file, | 194 | file, |
194 | column, | 195 | column, |
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs index ece68183e..be1fd1f13 100644 --- a/crates/hir_ty/src/autoderef.rs +++ b/crates/hir_ty/src/autoderef.rs | |||
@@ -81,7 +81,7 @@ fn deref_by_trait( | |||
81 | 81 | ||
82 | // Now do the assoc type projection | 82 | // Now do the assoc type projection |
83 | let projection = super::traits::ProjectionPredicate { | 83 | let projection = super::traits::ProjectionPredicate { |
84 | ty: Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len())), | 84 | ty: Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len())), |
85 | projection_ty: super::ProjectionTy { associated_ty: target, parameters }, | 85 | projection_ty: super::ProjectionTy { associated_ty: target, parameters }, |
86 | }; | 86 | }; |
87 | 87 | ||
@@ -89,8 +89,10 @@ fn deref_by_trait( | |||
89 | 89 | ||
90 | let in_env = InEnvironment { value: obligation, environment: ty.environment }; | 90 | let in_env = InEnvironment { value: obligation, environment: ty.environment }; |
91 | 91 | ||
92 | let canonical = | 92 | let canonical = Canonical::new( |
93 | Canonical::new(in_env, ty.value.kinds.iter().copied().chain(Some(super::TyKind::General))); | 93 | in_env, |
94 | ty.value.kinds.iter().copied().chain(Some(chalk_ir::TyVariableKind::General)), | ||
95 | ); | ||
94 | 96 | ||
95 | let solution = db.trait_solve(krate, canonical)?; | 97 | let solution = db.trait_solve(krate, canonical)?; |
96 | 98 | ||
@@ -112,7 +114,8 @@ fn deref_by_trait( | |||
112 | // new variables in that case | 114 | // new variables in that case |
113 | 115 | ||
114 | for i in 1..vars.0.kinds.len() { | 116 | for i in 1..vars.0.kinds.len() { |
115 | if vars.0.value[i - 1] != Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) | 117 | if vars.0.value[i - 1] |
118 | != Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) | ||
116 | { | 119 | { |
117 | warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution); | 120 | warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution); |
118 | return None; | 121 | return None; |
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs index d740b7265..66a88e2b6 100644 --- a/crates/hir_ty/src/diagnostics/expr.rs +++ b/crates/hir_ty/src/diagnostics/expr.rs | |||
@@ -17,7 +17,7 @@ use crate::{ | |||
17 | MissingPatFields, RemoveThisSemicolon, | 17 | MissingPatFields, RemoveThisSemicolon, |
18 | }, | 18 | }, |
19 | utils::variant_data, | 19 | utils::variant_data, |
20 | ApplicationTy, InferenceResult, Ty, TypeCtor, | 20 | InferenceResult, Ty, |
21 | }; | 21 | }; |
22 | 22 | ||
23 | pub(crate) use hir_def::{ | 23 | pub(crate) use hir_def::{ |
@@ -381,14 +381,11 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
381 | _ => return, | 381 | _ => return, |
382 | }; | 382 | }; |
383 | 383 | ||
384 | let core_result_ctor = TypeCtor::Adt(AdtId::EnumId(core_result_enum)); | 384 | let (params, required) = match mismatch.expected { |
385 | let core_option_ctor = TypeCtor::Adt(AdtId::EnumId(core_option_enum)); | 385 | Ty::Adt(AdtId::EnumId(enum_id), ref parameters) if enum_id == core_result_enum => { |
386 | |||
387 | let (params, required) = match &mismatch.expected { | ||
388 | Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &core_result_ctor => { | ||
389 | (parameters, "Ok".to_string()) | 386 | (parameters, "Ok".to_string()) |
390 | } | 387 | } |
391 | Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &core_option_ctor => { | 388 | Ty::Adt(AdtId::EnumId(enum_id), ref parameters) if enum_id == core_option_enum => { |
392 | (parameters, "Some".to_string()) | 389 | (parameters, "Some".to_string()) |
393 | } | 390 | } |
394 | _ => return, | 391 | _ => return, |
diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs index 1c1423fbf..86fee0050 100644 --- a/crates/hir_ty/src/diagnostics/match_check.rs +++ b/crates/hir_ty/src/diagnostics/match_check.rs | |||
@@ -227,7 +227,7 @@ use hir_def::{ | |||
227 | use la_arena::Idx; | 227 | use la_arena::Idx; |
228 | use smallvec::{smallvec, SmallVec}; | 228 | use smallvec::{smallvec, SmallVec}; |
229 | 229 | ||
230 | use crate::{db::HirDatabase, ApplicationTy, InferenceResult, Ty, TypeCtor}; | 230 | use crate::{db::HirDatabase, InferenceResult, Ty}; |
231 | 231 | ||
232 | #[derive(Debug, Clone, Copy)] | 232 | #[derive(Debug, Clone, Copy)] |
233 | /// Either a pattern from the source code being analyzed, represented as | 233 | /// Either a pattern from the source code being analyzed, represented as |
@@ -627,14 +627,12 @@ pub(super) fn is_useful( | |||
627 | // - `!` type | 627 | // - `!` type |
628 | // In those cases, no match arm is useful. | 628 | // In those cases, no match arm is useful. |
629 | match cx.infer[cx.match_expr].strip_references() { | 629 | match cx.infer[cx.match_expr].strip_references() { |
630 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(AdtId::EnumId(enum_id)), .. }) => { | 630 | Ty::Adt(AdtId::EnumId(enum_id), ..) => { |
631 | if cx.db.enum_data(*enum_id).variants.is_empty() { | 631 | if cx.db.enum_data(*enum_id).variants.is_empty() { |
632 | return Ok(Usefulness::NotUseful); | 632 | return Ok(Usefulness::NotUseful); |
633 | } | 633 | } |
634 | } | 634 | } |
635 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. }) => { | 635 | Ty::Never => return Ok(Usefulness::NotUseful), |
636 | return Ok(Usefulness::NotUseful); | ||
637 | } | ||
638 | _ => (), | 636 | _ => (), |
639 | } | 637 | } |
640 | 638 | ||
diff --git a/crates/hir_ty/src/diagnostics/unsafe_check.rs b/crates/hir_ty/src/diagnostics/unsafe_check.rs index 9c506112d..e77a20fea 100644 --- a/crates/hir_ty/src/diagnostics/unsafe_check.rs +++ b/crates/hir_ty/src/diagnostics/unsafe_check.rs | |||
@@ -11,9 +11,7 @@ use hir_def::{ | |||
11 | }; | 11 | }; |
12 | use hir_expand::diagnostics::DiagnosticSink; | 12 | use hir_expand::diagnostics::DiagnosticSink; |
13 | 13 | ||
14 | use crate::{ | 14 | use crate::{db::HirDatabase, diagnostics::MissingUnsafe, InferenceResult, Ty}; |
15 | db::HirDatabase, diagnostics::MissingUnsafe, ApplicationTy, InferenceResult, Ty, TypeCtor, | ||
16 | }; | ||
17 | 15 | ||
18 | pub(super) struct UnsafeValidator<'a, 'b: 'a> { | 16 | pub(super) struct UnsafeValidator<'a, 'b: 'a> { |
19 | owner: DefWithBodyId, | 17 | owner: DefWithBodyId, |
@@ -112,7 +110,7 @@ fn walk_unsafe( | |||
112 | } | 110 | } |
113 | } | 111 | } |
114 | Expr::UnaryOp { expr, op: UnaryOp::Deref } => { | 112 | Expr::UnaryOp { expr, op: UnaryOp::Deref } => { |
115 | if let Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. }) = &infer[*expr] { | 113 | if let Ty::Raw(..) = &infer[*expr] { |
116 | unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); | 114 | unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); |
117 | } | 115 | } |
118 | } | 116 | } |
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 271fcbfaf..f3a4333cb 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -3,8 +3,9 @@ | |||
3 | use std::{borrow::Cow, fmt}; | 3 | use std::{borrow::Cow, fmt}; |
4 | 4 | ||
5 | use crate::{ | 5 | use crate::{ |
6 | db::HirDatabase, utils::generics, ApplicationTy, CallableDefId, FnSig, GenericPredicate, | 6 | db::HirDatabase, primitive, utils::generics, AliasTy, CallableDefId, CallableSig, |
7 | Lifetime, Obligation, OpaqueTy, OpaqueTyId, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, | 7 | GenericPredicate, Lifetime, Obligation, OpaqueTy, OpaqueTyId, ProjectionTy, Scalar, Substs, |
8 | TraitRef, Ty, | ||
8 | }; | 9 | }; |
9 | use arrayvec::ArrayVec; | 10 | use arrayvec::ArrayVec; |
10 | use hir_def::{ | 11 | use hir_def::{ |
@@ -234,36 +235,62 @@ impl HirDisplay for &Ty { | |||
234 | } | 235 | } |
235 | } | 236 | } |
236 | 237 | ||
237 | impl HirDisplay for ApplicationTy { | 238 | impl HirDisplay for ProjectionTy { |
239 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
240 | if f.should_truncate() { | ||
241 | return write!(f, "{}", TYPE_HINT_TRUNCATION); | ||
242 | } | ||
243 | |||
244 | let trait_ = f.db.trait_data(self.trait_(f.db)); | ||
245 | let first_parameter = self.parameters[0].into_displayable( | ||
246 | f.db, | ||
247 | f.max_size, | ||
248 | f.omit_verbose_types, | ||
249 | f.display_target, | ||
250 | ); | ||
251 | write!(f, "<{} as {}", first_parameter, trait_.name)?; | ||
252 | if self.parameters.len() > 1 { | ||
253 | write!(f, "<")?; | ||
254 | f.write_joined(&self.parameters[1..], ", ")?; | ||
255 | write!(f, ">")?; | ||
256 | } | ||
257 | write!(f, ">::{}", f.db.type_alias_data(self.associated_ty).name)?; | ||
258 | Ok(()) | ||
259 | } | ||
260 | } | ||
261 | |||
262 | impl HirDisplay for Ty { | ||
238 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 263 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
239 | if f.should_truncate() { | 264 | if f.should_truncate() { |
240 | return write!(f, "{}", TYPE_HINT_TRUNCATION); | 265 | return write!(f, "{}", TYPE_HINT_TRUNCATION); |
241 | } | 266 | } |
242 | 267 | ||
243 | match self.ctor { | 268 | match self { |
244 | TypeCtor::Bool => write!(f, "bool")?, | 269 | Ty::Never => write!(f, "!")?, |
245 | TypeCtor::Char => write!(f, "char")?, | 270 | Ty::Str => write!(f, "str")?, |
246 | TypeCtor::Int(t) => write!(f, "{}", t)?, | 271 | Ty::Scalar(Scalar::Bool) => write!(f, "bool")?, |
247 | TypeCtor::Float(t) => write!(f, "{}", t)?, | 272 | Ty::Scalar(Scalar::Char) => write!(f, "char")?, |
248 | TypeCtor::Str => write!(f, "str")?, | 273 | &Ty::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?, |
249 | TypeCtor::Slice => { | 274 | &Ty::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?, |
250 | let t = self.parameters.as_single(); | 275 | &Ty::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?, |
276 | Ty::Slice(parameters) => { | ||
277 | let t = parameters.as_single(); | ||
251 | write!(f, "[")?; | 278 | write!(f, "[")?; |
252 | t.hir_fmt(f)?; | 279 | t.hir_fmt(f)?; |
253 | write!(f, "]")?; | 280 | write!(f, "]")?; |
254 | } | 281 | } |
255 | TypeCtor::Array => { | 282 | Ty::Array(parameters) => { |
256 | let t = self.parameters.as_single(); | 283 | let t = parameters.as_single(); |
257 | write!(f, "[")?; | 284 | write!(f, "[")?; |
258 | t.hir_fmt(f)?; | 285 | t.hir_fmt(f)?; |
259 | write!(f, "; _]")?; | 286 | write!(f, "; _]")?; |
260 | } | 287 | } |
261 | TypeCtor::RawPtr(m) | TypeCtor::Ref(m) => { | 288 | Ty::Raw(m, parameters) | Ty::Ref(m, parameters) => { |
262 | let t = self.parameters.as_single(); | 289 | let t = parameters.as_single(); |
263 | let ty_display = | 290 | let ty_display = |
264 | t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); | 291 | t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); |
265 | 292 | ||
266 | if matches!(self.ctor, TypeCtor::RawPtr(_)) { | 293 | if matches!(self, Ty::Raw(..)) { |
267 | write!(f, "*{}", m.as_keyword_for_ptr())?; | 294 | write!(f, "*{}", m.as_keyword_for_ptr())?; |
268 | } else { | 295 | } else { |
269 | write!(f, "&{}", m.as_keyword_for_ref())?; | 296 | write!(f, "&{}", m.as_keyword_for_ref())?; |
@@ -274,10 +301,10 @@ impl HirDisplay for ApplicationTy { | |||
274 | Ty::Dyn(predicates) if predicates.len() > 1 => { | 301 | Ty::Dyn(predicates) if predicates.len() > 1 => { |
275 | Cow::Borrowed(predicates.as_ref()) | 302 | Cow::Borrowed(predicates.as_ref()) |
276 | } | 303 | } |
277 | &Ty::Opaque(OpaqueTy { | 304 | &Ty::Alias(AliasTy::Opaque(OpaqueTy { |
278 | opaque_ty_id: OpaqueTyId::ReturnTypeImplTrait(func, idx), | 305 | opaque_ty_id: OpaqueTyId::ReturnTypeImplTrait(func, idx), |
279 | ref parameters, | 306 | ref parameters, |
280 | }) => { | 307 | })) => { |
281 | datas = | 308 | datas = |
282 | f.db.return_type_impl_traits(func).expect("impl trait id without data"); | 309 | f.db.return_type_impl_traits(func).expect("impl trait id without data"); |
283 | let data = (*datas) | 310 | let data = (*datas) |
@@ -304,25 +331,24 @@ impl HirDisplay for ApplicationTy { | |||
304 | write!(f, "{}", ty_display)?; | 331 | write!(f, "{}", ty_display)?; |
305 | } | 332 | } |
306 | } | 333 | } |
307 | TypeCtor::Never => write!(f, "!")?, | 334 | Ty::Tuple(_, substs) => { |
308 | TypeCtor::Tuple { .. } => { | 335 | if substs.len() == 1 { |
309 | let ts = &self.parameters; | ||
310 | if ts.len() == 1 { | ||
311 | write!(f, "(")?; | 336 | write!(f, "(")?; |
312 | ts[0].hir_fmt(f)?; | 337 | substs[0].hir_fmt(f)?; |
313 | write!(f, ",)")?; | 338 | write!(f, ",)")?; |
314 | } else { | 339 | } else { |
315 | write!(f, "(")?; | 340 | write!(f, "(")?; |
316 | f.write_joined(&*ts.0, ", ")?; | 341 | f.write_joined(&*substs.0, ", ")?; |
317 | write!(f, ")")?; | 342 | write!(f, ")")?; |
318 | } | 343 | } |
319 | } | 344 | } |
320 | TypeCtor::FnPtr { is_varargs, .. } => { | 345 | Ty::Function(fn_ptr) => { |
321 | let sig = FnSig::from_fn_ptr_substs(&self.parameters, is_varargs); | 346 | let sig = CallableSig::from_fn_ptr(fn_ptr); |
322 | sig.hir_fmt(f)?; | 347 | sig.hir_fmt(f)?; |
323 | } | 348 | } |
324 | TypeCtor::FnDef(def) => { | 349 | Ty::FnDef(def, parameters) => { |
325 | let sig = f.db.callable_item_signature(def).subst(&self.parameters); | 350 | let def = *def; |
351 | let sig = f.db.callable_item_signature(def).subst(parameters); | ||
326 | match def { | 352 | match def { |
327 | CallableDefId::FunctionId(ff) => { | 353 | CallableDefId::FunctionId(ff) => { |
328 | write!(f, "fn {}", f.db.function_data(ff).name)? | 354 | write!(f, "fn {}", f.db.function_data(ff).name)? |
@@ -332,7 +358,7 @@ impl HirDisplay for ApplicationTy { | |||
332 | write!(f, "{}", f.db.enum_data(e.parent).variants[e.local_id].name)? | 358 | write!(f, "{}", f.db.enum_data(e.parent).variants[e.local_id].name)? |
333 | } | 359 | } |
334 | }; | 360 | }; |
335 | if self.parameters.len() > 0 { | 361 | if parameters.len() > 0 { |
336 | let generics = generics(f.db.upcast(), def.into()); | 362 | let generics = generics(f.db.upcast(), def.into()); |
337 | let (parent_params, self_param, type_params, _impl_trait_params) = | 363 | let (parent_params, self_param, type_params, _impl_trait_params) = |
338 | generics.provenance_split(); | 364 | generics.provenance_split(); |
@@ -340,7 +366,7 @@ impl HirDisplay for ApplicationTy { | |||
340 | // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self? | 366 | // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self? |
341 | if total_len > 0 { | 367 | if total_len > 0 { |
342 | write!(f, "<")?; | 368 | write!(f, "<")?; |
343 | f.write_joined(&self.parameters.0[..total_len], ", ")?; | 369 | f.write_joined(¶meters.0[..total_len], ", ")?; |
344 | write!(f, ">")?; | 370 | write!(f, ">")?; |
345 | } | 371 | } |
346 | } | 372 | } |
@@ -359,10 +385,10 @@ impl HirDisplay for ApplicationTy { | |||
359 | write!(f, " -> {}", ret_display)?; | 385 | write!(f, " -> {}", ret_display)?; |
360 | } | 386 | } |
361 | } | 387 | } |
362 | TypeCtor::Adt(def_id) => { | 388 | Ty::Adt(def_id, parameters) => { |
363 | match f.display_target { | 389 | match f.display_target { |
364 | DisplayTarget::Diagnostics | DisplayTarget::Test => { | 390 | DisplayTarget::Diagnostics | DisplayTarget::Test => { |
365 | let name = match def_id { | 391 | let name = match *def_id { |
366 | AdtId::StructId(it) => f.db.struct_data(it).name.clone(), | 392 | AdtId::StructId(it) => f.db.struct_data(it).name.clone(), |
367 | AdtId::UnionId(it) => f.db.union_data(it).name.clone(), | 393 | AdtId::UnionId(it) => f.db.union_data(it).name.clone(), |
368 | AdtId::EnumId(it) => f.db.enum_data(it).name.clone(), | 394 | AdtId::EnumId(it) => f.db.enum_data(it).name.clone(), |
@@ -372,7 +398,7 @@ impl HirDisplay for ApplicationTy { | |||
372 | DisplayTarget::SourceCode { module_id } => { | 398 | DisplayTarget::SourceCode { module_id } => { |
373 | if let Some(path) = find_path::find_path( | 399 | if let Some(path) = find_path::find_path( |
374 | f.db.upcast(), | 400 | f.db.upcast(), |
375 | ItemInNs::Types(def_id.into()), | 401 | ItemInNs::Types((*def_id).into()), |
376 | module_id, | 402 | module_id, |
377 | ) { | 403 | ) { |
378 | write!(f, "{}", path)?; | 404 | write!(f, "{}", path)?; |
@@ -384,19 +410,18 @@ impl HirDisplay for ApplicationTy { | |||
384 | } | 410 | } |
385 | } | 411 | } |
386 | 412 | ||
387 | if self.parameters.len() > 0 { | 413 | if parameters.len() > 0 { |
388 | let parameters_to_write = | 414 | let parameters_to_write = |
389 | if f.display_target.is_source_code() || f.omit_verbose_types() { | 415 | if f.display_target.is_source_code() || f.omit_verbose_types() { |
390 | match self | 416 | match self |
391 | .ctor | ||
392 | .as_generic_def() | 417 | .as_generic_def() |
393 | .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) | 418 | .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) |
394 | .filter(|defaults| !defaults.is_empty()) | 419 | .filter(|defaults| !defaults.is_empty()) |
395 | { | 420 | { |
396 | None => self.parameters.0.as_ref(), | 421 | None => parameters.0.as_ref(), |
397 | Some(default_parameters) => { | 422 | Some(default_parameters) => { |
398 | let mut default_from = 0; | 423 | let mut default_from = 0; |
399 | for (i, parameter) in self.parameters.iter().enumerate() { | 424 | for (i, parameter) in parameters.iter().enumerate() { |
400 | match (parameter, default_parameters.get(i)) { | 425 | match (parameter, default_parameters.get(i)) { |
401 | (&Ty::Unknown, _) | (_, None) => { | 426 | (&Ty::Unknown, _) | (_, None) => { |
402 | default_from = i + 1; | 427 | default_from = i + 1; |
@@ -404,18 +429,18 @@ impl HirDisplay for ApplicationTy { | |||
404 | (_, Some(default_parameter)) => { | 429 | (_, Some(default_parameter)) => { |
405 | let actual_default = default_parameter | 430 | let actual_default = default_parameter |
406 | .clone() | 431 | .clone() |
407 | .subst(&self.parameters.prefix(i)); | 432 | .subst(¶meters.prefix(i)); |
408 | if parameter != &actual_default { | 433 | if parameter != &actual_default { |
409 | default_from = i + 1; | 434 | default_from = i + 1; |
410 | } | 435 | } |
411 | } | 436 | } |
412 | } | 437 | } |
413 | } | 438 | } |
414 | &self.parameters.0[0..default_from] | 439 | ¶meters.0[0..default_from] |
415 | } | 440 | } |
416 | } | 441 | } |
417 | } else { | 442 | } else { |
418 | self.parameters.0.as_ref() | 443 | parameters.0.as_ref() |
419 | }; | 444 | }; |
420 | if !parameters_to_write.is_empty() { | 445 | if !parameters_to_write.is_empty() { |
421 | write!(f, "<")?; | 446 | write!(f, "<")?; |
@@ -424,61 +449,54 @@ impl HirDisplay for ApplicationTy { | |||
424 | } | 449 | } |
425 | } | 450 | } |
426 | } | 451 | } |
427 | TypeCtor::AssociatedType(type_alias) => { | 452 | Ty::AssociatedType(type_alias, parameters) => { |
428 | let trait_ = match type_alias.lookup(f.db.upcast()).container { | 453 | let trait_ = match type_alias.lookup(f.db.upcast()).container { |
429 | AssocContainerId::TraitId(it) => it, | 454 | AssocContainerId::TraitId(it) => it, |
430 | _ => panic!("not an associated type"), | 455 | _ => panic!("not an associated type"), |
431 | }; | 456 | }; |
432 | let trait_ = f.db.trait_data(trait_); | 457 | let trait_ = f.db.trait_data(trait_); |
433 | let type_alias_data = f.db.type_alias_data(type_alias); | 458 | let type_alias_data = f.db.type_alias_data(*type_alias); |
434 | 459 | ||
435 | // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) | 460 | // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) |
436 | if f.display_target.is_test() { | 461 | if f.display_target.is_test() { |
437 | write!(f, "{}::{}", trait_.name, type_alias_data.name)?; | 462 | write!(f, "{}::{}", trait_.name, type_alias_data.name)?; |
438 | if self.parameters.len() > 0 { | 463 | if parameters.len() > 0 { |
439 | write!(f, "<")?; | 464 | write!(f, "<")?; |
440 | f.write_joined(&*self.parameters.0, ", ")?; | 465 | f.write_joined(&*parameters.0, ", ")?; |
441 | write!(f, ">")?; | 466 | write!(f, ">")?; |
442 | } | 467 | } |
443 | } else { | 468 | } else { |
444 | let projection_ty = ProjectionTy { | 469 | let projection_ty = |
445 | associated_ty: type_alias, | 470 | ProjectionTy { associated_ty: *type_alias, parameters: parameters.clone() }; |
446 | parameters: self.parameters.clone(), | ||
447 | }; | ||
448 | 471 | ||
449 | projection_ty.hir_fmt(f)?; | 472 | projection_ty.hir_fmt(f)?; |
450 | } | 473 | } |
451 | } | 474 | } |
452 | TypeCtor::ForeignType(type_alias) => { | 475 | Ty::ForeignType(type_alias) => { |
453 | let type_alias = f.db.type_alias_data(type_alias); | 476 | let type_alias = f.db.type_alias_data(*type_alias); |
454 | write!(f, "{}", type_alias.name)?; | 477 | write!(f, "{}", type_alias.name)?; |
455 | if self.parameters.len() > 0 { | ||
456 | write!(f, "<")?; | ||
457 | f.write_joined(&*self.parameters.0, ", ")?; | ||
458 | write!(f, ">")?; | ||
459 | } | ||
460 | } | 478 | } |
461 | TypeCtor::OpaqueType(opaque_ty_id) => { | 479 | Ty::OpaqueType(opaque_ty_id, parameters) => { |
462 | match opaque_ty_id { | 480 | match opaque_ty_id { |
463 | OpaqueTyId::ReturnTypeImplTrait(func, idx) => { | 481 | &OpaqueTyId::ReturnTypeImplTrait(func, idx) => { |
464 | let datas = | 482 | let datas = |
465 | f.db.return_type_impl_traits(func).expect("impl trait id without data"); | 483 | f.db.return_type_impl_traits(func).expect("impl trait id without data"); |
466 | let data = (*datas) | 484 | let data = (*datas) |
467 | .as_ref() | 485 | .as_ref() |
468 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); | 486 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); |
469 | let bounds = data.subst(&self.parameters); | 487 | let bounds = data.subst(¶meters); |
470 | write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; | 488 | write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; |
471 | // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution | 489 | // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution |
472 | } | 490 | } |
473 | OpaqueTyId::AsyncBlockTypeImplTrait(..) => { | 491 | OpaqueTyId::AsyncBlockTypeImplTrait(..) => { |
474 | write!(f, "impl Future<Output = ")?; | 492 | write!(f, "impl Future<Output = ")?; |
475 | self.parameters[0].hir_fmt(f)?; | 493 | parameters[0].hir_fmt(f)?; |
476 | write!(f, ">")?; | 494 | write!(f, ">")?; |
477 | } | 495 | } |
478 | } | 496 | } |
479 | } | 497 | } |
480 | TypeCtor::Closure { .. } => { | 498 | Ty::Closure(.., substs) => { |
481 | let sig = self.parameters[0].callable_sig(f.db); | 499 | let sig = substs[0].callable_sig(f.db); |
482 | if let Some(sig) = sig { | 500 | if let Some(sig) = sig { |
483 | if sig.params().is_empty() { | 501 | if sig.params().is_empty() { |
484 | write!(f, "||")?; | 502 | write!(f, "||")?; |
@@ -501,44 +519,6 @@ impl HirDisplay for ApplicationTy { | |||
501 | write!(f, "{{closure}}")?; | 519 | write!(f, "{{closure}}")?; |
502 | } | 520 | } |
503 | } | 521 | } |
504 | } | ||
505 | Ok(()) | ||
506 | } | ||
507 | } | ||
508 | |||
509 | impl HirDisplay for ProjectionTy { | ||
510 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
511 | if f.should_truncate() { | ||
512 | return write!(f, "{}", TYPE_HINT_TRUNCATION); | ||
513 | } | ||
514 | |||
515 | let trait_ = f.db.trait_data(self.trait_(f.db)); | ||
516 | let first_parameter = self.parameters[0].into_displayable( | ||
517 | f.db, | ||
518 | f.max_size, | ||
519 | f.omit_verbose_types, | ||
520 | f.display_target, | ||
521 | ); | ||
522 | write!(f, "<{} as {}", first_parameter, trait_.name)?; | ||
523 | if self.parameters.len() > 1 { | ||
524 | write!(f, "<")?; | ||
525 | f.write_joined(&self.parameters[1..], ", ")?; | ||
526 | write!(f, ">")?; | ||
527 | } | ||
528 | write!(f, ">::{}", f.db.type_alias_data(self.associated_ty).name)?; | ||
529 | Ok(()) | ||
530 | } | ||
531 | } | ||
532 | |||
533 | impl HirDisplay for Ty { | ||
534 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
535 | if f.should_truncate() { | ||
536 | return write!(f, "{}", TYPE_HINT_TRUNCATION); | ||
537 | } | ||
538 | |||
539 | match self { | ||
540 | Ty::Apply(a_ty) => a_ty.hir_fmt(f)?, | ||
541 | Ty::Projection(p_ty) => p_ty.hir_fmt(f)?, | ||
542 | Ty::Placeholder(id) => { | 522 | Ty::Placeholder(id) => { |
543 | let generics = generics(f.db.upcast(), id.parent); | 523 | let generics = generics(f.db.upcast(), id.parent); |
544 | let param_data = &generics.params.types[id.local_id]; | 524 | let param_data = &generics.params.types[id.local_id]; |
@@ -557,11 +537,12 @@ impl HirDisplay for Ty { | |||
557 | } | 537 | } |
558 | } | 538 | } |
559 | } | 539 | } |
560 | Ty::Bound(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, | 540 | Ty::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, |
561 | Ty::Dyn(predicates) => { | 541 | Ty::Dyn(predicates) => { |
562 | write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?; | 542 | write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?; |
563 | } | 543 | } |
564 | Ty::Opaque(opaque_ty) => { | 544 | Ty::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?, |
545 | Ty::Alias(AliasTy::Opaque(opaque_ty)) => { | ||
565 | match opaque_ty.opaque_ty_id { | 546 | match opaque_ty.opaque_ty_id { |
566 | OpaqueTyId::ReturnTypeImplTrait(func, idx) => { | 547 | OpaqueTyId::ReturnTypeImplTrait(func, idx) => { |
567 | let datas = | 548 | let datas = |
@@ -585,13 +566,13 @@ impl HirDisplay for Ty { | |||
585 | } | 566 | } |
586 | write!(f, "{{unknown}}")?; | 567 | write!(f, "{{unknown}}")?; |
587 | } | 568 | } |
588 | Ty::Infer(..) => write!(f, "_")?, | 569 | Ty::InferenceVar(..) => write!(f, "_")?, |
589 | } | 570 | } |
590 | Ok(()) | 571 | Ok(()) |
591 | } | 572 | } |
592 | } | 573 | } |
593 | 574 | ||
594 | impl HirDisplay for FnSig { | 575 | impl HirDisplay for CallableSig { |
595 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 576 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
596 | write!(f, "fn(")?; | 577 | write!(f, "fn(")?; |
597 | f.write_joined(self.params(), ", ")?; | 578 | f.write_joined(self.params(), ", ")?; |
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index 4b683c5a7..18a4f5e8a 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs | |||
@@ -36,25 +36,15 @@ use stdx::impl_from; | |||
36 | use syntax::SmolStr; | 36 | use syntax::SmolStr; |
37 | 37 | ||
38 | use super::{ | 38 | use super::{ |
39 | primitive::{FloatTy, IntTy}, | ||
40 | traits::{Guidance, Obligation, ProjectionPredicate, Solution}, | 39 | traits::{Guidance, Obligation, ProjectionPredicate, Solution}, |
41 | InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, | 40 | InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeWalk, |
42 | }; | 41 | }; |
43 | use crate::{ | 42 | use crate::{ |
44 | db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, | 43 | db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, AliasTy, |
45 | }; | 44 | }; |
46 | 45 | ||
47 | pub(crate) use unify::unify; | 46 | pub(crate) use unify::unify; |
48 | 47 | ||
49 | macro_rules! ty_app { | ||
50 | ($ctor:pat, $param:pat) => { | ||
51 | crate::Ty::Apply(crate::ApplicationTy { ctor: $ctor, parameters: $param }) | ||
52 | }; | ||
53 | ($ctor:pat) => { | ||
54 | ty_app!($ctor, _) | ||
55 | }; | ||
56 | } | ||
57 | |||
58 | mod unify; | 48 | mod unify; |
59 | mod path; | 49 | mod path; |
60 | mod expr; | 50 | mod expr; |
@@ -405,7 +395,7 @@ impl<'a> InferenceContext<'a> { | |||
405 | fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { | 395 | fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { |
406 | let ty = self.resolve_ty_as_possible(ty); | 396 | let ty = self.resolve_ty_as_possible(ty); |
407 | ty.fold(&mut |ty| match ty { | 397 | ty.fold(&mut |ty| match ty { |
408 | Ty::Projection(proj_ty) => self.normalize_projection_ty(proj_ty), | 398 | Ty::Alias(AliasTy::Projection(proj_ty)) => self.normalize_projection_ty(proj_ty), |
409 | _ => ty, | 399 | _ => ty, |
410 | }) | 400 | }) |
411 | } | 401 | } |
@@ -664,30 +654,17 @@ impl<'a> InferenceContext<'a> { | |||
664 | /// two are used for inference of literal values (e.g. `100` could be one of | 654 | /// two are used for inference of literal values (e.g. `100` could be one of |
665 | /// several integer types). | 655 | /// several integer types). |
666 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] | 656 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] |
667 | pub enum InferTy { | 657 | pub struct InferenceVar { |
668 | TypeVar(unify::TypeVarId), | 658 | index: u32, |
669 | IntVar(unify::TypeVarId), | ||
670 | FloatVar(unify::TypeVarId), | ||
671 | MaybeNeverTypeVar(unify::TypeVarId), | ||
672 | } | 659 | } |
673 | 660 | ||
674 | impl InferTy { | 661 | impl InferenceVar { |
675 | fn to_inner(self) -> unify::TypeVarId { | 662 | fn to_inner(self) -> unify::TypeVarId { |
676 | match self { | 663 | unify::TypeVarId(self.index) |
677 | InferTy::TypeVar(ty) | ||
678 | | InferTy::IntVar(ty) | ||
679 | | InferTy::FloatVar(ty) | ||
680 | | InferTy::MaybeNeverTypeVar(ty) => ty, | ||
681 | } | ||
682 | } | 664 | } |
683 | 665 | ||
684 | fn fallback_value(self) -> Ty { | 666 | fn from_inner(unify::TypeVarId(index): unify::TypeVarId) -> Self { |
685 | match self { | 667 | InferenceVar { index } |
686 | InferTy::TypeVar(..) => Ty::Unknown, | ||
687 | InferTy::IntVar(..) => Ty::simple(TypeCtor::Int(IntTy::i32())), | ||
688 | InferTy::FloatVar(..) => Ty::simple(TypeCtor::Float(FloatTy::f64())), | ||
689 | InferTy::MaybeNeverTypeVar(..) => Ty::simple(TypeCtor::Never), | ||
690 | } | ||
691 | } | 668 | } |
692 | } | 669 | } |
693 | 670 | ||
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index 32c7c57cd..c33d8c61e 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs | |||
@@ -4,12 +4,13 @@ | |||
4 | //! | 4 | //! |
5 | //! See: https://doc.rust-lang.org/nomicon/coercions.html | 5 | //! See: https://doc.rust-lang.org/nomicon/coercions.html |
6 | 6 | ||
7 | use chalk_ir::TyVariableKind; | ||
7 | use hir_def::{lang_item::LangItemTarget, type_ref::Mutability}; | 8 | use hir_def::{lang_item::LangItemTarget, type_ref::Mutability}; |
8 | use test_utils::mark; | 9 | use test_utils::mark; |
9 | 10 | ||
10 | use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty, TypeCtor}; | 11 | use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty}; |
11 | 12 | ||
12 | use super::{unify::TypeVarValue, InEnvironment, InferTy, InferenceContext}; | 13 | use super::{InEnvironment, InferenceContext}; |
13 | 14 | ||
14 | impl<'a> InferenceContext<'a> { | 15 | impl<'a> InferenceContext<'a> { |
15 | /// Unify two types, but may coerce the first one to the second one | 16 | /// Unify two types, but may coerce the first one to the second one |
@@ -33,7 +34,7 @@ impl<'a> InferenceContext<'a> { | |||
33 | } else if self.coerce(ty2, ty1) { | 34 | } else if self.coerce(ty2, ty1) { |
34 | ty1.clone() | 35 | ty1.clone() |
35 | } else { | 36 | } else { |
36 | if let (ty_app!(TypeCtor::FnDef(_)), ty_app!(TypeCtor::FnDef(_))) = (ty1, ty2) { | 37 | if let (Ty::FnDef(..), Ty::FnDef(..)) = (ty1, ty2) { |
37 | mark::hit!(coerce_fn_reification); | 38 | mark::hit!(coerce_fn_reification); |
38 | // Special case: two function types. Try to coerce both to | 39 | // Special case: two function types. Try to coerce both to |
39 | // pointers to have a chance at getting a match. See | 40 | // pointers to have a chance at getting a match. See |
@@ -53,12 +54,11 @@ impl<'a> InferenceContext<'a> { | |||
53 | fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool { | 54 | fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool { |
54 | match (&from_ty, to_ty) { | 55 | match (&from_ty, to_ty) { |
55 | // Never type will make type variable to fallback to Never Type instead of Unknown. | 56 | // Never type will make type variable to fallback to Never Type instead of Unknown. |
56 | (ty_app!(TypeCtor::Never), Ty::Infer(InferTy::TypeVar(tv))) => { | 57 | (Ty::Never, Ty::InferenceVar(tv, TyVariableKind::General)) => { |
57 | let var = self.table.new_maybe_never_type_var(); | 58 | self.table.type_variable_table.set_diverging(*tv, true); |
58 | self.table.var_unification_table.union_value(*tv, TypeVarValue::Known(var)); | ||
59 | return true; | 59 | return true; |
60 | } | 60 | } |
61 | (ty_app!(TypeCtor::Never), _) => return true, | 61 | (Ty::Never, _) => return true, |
62 | 62 | ||
63 | // Trivial cases, this should go after `never` check to | 63 | // Trivial cases, this should go after `never` check to |
64 | // avoid infer result type to be never | 64 | // avoid infer result type to be never |
@@ -71,38 +71,33 @@ impl<'a> InferenceContext<'a> { | |||
71 | 71 | ||
72 | // Pointer weakening and function to pointer | 72 | // Pointer weakening and function to pointer |
73 | match (&mut from_ty, to_ty) { | 73 | match (&mut from_ty, to_ty) { |
74 | // `*mut T`, `&mut T, `&T`` -> `*const T` | 74 | // `*mut T` -> `*const T` |
75 | // `&mut T` -> `&T` | 75 | // `&mut T` -> `&T` |
76 | // `&mut T` -> `*mut T` | 76 | (Ty::Raw(m1, ..), Ty::Raw(m2 @ Mutability::Shared, ..)) |
77 | (ty_app!(c1@TypeCtor::RawPtr(_)), ty_app!(c2@TypeCtor::RawPtr(Mutability::Shared))) | 77 | | (Ty::Ref(m1, ..), Ty::Ref(m2 @ Mutability::Shared, ..)) => { |
78 | | (ty_app!(c1@TypeCtor::Ref(_)), ty_app!(c2@TypeCtor::RawPtr(Mutability::Shared))) | 78 | *m1 = *m2; |
79 | | (ty_app!(c1@TypeCtor::Ref(_)), ty_app!(c2@TypeCtor::Ref(Mutability::Shared))) | 79 | } |
80 | | (ty_app!(c1@TypeCtor::Ref(Mutability::Mut)), ty_app!(c2@TypeCtor::RawPtr(_))) => { | 80 | // `&T` -> `*const T` |
81 | *c1 = *c2; | 81 | // `&mut T` -> `*mut T`/`*const T` |
82 | (Ty::Ref(.., substs), &Ty::Raw(m2 @ Mutability::Shared, ..)) | ||
83 | | (Ty::Ref(Mutability::Mut, substs), &Ty::Raw(m2, ..)) => { | ||
84 | from_ty = Ty::Raw(m2, substs.clone()); | ||
82 | } | 85 | } |
83 | 86 | ||
84 | // Illegal mutablity conversion | 87 | // Illegal mutability conversion |
85 | ( | 88 | (Ty::Raw(Mutability::Shared, ..), Ty::Raw(Mutability::Mut, ..)) |
86 | ty_app!(TypeCtor::RawPtr(Mutability::Shared)), | 89 | | (Ty::Ref(Mutability::Shared, ..), Ty::Ref(Mutability::Mut, ..)) => return false, |
87 | ty_app!(TypeCtor::RawPtr(Mutability::Mut)), | ||
88 | ) | ||
89 | | ( | ||
90 | ty_app!(TypeCtor::Ref(Mutability::Shared)), | ||
91 | ty_app!(TypeCtor::Ref(Mutability::Mut)), | ||
92 | ) => return false, | ||
93 | 90 | ||
94 | // `{function_type}` -> `fn()` | 91 | // `{function_type}` -> `fn()` |
95 | (ty_app!(TypeCtor::FnDef(_)), ty_app!(TypeCtor::FnPtr { .. })) => { | 92 | (Ty::FnDef(..), Ty::Function { .. }) => match from_ty.callable_sig(self.db) { |
96 | match from_ty.callable_sig(self.db) { | 93 | None => return false, |
97 | None => return false, | 94 | Some(sig) => { |
98 | Some(sig) => { | 95 | from_ty = Ty::fn_ptr(sig); |
99 | from_ty = Ty::fn_ptr(sig); | ||
100 | } | ||
101 | } | 96 | } |
102 | } | 97 | }, |
103 | 98 | ||
104 | (ty_app!(TypeCtor::Closure { .. }, params), ty_app!(TypeCtor::FnPtr { .. })) => { | 99 | (Ty::Closure(.., substs), Ty::Function { .. }) => { |
105 | from_ty = params[0].clone(); | 100 | from_ty = substs[0].clone(); |
106 | } | 101 | } |
107 | 102 | ||
108 | _ => {} | 103 | _ => {} |
@@ -115,9 +110,7 @@ impl<'a> InferenceContext<'a> { | |||
115 | // Auto Deref if cannot coerce | 110 | // Auto Deref if cannot coerce |
116 | match (&from_ty, to_ty) { | 111 | match (&from_ty, to_ty) { |
117 | // FIXME: DerefMut | 112 | // FIXME: DerefMut |
118 | (ty_app!(TypeCtor::Ref(_), st1), ty_app!(TypeCtor::Ref(_), st2)) => { | 113 | (Ty::Ref(_, st1), Ty::Ref(_, st2)) => self.unify_autoderef_behind_ref(&st1[0], &st2[0]), |
119 | self.unify_autoderef_behind_ref(&st1[0], &st2[0]) | ||
120 | } | ||
121 | 114 | ||
122 | // Otherwise, normal unify | 115 | // Otherwise, normal unify |
123 | _ => self.unify(&from_ty, to_ty), | 116 | _ => self.unify(&from_ty, to_ty), |
@@ -178,17 +171,17 @@ impl<'a> InferenceContext<'a> { | |||
178 | }, | 171 | }, |
179 | ) { | 172 | ) { |
180 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); | 173 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); |
181 | match (&*self.resolve_ty_shallow(&derefed_ty), &*to_ty) { | 174 | let from_ty = self.resolve_ty_shallow(&derefed_ty); |
182 | // Stop when constructor matches. | 175 | // Stop when constructor matches. |
183 | (ty_app!(from_ctor, st1), ty_app!(to_ctor, st2)) if from_ctor == to_ctor => { | 176 | if from_ty.equals_ctor(&to_ty) { |
184 | // It will not recurse to `coerce`. | 177 | // It will not recurse to `coerce`. |
185 | return self.table.unify_substs(st1, st2, 0); | 178 | return match (from_ty.substs(), to_ty.substs()) { |
186 | } | 179 | (Some(st1), Some(st2)) => self.table.unify_substs(st1, st2, 0), |
187 | _ => { | 180 | (None, None) => true, |
188 | if self.table.unify_inner_trivial(&derefed_ty, &to_ty, 0) { | 181 | _ => false, |
189 | return true; | 182 | }; |
190 | } | 183 | } else if self.table.unify_inner_trivial(&derefed_ty, &to_ty, 0) { |
191 | } | 184 | return true; |
192 | } | 185 | } |
193 | } | 186 | } |
194 | 187 | ||
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index cb59a6937..7852b3d23 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -3,8 +3,8 @@ | |||
3 | use std::iter::{repeat, repeat_with}; | 3 | use std::iter::{repeat, repeat_with}; |
4 | use std::{mem, sync::Arc}; | 4 | use std::{mem, sync::Arc}; |
5 | 5 | ||
6 | use chalk_ir::TyVariableKind; | ||
6 | use hir_def::{ | 7 | use hir_def::{ |
7 | builtin_type::Signedness, | ||
8 | expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, | 8 | expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, |
9 | path::{GenericArg, GenericArgs}, | 9 | path::{GenericArg, GenericArgs}, |
10 | resolver::resolver_for_expr, | 10 | resolver::resolver_for_expr, |
@@ -16,10 +16,11 @@ use test_utils::mark; | |||
16 | 16 | ||
17 | use crate::{ | 17 | use crate::{ |
18 | autoderef, method_resolution, op, | 18 | autoderef, method_resolution, op, |
19 | primitive::{self, UintTy}, | ||
19 | traits::{FnTrait, InEnvironment}, | 20 | traits::{FnTrait, InEnvironment}, |
20 | utils::{generics, variant_data, Generics}, | 21 | utils::{generics, variant_data, Generics}, |
21 | ApplicationTy, Binders, CallableDefId, InferTy, IntTy, Mutability, Obligation, OpaqueTyId, | 22 | Binders, CallableDefId, FnPointer, FnSig, Mutability, Obligation, OpaqueTyId, Rawness, Scalar, |
22 | Rawness, Substs, TraitRef, Ty, TypeCtor, | 23 | Substs, TraitRef, Ty, |
23 | }; | 24 | }; |
24 | 25 | ||
25 | use super::{ | 26 | use super::{ |
@@ -82,10 +83,7 @@ impl<'a> InferenceContext<'a> { | |||
82 | arg_tys.push(arg); | 83 | arg_tys.push(arg); |
83 | } | 84 | } |
84 | let parameters = param_builder.build(); | 85 | let parameters = param_builder.build(); |
85 | let arg_ty = Ty::Apply(ApplicationTy { | 86 | let arg_ty = Ty::Tuple(num_args, parameters); |
86 | ctor: TypeCtor::Tuple { cardinality: num_args as u16 }, | ||
87 | parameters, | ||
88 | }); | ||
89 | let substs = | 87 | let substs = |
90 | Substs::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); | 88 | Substs::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); |
91 | 89 | ||
@@ -120,7 +118,7 @@ impl<'a> InferenceContext<'a> { | |||
120 | Expr::Missing => Ty::Unknown, | 118 | Expr::Missing => Ty::Unknown, |
121 | Expr::If { condition, then_branch, else_branch } => { | 119 | Expr::If { condition, then_branch, else_branch } => { |
122 | // if let is desugared to match, so this is always simple if | 120 | // if let is desugared to match, so this is always simple if |
123 | self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); | 121 | self.infer_expr(*condition, &Expectation::has_type(Ty::Scalar(Scalar::Bool))); |
124 | 122 | ||
125 | let condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); | 123 | let condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); |
126 | let mut both_arms_diverge = Diverges::Always; | 124 | let mut both_arms_diverge = Diverges::Always; |
@@ -175,7 +173,7 @@ impl<'a> InferenceContext<'a> { | |||
175 | // existenail type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType> | 173 | // existenail type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType> |
176 | let inner_ty = self.infer_expr(*body, &Expectation::none()); | 174 | let inner_ty = self.infer_expr(*body, &Expectation::none()); |
177 | let opaque_ty_id = OpaqueTyId::AsyncBlockTypeImplTrait(self.owner, *body); | 175 | let opaque_ty_id = OpaqueTyId::AsyncBlockTypeImplTrait(self.owner, *body); |
178 | Ty::apply_one(TypeCtor::OpaqueType(opaque_ty_id), inner_ty) | 176 | Ty::OpaqueType(opaque_ty_id, Substs::single(inner_ty)) |
179 | } | 177 | } |
180 | Expr::Loop { body, label } => { | 178 | Expr::Loop { body, label } => { |
181 | self.breakables.push(BreakableContext { | 179 | self.breakables.push(BreakableContext { |
@@ -193,7 +191,7 @@ impl<'a> InferenceContext<'a> { | |||
193 | if ctxt.may_break { | 191 | if ctxt.may_break { |
194 | ctxt.break_ty | 192 | ctxt.break_ty |
195 | } else { | 193 | } else { |
196 | Ty::simple(TypeCtor::Never) | 194 | Ty::Never |
197 | } | 195 | } |
198 | } | 196 | } |
199 | Expr::While { condition, body, label } => { | 197 | Expr::While { condition, body, label } => { |
@@ -203,7 +201,7 @@ impl<'a> InferenceContext<'a> { | |||
203 | label: label.map(|label| self.body[label].name.clone()), | 201 | label: label.map(|label| self.body[label].name.clone()), |
204 | }); | 202 | }); |
205 | // while let is desugared to a match loop, so this is always simple while | 203 | // while let is desugared to a match loop, so this is always simple while |
206 | self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); | 204 | self.infer_expr(*condition, &Expectation::has_type(Ty::Scalar(Scalar::Bool))); |
207 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); | 205 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); |
208 | let _ctxt = self.breakables.pop().expect("breakable stack broken"); | 206 | let _ctxt = self.breakables.pop().expect("breakable stack broken"); |
209 | // the body may not run, so it diverging doesn't mean we diverge | 207 | // the body may not run, so it diverging doesn't mean we diverge |
@@ -250,12 +248,12 @@ impl<'a> InferenceContext<'a> { | |||
250 | None => self.table.new_type_var(), | 248 | None => self.table.new_type_var(), |
251 | }; | 249 | }; |
252 | sig_tys.push(ret_ty.clone()); | 250 | sig_tys.push(ret_ty.clone()); |
253 | let sig_ty = Ty::apply( | 251 | let sig_ty = Ty::Function(FnPointer { |
254 | TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1, is_varargs: false }, | 252 | num_args: sig_tys.len() - 1, |
255 | Substs(sig_tys.clone().into()), | 253 | sig: FnSig { variadic: false }, |
256 | ); | 254 | substs: Substs(sig_tys.clone().into()), |
257 | let closure_ty = | 255 | }); |
258 | Ty::apply_one(TypeCtor::Closure { def: self.owner, expr: tgt_expr }, sig_ty); | 256 | let closure_ty = Ty::Closure(self.owner, tgt_expr, Substs::single(sig_ty)); |
259 | 257 | ||
260 | // Eagerly try to relate the closure type with the expected | 258 | // Eagerly try to relate the closure type with the expected |
261 | // type, otherwise we often won't have enough information to | 259 | // type, otherwise we often won't have enough information to |
@@ -306,11 +304,8 @@ impl<'a> InferenceContext<'a> { | |||
306 | Expr::Match { expr, arms } => { | 304 | Expr::Match { expr, arms } => { |
307 | let input_ty = self.infer_expr(*expr, &Expectation::none()); | 305 | let input_ty = self.infer_expr(*expr, &Expectation::none()); |
308 | 306 | ||
309 | let mut result_ty = if arms.is_empty() { | 307 | let mut result_ty = |
310 | Ty::simple(TypeCtor::Never) | 308 | if arms.is_empty() { Ty::Never } else { self.table.new_type_var() }; |
311 | } else { | ||
312 | self.table.new_type_var() | ||
313 | }; | ||
314 | 309 | ||
315 | let matchee_diverges = self.diverges; | 310 | let matchee_diverges = self.diverges; |
316 | let mut all_arms_diverge = Diverges::Always; | 311 | let mut all_arms_diverge = Diverges::Always; |
@@ -321,7 +316,7 @@ impl<'a> InferenceContext<'a> { | |||
321 | if let Some(guard_expr) = arm.guard { | 316 | if let Some(guard_expr) = arm.guard { |
322 | self.infer_expr( | 317 | self.infer_expr( |
323 | guard_expr, | 318 | guard_expr, |
324 | &Expectation::has_type(Ty::simple(TypeCtor::Bool)), | 319 | &Expectation::has_type(Ty::Scalar(Scalar::Bool)), |
325 | ); | 320 | ); |
326 | } | 321 | } |
327 | 322 | ||
@@ -339,7 +334,7 @@ impl<'a> InferenceContext<'a> { | |||
339 | let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); | 334 | let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); |
340 | self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown) | 335 | self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown) |
341 | } | 336 | } |
342 | Expr::Continue { .. } => Ty::simple(TypeCtor::Never), | 337 | Expr::Continue { .. } => Ty::Never, |
343 | Expr::Break { expr, label } => { | 338 | Expr::Break { expr, label } => { |
344 | let val_ty = if let Some(expr) = expr { | 339 | let val_ty = if let Some(expr) = expr { |
345 | self.infer_expr(*expr, &Expectation::none()) | 340 | self.infer_expr(*expr, &Expectation::none()) |
@@ -364,8 +359,7 @@ impl<'a> InferenceContext<'a> { | |||
364 | expr: tgt_expr, | 359 | expr: tgt_expr, |
365 | }); | 360 | }); |
366 | } | 361 | } |
367 | 362 | Ty::Never | |
368 | Ty::simple(TypeCtor::Never) | ||
369 | } | 363 | } |
370 | Expr::Return { expr } => { | 364 | Expr::Return { expr } => { |
371 | if let Some(expr) = expr { | 365 | if let Some(expr) = expr { |
@@ -374,14 +368,14 @@ impl<'a> InferenceContext<'a> { | |||
374 | let unit = Ty::unit(); | 368 | let unit = Ty::unit(); |
375 | self.coerce(&unit, &self.return_ty.clone()); | 369 | self.coerce(&unit, &self.return_ty.clone()); |
376 | } | 370 | } |
377 | Ty::simple(TypeCtor::Never) | 371 | Ty::Never |
378 | } | 372 | } |
379 | Expr::Yield { expr } => { | 373 | Expr::Yield { expr } => { |
380 | // FIXME: track yield type for coercion | 374 | // FIXME: track yield type for coercion |
381 | if let Some(expr) = expr { | 375 | if let Some(expr) = expr { |
382 | self.infer_expr(*expr, &Expectation::none()); | 376 | self.infer_expr(*expr, &Expectation::none()); |
383 | } | 377 | } |
384 | Ty::simple(TypeCtor::Never) | 378 | Ty::Never |
385 | } | 379 | } |
386 | Expr::RecordLit { path, fields, spread } => { | 380 | Expr::RecordLit { path, fields, spread } => { |
387 | let (ty, def_id) = self.resolve_variant(path.as_ref()); | 381 | let (ty, def_id) = self.resolve_variant(path.as_ref()); |
@@ -391,7 +385,7 @@ impl<'a> InferenceContext<'a> { | |||
391 | 385 | ||
392 | self.unify(&ty, &expected.ty); | 386 | self.unify(&ty, &expected.ty); |
393 | 387 | ||
394 | let substs = ty.substs().unwrap_or_else(Substs::empty); | 388 | let substs = ty.substs().cloned().unwrap_or_else(Substs::empty); |
395 | let field_types = def_id.map(|it| self.db.field_types(it)).unwrap_or_default(); | 389 | let field_types = def_id.map(|it| self.db.field_types(it)).unwrap_or_default(); |
396 | let variant_data = def_id.map(|it| variant_data(self.db.upcast(), it)); | 390 | let variant_data = def_id.map(|it| variant_data(self.db.upcast(), it)); |
397 | for (field_idx, field) in fields.iter().enumerate() { | 391 | for (field_idx, field) in fields.iter().enumerate() { |
@@ -430,30 +424,23 @@ impl<'a> InferenceContext<'a> { | |||
430 | }, | 424 | }, |
431 | ) | 425 | ) |
432 | .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) { | 426 | .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) { |
433 | Ty::Apply(a_ty) => match a_ty.ctor { | 427 | Ty::Tuple(_, substs) => { |
434 | TypeCtor::Tuple { .. } => name | 428 | name.as_tuple_index().and_then(|idx| substs.0.get(idx).cloned()) |
435 | .as_tuple_index() | 429 | } |
436 | .and_then(|idx| a_ty.parameters.0.get(idx).cloned()), | 430 | Ty::Adt(AdtId::StructId(s), parameters) => { |
437 | TypeCtor::Adt(AdtId::StructId(s)) => { | 431 | self.db.struct_data(s).variant_data.field(name).map(|local_id| { |
438 | self.db.struct_data(s).variant_data.field(name).map(|local_id| { | 432 | let field = FieldId { parent: s.into(), local_id }; |
439 | let field = FieldId { parent: s.into(), local_id }; | 433 | self.write_field_resolution(tgt_expr, field); |
440 | self.write_field_resolution(tgt_expr, field); | 434 | self.db.field_types(s.into())[field.local_id].clone().subst(¶meters) |
441 | self.db.field_types(s.into())[field.local_id] | 435 | }) |
442 | .clone() | 436 | } |
443 | .subst(&a_ty.parameters) | 437 | Ty::Adt(AdtId::UnionId(u), parameters) => { |
444 | }) | 438 | self.db.union_data(u).variant_data.field(name).map(|local_id| { |
445 | } | 439 | let field = FieldId { parent: u.into(), local_id }; |
446 | TypeCtor::Adt(AdtId::UnionId(u)) => { | 440 | self.write_field_resolution(tgt_expr, field); |
447 | self.db.union_data(u).variant_data.field(name).map(|local_id| { | 441 | self.db.field_types(u.into())[field.local_id].clone().subst(¶meters) |
448 | let field = FieldId { parent: u.into(), local_id }; | 442 | }) |
449 | self.write_field_resolution(tgt_expr, field); | 443 | } |
450 | self.db.field_types(u.into())[field.local_id] | ||
451 | .clone() | ||
452 | .subst(&a_ty.parameters) | ||
453 | }) | ||
454 | } | ||
455 | _ => None, | ||
456 | }, | ||
457 | _ => None, | 444 | _ => None, |
458 | }) | 445 | }) |
459 | .unwrap_or(Ty::Unknown); | 446 | .unwrap_or(Ty::Unknown); |
@@ -491,19 +478,24 @@ impl<'a> InferenceContext<'a> { | |||
491 | Expectation::none() | 478 | Expectation::none() |
492 | }; | 479 | }; |
493 | let inner_ty = self.infer_expr_inner(*expr, &expectation); | 480 | let inner_ty = self.infer_expr_inner(*expr, &expectation); |
494 | let ty = match rawness { | 481 | match rawness { |
495 | Rawness::RawPtr => TypeCtor::RawPtr(*mutability), | 482 | Rawness::RawPtr => Ty::Raw(*mutability, Substs::single(inner_ty)), |
496 | Rawness::Ref => TypeCtor::Ref(*mutability), | 483 | Rawness::Ref => Ty::Ref(*mutability, Substs::single(inner_ty)), |
497 | }; | 484 | } |
498 | Ty::apply_one(ty, inner_ty) | ||
499 | } | 485 | } |
500 | Expr::Box { expr } => { | 486 | Expr::Box { expr } => { |
501 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); | 487 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); |
502 | if let Some(box_) = self.resolve_boxed_box() { | 488 | if let Some(box_) = self.resolve_boxed_box() { |
503 | let mut sb = Substs::build_for_type_ctor(self.db, TypeCtor::Adt(box_)); | 489 | let mut sb = Substs::builder(generics(self.db.upcast(), box_.into()).len()); |
504 | sb = sb.push(inner_ty); | 490 | sb = sb.push(inner_ty); |
491 | match self.db.generic_defaults(box_.into()).as_ref() { | ||
492 | [_, alloc_ty, ..] if !alloc_ty.value.is_unknown() => { | ||
493 | sb = sb.push(alloc_ty.value.clone()); | ||
494 | } | ||
495 | _ => (), | ||
496 | } | ||
505 | sb = sb.fill(repeat_with(|| self.table.new_type_var())); | 497 | sb = sb.fill(repeat_with(|| self.table.new_type_var())); |
506 | Ty::apply(TypeCtor::Adt(box_), sb.build()) | 498 | Ty::Adt(box_, sb.build()) |
507 | } else { | 499 | } else { |
508 | Ty::Unknown | 500 | Ty::Unknown |
509 | } | 501 | } |
@@ -533,13 +525,11 @@ impl<'a> InferenceContext<'a> { | |||
533 | UnaryOp::Neg => { | 525 | UnaryOp::Neg => { |
534 | match &inner_ty { | 526 | match &inner_ty { |
535 | // Fast path for builtins | 527 | // Fast path for builtins |
536 | Ty::Apply(ApplicationTy { | 528 | Ty::Scalar(Scalar::Int(_)) |
537 | ctor: TypeCtor::Int(IntTy { signedness: Signedness::Signed, .. }), | 529 | | Ty::Scalar(Scalar::Uint(_)) |
538 | .. | 530 | | Ty::Scalar(Scalar::Float(_)) |
539 | }) | 531 | | Ty::InferenceVar(_, TyVariableKind::Integer) |
540 | | Ty::Apply(ApplicationTy { ctor: TypeCtor::Float(_), .. }) | 532 | | Ty::InferenceVar(_, TyVariableKind::Float) => inner_ty, |
541 | | Ty::Infer(InferTy::IntVar(..)) | ||
542 | | Ty::Infer(InferTy::FloatVar(..)) => inner_ty, | ||
543 | // Otherwise we resolve via the std::ops::Neg trait | 533 | // Otherwise we resolve via the std::ops::Neg trait |
544 | _ => self | 534 | _ => self |
545 | .resolve_associated_type(inner_ty, self.resolve_ops_neg_output()), | 535 | .resolve_associated_type(inner_ty, self.resolve_ops_neg_output()), |
@@ -548,9 +538,10 @@ impl<'a> InferenceContext<'a> { | |||
548 | UnaryOp::Not => { | 538 | UnaryOp::Not => { |
549 | match &inner_ty { | 539 | match &inner_ty { |
550 | // Fast path for builtins | 540 | // Fast path for builtins |
551 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. }) | 541 | Ty::Scalar(Scalar::Bool) |
552 | | Ty::Apply(ApplicationTy { ctor: TypeCtor::Int(_), .. }) | 542 | | Ty::Scalar(Scalar::Int(_)) |
553 | | Ty::Infer(InferTy::IntVar(..)) => inner_ty, | 543 | | Ty::Scalar(Scalar::Uint(_)) |
544 | | Ty::InferenceVar(_, TyVariableKind::Integer) => inner_ty, | ||
554 | // Otherwise we resolve via the std::ops::Not trait | 545 | // Otherwise we resolve via the std::ops::Not trait |
555 | _ => self | 546 | _ => self |
556 | .resolve_associated_type(inner_ty, self.resolve_ops_not_output()), | 547 | .resolve_associated_type(inner_ty, self.resolve_ops_not_output()), |
@@ -561,7 +552,7 @@ impl<'a> InferenceContext<'a> { | |||
561 | Expr::BinaryOp { lhs, rhs, op } => match op { | 552 | Expr::BinaryOp { lhs, rhs, op } => match op { |
562 | Some(op) => { | 553 | Some(op) => { |
563 | let lhs_expectation = match op { | 554 | let lhs_expectation = match op { |
564 | BinaryOp::LogicOp(..) => Expectation::has_type(Ty::simple(TypeCtor::Bool)), | 555 | BinaryOp::LogicOp(..) => Expectation::has_type(Ty::Scalar(Scalar::Bool)), |
565 | _ => Expectation::none(), | 556 | _ => Expectation::none(), |
566 | }; | 557 | }; |
567 | let lhs_ty = self.infer_expr(*lhs, &lhs_expectation); | 558 | let lhs_ty = self.infer_expr(*lhs, &lhs_expectation); |
@@ -592,31 +583,31 @@ impl<'a> InferenceContext<'a> { | |||
592 | let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect)); | 583 | let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect)); |
593 | match (range_type, lhs_ty, rhs_ty) { | 584 | match (range_type, lhs_ty, rhs_ty) { |
594 | (RangeOp::Exclusive, None, None) => match self.resolve_range_full() { | 585 | (RangeOp::Exclusive, None, None) => match self.resolve_range_full() { |
595 | Some(adt) => Ty::simple(TypeCtor::Adt(adt)), | 586 | Some(adt) => Ty::Adt(adt, Substs::empty()), |
596 | None => Ty::Unknown, | 587 | None => Ty::Unknown, |
597 | }, | 588 | }, |
598 | (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() { | 589 | (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() { |
599 | Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), | 590 | Some(adt) => Ty::Adt(adt, Substs::single(ty)), |
600 | None => Ty::Unknown, | 591 | None => Ty::Unknown, |
601 | }, | 592 | }, |
602 | (RangeOp::Inclusive, None, Some(ty)) => { | 593 | (RangeOp::Inclusive, None, Some(ty)) => { |
603 | match self.resolve_range_to_inclusive() { | 594 | match self.resolve_range_to_inclusive() { |
604 | Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), | 595 | Some(adt) => Ty::Adt(adt, Substs::single(ty)), |
605 | None => Ty::Unknown, | 596 | None => Ty::Unknown, |
606 | } | 597 | } |
607 | } | 598 | } |
608 | (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() { | 599 | (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() { |
609 | Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), | 600 | Some(adt) => Ty::Adt(adt, Substs::single(ty)), |
610 | None => Ty::Unknown, | 601 | None => Ty::Unknown, |
611 | }, | 602 | }, |
612 | (RangeOp::Inclusive, Some(_), Some(ty)) => { | 603 | (RangeOp::Inclusive, Some(_), Some(ty)) => { |
613 | match self.resolve_range_inclusive() { | 604 | match self.resolve_range_inclusive() { |
614 | Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), | 605 | Some(adt) => Ty::Adt(adt, Substs::single(ty)), |
615 | None => Ty::Unknown, | 606 | None => Ty::Unknown, |
616 | } | 607 | } |
617 | } | 608 | } |
618 | (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() { | 609 | (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() { |
619 | Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), | 610 | Some(adt) => Ty::Adt(adt, Substs::single(ty)), |
620 | None => Ty::Unknown, | 611 | None => Ty::Unknown, |
621 | }, | 612 | }, |
622 | (RangeOp::Inclusive, _, None) => Ty::Unknown, | 613 | (RangeOp::Inclusive, _, None) => Ty::Unknown, |
@@ -650,7 +641,7 @@ impl<'a> InferenceContext<'a> { | |||
650 | } | 641 | } |
651 | Expr::Tuple { exprs } => { | 642 | Expr::Tuple { exprs } => { |
652 | let mut tys = match &expected.ty { | 643 | let mut tys = match &expected.ty { |
653 | ty_app!(TypeCtor::Tuple { .. }, st) => st | 644 | Ty::Tuple(_, substs) => substs |
654 | .iter() | 645 | .iter() |
655 | .cloned() | 646 | .cloned() |
656 | .chain(repeat_with(|| self.table.new_type_var())) | 647 | .chain(repeat_with(|| self.table.new_type_var())) |
@@ -663,15 +654,11 @@ impl<'a> InferenceContext<'a> { | |||
663 | self.infer_expr_coerce(*expr, &Expectation::has_type(ty.clone())); | 654 | self.infer_expr_coerce(*expr, &Expectation::has_type(ty.clone())); |
664 | } | 655 | } |
665 | 656 | ||
666 | Ty::apply(TypeCtor::Tuple { cardinality: tys.len() as u16 }, Substs(tys.into())) | 657 | Ty::Tuple(tys.len(), Substs(tys.into())) |
667 | } | 658 | } |
668 | Expr::Array(array) => { | 659 | Expr::Array(array) => { |
669 | let elem_ty = match &expected.ty { | 660 | let elem_ty = match &expected.ty { |
670 | // FIXME: remove when https://github.com/rust-lang/rust/issues/80501 is fixed | 661 | Ty::Array(st) | Ty::Slice(st) => st.as_single().clone(), |
671 | #[allow(unreachable_patterns)] | ||
672 | ty_app!(TypeCtor::Array, st) | ty_app!(TypeCtor::Slice, st) => { | ||
673 | st.as_single().clone() | ||
674 | } | ||
675 | _ => self.table.new_type_var(), | 662 | _ => self.table.new_type_var(), |
676 | }; | 663 | }; |
677 | 664 | ||
@@ -688,30 +675,38 @@ impl<'a> InferenceContext<'a> { | |||
688 | ); | 675 | ); |
689 | self.infer_expr( | 676 | self.infer_expr( |
690 | *repeat, | 677 | *repeat, |
691 | &Expectation::has_type(Ty::simple(TypeCtor::Int(IntTy::usize()))), | 678 | &Expectation::has_type(Ty::Scalar(Scalar::Uint(UintTy::Usize))), |
692 | ); | 679 | ); |
693 | } | 680 | } |
694 | } | 681 | } |
695 | 682 | ||
696 | Ty::apply_one(TypeCtor::Array, elem_ty) | 683 | Ty::Array(Substs::single(elem_ty)) |
697 | } | 684 | } |
698 | Expr::Literal(lit) => match lit { | 685 | Expr::Literal(lit) => match lit { |
699 | Literal::Bool(..) => Ty::simple(TypeCtor::Bool), | 686 | Literal::Bool(..) => Ty::Scalar(Scalar::Bool), |
700 | Literal::String(..) => { | 687 | Literal::String(..) => Ty::Ref(Mutability::Shared, Substs::single(Ty::Str)), |
701 | Ty::apply_one(TypeCtor::Ref(Mutability::Shared), Ty::simple(TypeCtor::Str)) | ||
702 | } | ||
703 | Literal::ByteString(..) => { | 688 | Literal::ByteString(..) => { |
704 | let byte_type = Ty::simple(TypeCtor::Int(IntTy::u8())); | 689 | let byte_type = Ty::Scalar(Scalar::Uint(UintTy::U8)); |
705 | let array_type = Ty::apply_one(TypeCtor::Array, byte_type); | 690 | let array_type = Ty::Array(Substs::single(byte_type)); |
706 | Ty::apply_one(TypeCtor::Ref(Mutability::Shared), array_type) | 691 | Ty::Ref(Mutability::Shared, Substs::single(array_type)) |
707 | } | 692 | } |
708 | Literal::Char(..) => Ty::simple(TypeCtor::Char), | 693 | Literal::Char(..) => Ty::Scalar(Scalar::Char), |
709 | Literal::Int(_v, ty) => match ty { | 694 | Literal::Int(_v, ty) => match ty { |
710 | Some(int_ty) => Ty::simple(TypeCtor::Int((*int_ty).into())), | 695 | Some(int_ty) => { |
696 | Ty::Scalar(Scalar::Int(primitive::int_ty_from_builtin(*int_ty))) | ||
697 | } | ||
698 | None => self.table.new_integer_var(), | ||
699 | }, | ||
700 | Literal::Uint(_v, ty) => match ty { | ||
701 | Some(int_ty) => { | ||
702 | Ty::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(*int_ty))) | ||
703 | } | ||
711 | None => self.table.new_integer_var(), | 704 | None => self.table.new_integer_var(), |
712 | }, | 705 | }, |
713 | Literal::Float(_v, ty) => match ty { | 706 | Literal::Float(_v, ty) => match ty { |
714 | Some(float_ty) => Ty::simple(TypeCtor::Float((*float_ty).into())), | 707 | Some(float_ty) => { |
708 | Ty::Scalar(Scalar::Float(primitive::float_ty_from_builtin(*float_ty))) | ||
709 | } | ||
715 | None => self.table.new_float_var(), | 710 | None => self.table.new_float_var(), |
716 | }, | 711 | }, |
717 | }, | 712 | }, |
@@ -767,7 +762,7 @@ impl<'a> InferenceContext<'a> { | |||
767 | // `!`). | 762 | // `!`). |
768 | if self.diverges.is_always() { | 763 | if self.diverges.is_always() { |
769 | // we don't even make an attempt at coercion | 764 | // we don't even make an attempt at coercion |
770 | self.table.new_maybe_never_type_var() | 765 | self.table.new_maybe_never_var() |
771 | } else { | 766 | } else { |
772 | self.coerce(&Ty::unit(), expected.coercion_target()); | 767 | self.coerce(&Ty::unit(), expected.coercion_target()); |
773 | Ty::unit() | 768 | Ty::unit() |
@@ -824,7 +819,7 @@ impl<'a> InferenceContext<'a> { | |||
824 | // Apply autoref so the below unification works correctly | 819 | // Apply autoref so the below unification works correctly |
825 | // FIXME: return correct autorefs from lookup_method | 820 | // FIXME: return correct autorefs from lookup_method |
826 | let actual_receiver_ty = match expected_receiver_ty.as_reference() { | 821 | let actual_receiver_ty = match expected_receiver_ty.as_reference() { |
827 | Some((_, mutability)) => Ty::apply_one(TypeCtor::Ref(mutability), derefed_receiver_ty), | 822 | Some((_, mutability)) => Ty::Ref(mutability, Substs::single(derefed_receiver_ty)), |
828 | _ => derefed_receiver_ty, | 823 | _ => derefed_receiver_ty, |
829 | }; | 824 | }; |
830 | self.unify(&expected_receiver_ty, &actual_receiver_ty); | 825 | self.unify(&expected_receiver_ty, &actual_receiver_ty); |
@@ -901,30 +896,26 @@ impl<'a> InferenceContext<'a> { | |||
901 | } | 896 | } |
902 | 897 | ||
903 | fn register_obligations_for_call(&mut self, callable_ty: &Ty) { | 898 | fn register_obligations_for_call(&mut self, callable_ty: &Ty) { |
904 | if let Ty::Apply(a_ty) = callable_ty { | 899 | if let &Ty::FnDef(def, ref parameters) = callable_ty { |
905 | if let TypeCtor::FnDef(def) = a_ty.ctor { | 900 | let generic_predicates = self.db.generic_predicates(def.into()); |
906 | let generic_predicates = self.db.generic_predicates(def.into()); | 901 | for predicate in generic_predicates.iter() { |
907 | for predicate in generic_predicates.iter() { | 902 | let predicate = predicate.clone().subst(parameters); |
908 | let predicate = predicate.clone().subst(&a_ty.parameters); | 903 | if let Some(obligation) = Obligation::from_predicate(predicate) { |
909 | if let Some(obligation) = Obligation::from_predicate(predicate) { | 904 | self.obligations.push(obligation); |
910 | self.obligations.push(obligation); | ||
911 | } | ||
912 | } | 905 | } |
913 | // add obligation for trait implementation, if this is a trait method | 906 | } |
914 | match def { | 907 | // add obligation for trait implementation, if this is a trait method |
915 | CallableDefId::FunctionId(f) => { | 908 | match def { |
916 | if let AssocContainerId::TraitId(trait_) = | 909 | CallableDefId::FunctionId(f) => { |
917 | f.lookup(self.db.upcast()).container | 910 | if let AssocContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container |
918 | { | 911 | { |
919 | // construct a TraitDef | 912 | // construct a TraitDef |
920 | let substs = a_ty | 913 | let substs = |
921 | .parameters | 914 | parameters.prefix(generics(self.db.upcast(), trait_.into()).len()); |
922 | .prefix(generics(self.db.upcast(), trait_.into()).len()); | 915 | self.obligations.push(Obligation::Trait(TraitRef { trait_, substs })); |
923 | self.obligations.push(Obligation::Trait(TraitRef { trait_, substs })); | ||
924 | } | ||
925 | } | 916 | } |
926 | CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {} | ||
927 | } | 917 | } |
918 | CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {} | ||
928 | } | 919 | } |
929 | } | 920 | } |
930 | } | 921 | } |
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index d974f805b..a318e47f3 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs | |||
@@ -13,7 +13,7 @@ use hir_expand::name::Name; | |||
13 | use test_utils::mark; | 13 | use test_utils::mark; |
14 | 14 | ||
15 | use super::{BindingMode, Expectation, InferenceContext}; | 15 | use super::{BindingMode, Expectation, InferenceContext}; |
16 | use crate::{utils::variant_data, Substs, Ty, TypeCtor}; | 16 | use crate::{utils::variant_data, Substs, Ty}; |
17 | 17 | ||
18 | impl<'a> InferenceContext<'a> { | 18 | impl<'a> InferenceContext<'a> { |
19 | fn infer_tuple_struct_pat( | 19 | fn infer_tuple_struct_pat( |
@@ -32,7 +32,7 @@ impl<'a> InferenceContext<'a> { | |||
32 | } | 32 | } |
33 | self.unify(&ty, expected); | 33 | self.unify(&ty, expected); |
34 | 34 | ||
35 | let substs = ty.substs().unwrap_or_else(Substs::empty); | 35 | let substs = ty.substs().cloned().unwrap_or_else(Substs::empty); |
36 | 36 | ||
37 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); | 37 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); |
38 | let (pre, post) = match ellipsis { | 38 | let (pre, post) = match ellipsis { |
@@ -71,7 +71,7 @@ impl<'a> InferenceContext<'a> { | |||
71 | 71 | ||
72 | self.unify(&ty, expected); | 72 | self.unify(&ty, expected); |
73 | 73 | ||
74 | let substs = ty.substs().unwrap_or_else(Substs::empty); | 74 | let substs = ty.substs().cloned().unwrap_or_else(Substs::empty); |
75 | 75 | ||
76 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); | 76 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); |
77 | for subpat in subpats { | 77 | for subpat in subpats { |
@@ -138,10 +138,7 @@ impl<'a> InferenceContext<'a> { | |||
138 | inner_tys.extend(expectations_iter.by_ref().take(n_uncovered_patterns).cloned()); | 138 | inner_tys.extend(expectations_iter.by_ref().take(n_uncovered_patterns).cloned()); |
139 | inner_tys.extend(post.iter().zip(expectations_iter).map(infer_pat)); | 139 | inner_tys.extend(post.iter().zip(expectations_iter).map(infer_pat)); |
140 | 140 | ||
141 | Ty::apply( | 141 | Ty::Tuple(inner_tys.len(), Substs(inner_tys.into())) |
142 | TypeCtor::Tuple { cardinality: inner_tys.len() as u16 }, | ||
143 | Substs(inner_tys.into()), | ||
144 | ) | ||
145 | } | 142 | } |
146 | Pat::Or(ref pats) => { | 143 | Pat::Or(ref pats) => { |
147 | if let Some((first_pat, rest)) = pats.split_first() { | 144 | if let Some((first_pat, rest)) = pats.split_first() { |
@@ -165,7 +162,7 @@ impl<'a> InferenceContext<'a> { | |||
165 | _ => &Ty::Unknown, | 162 | _ => &Ty::Unknown, |
166 | }; | 163 | }; |
167 | let subty = self.infer_pat(*pat, expectation, default_bm); | 164 | let subty = self.infer_pat(*pat, expectation, default_bm); |
168 | Ty::apply_one(TypeCtor::Ref(*mutability), subty) | 165 | Ty::Ref(*mutability, Substs::single(subty)) |
169 | } | 166 | } |
170 | Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat( | 167 | Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat( |
171 | p.as_ref(), | 168 | p.as_ref(), |
@@ -198,7 +195,7 @@ impl<'a> InferenceContext<'a> { | |||
198 | 195 | ||
199 | let bound_ty = match mode { | 196 | let bound_ty = match mode { |
200 | BindingMode::Ref(mutability) => { | 197 | BindingMode::Ref(mutability) => { |
201 | Ty::apply_one(TypeCtor::Ref(mutability), inner_ty.clone()) | 198 | Ty::Ref(mutability, Substs::single(inner_ty.clone())) |
202 | } | 199 | } |
203 | BindingMode::Move => inner_ty.clone(), | 200 | BindingMode::Move => inner_ty.clone(), |
204 | }; | 201 | }; |
@@ -207,17 +204,17 @@ impl<'a> InferenceContext<'a> { | |||
207 | return inner_ty; | 204 | return inner_ty; |
208 | } | 205 | } |
209 | Pat::Slice { prefix, slice, suffix } => { | 206 | Pat::Slice { prefix, slice, suffix } => { |
210 | let (container_ty, elem_ty) = match &expected { | 207 | let (container_ty, elem_ty): (fn(_) -> _, _) = match &expected { |
211 | ty_app!(TypeCtor::Array, st) => (TypeCtor::Array, st.as_single().clone()), | 208 | Ty::Array(st) => (Ty::Array, st.as_single().clone()), |
212 | ty_app!(TypeCtor::Slice, st) => (TypeCtor::Slice, st.as_single().clone()), | 209 | Ty::Slice(st) => (Ty::Slice, st.as_single().clone()), |
213 | _ => (TypeCtor::Slice, Ty::Unknown), | 210 | _ => (Ty::Slice, Ty::Unknown), |
214 | }; | 211 | }; |
215 | 212 | ||
216 | for pat_id in prefix.iter().chain(suffix) { | 213 | for pat_id in prefix.iter().chain(suffix) { |
217 | self.infer_pat(*pat_id, &elem_ty, default_bm); | 214 | self.infer_pat(*pat_id, &elem_ty, default_bm); |
218 | } | 215 | } |
219 | 216 | ||
220 | let pat_ty = Ty::apply_one(container_ty, elem_ty); | 217 | let pat_ty = container_ty(Substs::single(elem_ty)); |
221 | if let Some(slice_pat_id) = slice { | 218 | if let Some(slice_pat_id) = slice { |
222 | self.infer_pat(*slice_pat_id, &pat_ty, default_bm); | 219 | self.infer_pat(*slice_pat_id, &pat_ty, default_bm); |
223 | } | 220 | } |
@@ -239,7 +236,7 @@ impl<'a> InferenceContext<'a> { | |||
239 | }; | 236 | }; |
240 | 237 | ||
241 | let inner_ty = self.infer_pat(*inner, inner_expected, default_bm); | 238 | let inner_ty = self.infer_pat(*inner, inner_expected, default_bm); |
242 | Ty::apply_one(TypeCtor::Adt(box_adt), inner_ty) | 239 | Ty::Adt(box_adt, Substs::single(inner_ty)) |
243 | } | 240 | } |
244 | None => Ty::Unknown, | 241 | None => Ty::Unknown, |
245 | }, | 242 | }, |
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index 76984242e..99a89a7f3 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs | |||
@@ -2,14 +2,15 @@ | |||
2 | 2 | ||
3 | use std::borrow::Cow; | 3 | use std::borrow::Cow; |
4 | 4 | ||
5 | use chalk_ir::{FloatTy, IntTy, TyVariableKind}; | ||
5 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; | 6 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; |
6 | 7 | ||
7 | use test_utils::mark; | 8 | use test_utils::mark; |
8 | 9 | ||
9 | use super::{InferenceContext, Obligation}; | 10 | use super::{InferenceContext, Obligation}; |
10 | use crate::{ | 11 | use crate::{ |
11 | BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferTy, Substs, Ty, | 12 | BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferenceVar, Scalar, |
12 | TyKind, TypeCtor, TypeWalk, | 13 | Substs, Ty, TypeWalk, |
13 | }; | 14 | }; |
14 | 15 | ||
15 | impl<'a> InferenceContext<'a> { | 16 | impl<'a> InferenceContext<'a> { |
@@ -26,7 +27,7 @@ where | |||
26 | 'a: 'b, | 27 | 'a: 'b, |
27 | { | 28 | { |
28 | ctx: &'b mut InferenceContext<'a>, | 29 | ctx: &'b mut InferenceContext<'a>, |
29 | free_vars: Vec<InferTy>, | 30 | free_vars: Vec<(InferenceVar, TyVariableKind)>, |
30 | /// A stack of type variables that is used to detect recursive types (which | 31 | /// A stack of type variables that is used to detect recursive types (which |
31 | /// are an error, but we need to protect against them to avoid stack | 32 | /// are an error, but we need to protect against them to avoid stack |
32 | /// overflows). | 33 | /// overflows). |
@@ -36,17 +37,14 @@ where | |||
36 | #[derive(Debug)] | 37 | #[derive(Debug)] |
37 | pub(super) struct Canonicalized<T> { | 38 | pub(super) struct Canonicalized<T> { |
38 | pub(super) value: Canonical<T>, | 39 | pub(super) value: Canonical<T>, |
39 | free_vars: Vec<InferTy>, | 40 | free_vars: Vec<(InferenceVar, TyVariableKind)>, |
40 | } | 41 | } |
41 | 42 | ||
42 | impl<'a, 'b> Canonicalizer<'a, 'b> | 43 | impl<'a, 'b> Canonicalizer<'a, 'b> { |
43 | where | 44 | fn add(&mut self, free_var: InferenceVar, kind: TyVariableKind) -> usize { |
44 | 'a: 'b, | 45 | self.free_vars.iter().position(|&(v, _)| v == free_var).unwrap_or_else(|| { |
45 | { | ||
46 | fn add(&mut self, free_var: InferTy) -> usize { | ||
47 | self.free_vars.iter().position(|&v| v == free_var).unwrap_or_else(|| { | ||
48 | let next_index = self.free_vars.len(); | 46 | let next_index = self.free_vars.len(); |
49 | self.free_vars.push(free_var); | 47 | self.free_vars.push((free_var, kind)); |
50 | next_index | 48 | next_index |
51 | }) | 49 | }) |
52 | } | 50 | } |
@@ -54,11 +52,11 @@ where | |||
54 | fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: DebruijnIndex) -> T { | 52 | fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: DebruijnIndex) -> T { |
55 | t.fold_binders( | 53 | t.fold_binders( |
56 | &mut |ty, binders| match ty { | 54 | &mut |ty, binders| match ty { |
57 | Ty::Infer(tv) => { | 55 | Ty::InferenceVar(var, kind) => { |
58 | let inner = tv.to_inner(); | 56 | let inner = var.to_inner(); |
59 | if self.var_stack.contains(&inner) { | 57 | if self.var_stack.contains(&inner) { |
60 | // recursive type | 58 | // recursive type |
61 | return tv.fallback_value(); | 59 | return self.ctx.table.type_variable_table.fallback_value(var, kind); |
62 | } | 60 | } |
63 | if let Some(known_ty) = | 61 | if let Some(known_ty) = |
64 | self.ctx.table.var_unification_table.inlined_probe_value(inner).known() | 62 | self.ctx.table.var_unification_table.inlined_probe_value(inner).known() |
@@ -69,14 +67,8 @@ where | |||
69 | result | 67 | result |
70 | } else { | 68 | } else { |
71 | let root = self.ctx.table.var_unification_table.find(inner); | 69 | let root = self.ctx.table.var_unification_table.find(inner); |
72 | let free_var = match tv { | 70 | let position = self.add(InferenceVar::from_inner(root), kind); |
73 | InferTy::TypeVar(_) => InferTy::TypeVar(root), | 71 | Ty::BoundVar(BoundVar::new(binders, position)) |
74 | InferTy::IntVar(_) => InferTy::IntVar(root), | ||
75 | InferTy::FloatVar(_) => InferTy::FloatVar(root), | ||
76 | InferTy::MaybeNeverTypeVar(_) => InferTy::MaybeNeverTypeVar(root), | ||
77 | }; | ||
78 | let position = self.add(free_var); | ||
79 | Ty::Bound(BoundVar::new(binders, position)) | ||
80 | } | 72 | } |
81 | } | 73 | } |
82 | _ => ty, | 74 | _ => ty, |
@@ -86,19 +78,7 @@ where | |||
86 | } | 78 | } |
87 | 79 | ||
88 | fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { | 80 | fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { |
89 | let kinds = self | 81 | let kinds = self.free_vars.iter().map(|&(_, k)| k).collect(); |
90 | .free_vars | ||
91 | .iter() | ||
92 | .map(|v| match v { | ||
93 | // mapping MaybeNeverTypeVar to the same kind as general ones | ||
94 | // should be fine, because as opposed to int or float type vars, | ||
95 | // they don't restrict what kind of type can go into them, they | ||
96 | // just affect fallback. | ||
97 | InferTy::TypeVar(_) | InferTy::MaybeNeverTypeVar(_) => TyKind::General, | ||
98 | InferTy::IntVar(_) => TyKind::Integer, | ||
99 | InferTy::FloatVar(_) => TyKind::Float, | ||
100 | }) | ||
101 | .collect(); | ||
102 | Canonicalized { value: Canonical { value: result, kinds }, free_vars: self.free_vars } | 82 | Canonicalized { value: Canonical { value: result, kinds }, free_vars: self.free_vars } |
103 | } | 83 | } |
104 | 84 | ||
@@ -130,9 +110,10 @@ impl<T> Canonicalized<T> { | |||
130 | pub(super) fn decanonicalize_ty(&self, mut ty: Ty) -> Ty { | 110 | pub(super) fn decanonicalize_ty(&self, mut ty: Ty) -> Ty { |
131 | ty.walk_mut_binders( | 111 | ty.walk_mut_binders( |
132 | &mut |ty, binders| { | 112 | &mut |ty, binders| { |
133 | if let &mut Ty::Bound(bound) = ty { | 113 | if let &mut Ty::BoundVar(bound) = ty { |
134 | if bound.debruijn >= binders { | 114 | if bound.debruijn >= binders { |
135 | *ty = Ty::Infer(self.free_vars[bound.index]); | 115 | let (v, k) = self.free_vars[bound.index]; |
116 | *ty = Ty::InferenceVar(v, k); | ||
136 | } | 117 | } |
137 | } | 118 | } |
138 | }, | 119 | }, |
@@ -152,18 +133,18 @@ impl<T> Canonicalized<T> { | |||
152 | .kinds | 133 | .kinds |
153 | .iter() | 134 | .iter() |
154 | .map(|k| match k { | 135 | .map(|k| match k { |
155 | TyKind::General => ctx.table.new_type_var(), | 136 | TyVariableKind::General => ctx.table.new_type_var(), |
156 | TyKind::Integer => ctx.table.new_integer_var(), | 137 | TyVariableKind::Integer => ctx.table.new_integer_var(), |
157 | TyKind::Float => ctx.table.new_float_var(), | 138 | TyVariableKind::Float => ctx.table.new_float_var(), |
158 | }) | 139 | }) |
159 | .collect(), | 140 | .collect(), |
160 | ); | 141 | ); |
161 | for (i, ty) in solution.value.into_iter().enumerate() { | 142 | for (i, ty) in solution.value.into_iter().enumerate() { |
162 | let var = self.free_vars[i]; | 143 | let (v, k) = self.free_vars[i]; |
163 | // eagerly replace projections in the type; we may be getting types | 144 | // eagerly replace projections in the type; we may be getting types |
164 | // e.g. from where clauses where this hasn't happened yet | 145 | // e.g. from where clauses where this hasn't happened yet |
165 | let ty = ctx.normalize_associated_types_in(ty.clone().subst_bound_vars(&new_vars)); | 146 | let ty = ctx.normalize_associated_types_in(ty.clone().subst_bound_vars(&new_vars)); |
166 | ctx.table.unify(&Ty::Infer(var), &ty); | 147 | ctx.table.unify(&Ty::InferenceVar(v, k), &ty); |
167 | } | 148 | } |
168 | } | 149 | } |
169 | } | 150 | } |
@@ -187,7 +168,7 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substs> { | |||
187 | // (kind of hacky) | 168 | // (kind of hacky) |
188 | for (i, var) in vars.iter().enumerate() { | 169 | for (i, var) in vars.iter().enumerate() { |
189 | if &*table.resolve_ty_shallow(var) == var { | 170 | if &*table.resolve_ty_shallow(var) == var { |
190 | table.unify(var, &Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, i))); | 171 | table.unify(var, &Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i))); |
191 | } | 172 | } |
192 | } | 173 | } |
193 | Some( | 174 | Some( |
@@ -198,31 +179,73 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substs> { | |||
198 | } | 179 | } |
199 | 180 | ||
200 | #[derive(Clone, Debug)] | 181 | #[derive(Clone, Debug)] |
182 | pub(super) struct TypeVariableTable { | ||
183 | inner: Vec<TypeVariableData>, | ||
184 | } | ||
185 | |||
186 |