aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yaml2
-rw-r--r--Cargo.lock8
-rw-r--r--crates/hir/src/lib.rs36
-rw-r--r--crates/hir_def/src/attr.rs41
-rw-r--r--crates/hir_def/src/child_by_source.rs4
-rw-r--r--crates/hir_def/src/lib.rs13
-rw-r--r--crates/hir_def/src/nameres.rs28
-rw-r--r--crates/hir_def/src/nameres/collector.rs25
-rw-r--r--crates/hir_def/src/nameres/path_resolution.rs51
-rw-r--r--crates/hir_expand/src/builtin_derive.rs10
-rw-r--r--crates/hir_expand/src/builtin_macro.rs7
-rw-r--r--crates/hir_expand/src/db.rs7
-rw-r--r--crates/hir_expand/src/eager.rs5
-rw-r--r--crates/hir_expand/src/input.rs95
-rw-r--r--crates/hir_expand/src/lib.rs22
-rw-r--r--crates/hir_expand/src/proc_macro.rs102
-rw-r--r--crates/hir_ty/src/autoderef.rs44
-rw-r--r--crates/hir_ty/src/builder.rs12
-rw-r--r--crates/hir_ty/src/chalk_cast.rs73
-rw-r--r--crates/hir_ty/src/chalk_db.rs (renamed from crates/hir_ty/src/traits/chalk.rs)223
-rw-r--r--crates/hir_ty/src/chalk_ext.rs2
-rw-r--r--crates/hir_ty/src/db.rs52
-rw-r--r--crates/hir_ty/src/diagnostics.rs2
-rw-r--r--crates/hir_ty/src/display.rs52
-rw-r--r--crates/hir_ty/src/infer.rs26
-rw-r--r--crates/hir_ty/src/infer/coerce.rs10
-rw-r--r--crates/hir_ty/src/infer/expr.rs12
-rw-r--r--crates/hir_ty/src/infer/pat.rs4
-rw-r--r--crates/hir_ty/src/infer/path.rs2
-rw-r--r--crates/hir_ty/src/infer/unify.rs166
-rw-r--r--crates/hir_ty/src/interner.rs (renamed from crates/hir_ty/src/traits/chalk/interner.rs)127
-rw-r--r--crates/hir_ty/src/lib.rs216
-rw-r--r--crates/hir_ty/src/lower.rs48
-rw-r--r--crates/hir_ty/src/mapping.rs154
-rw-r--r--crates/hir_ty/src/method_resolution.rs103
-rw-r--r--crates/hir_ty/src/primitive.rs5
-rw-r--r--crates/hir_ty/src/tests/regression.rs38
-rw-r--r--crates/hir_ty/src/tests/traits.rs30
-rw-r--r--crates/hir_ty/src/tls.rs (renamed from crates/hir_ty/src/traits/chalk/tls.rs)14
-rw-r--r--crates/hir_ty/src/traits.rs44
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs546
-rw-r--r--crates/hir_ty/src/types.rs549
-rw-r--r--crates/hir_ty/src/utils.rs18
-rw-r--r--crates/hir_ty/src/walk.rs287
-rw-r--r--crates/ide/src/diagnostics.rs16
-rw-r--r--crates/ide/src/expand_macro.rs43
-rw-r--r--crates/ide/src/folding_ranges.rs17
-rw-r--r--crates/ide/src/syntax_highlighting/highlight.rs14
-rw-r--r--crates/ide/src/syntax_highlighting/tests.rs96
-rw-r--r--crates/ide/src/typing/on_enter.rs20
-rw-r--r--crates/ide_assists/src/handlers/remove_dbg.rs105
-rw-r--r--crates/rust-analyzer/Cargo.toml2
-rw-r--r--crates/rust-analyzer/src/to_proto.rs3
-rw-r--r--crates/test_utils/src/bench_fixture.rs3
-rw-r--r--docs/dev/architecture.md4
55 files changed, 1454 insertions, 2184 deletions
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 1850068a3..0f68b234c 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -76,7 +76,7 @@ jobs:
76 run: cargo test --no-run --locked 76 run: cargo test --no-run --locked
77 77
78 - name: Test 78 - name: Test
79 run: cargo test 79 run: cargo test -- --nocapture
80 80
81 - name: Prepare cache 81 - name: Prepare cache
82 run: cargo xtask pre-cache 82 run: cargo xtask pre-cache
diff --git a/Cargo.lock b/Cargo.lock
index bcb1cbd9f..d7e6d3ac8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -852,9 +852,9 @@ dependencies = [
852 852
853[[package]] 853[[package]]
854name = "lsp-types" 854name = "lsp-types"
855version = "0.88.0" 855version = "0.89.0"
856source = "registry+https://github.com/rust-lang/crates.io-index" 856source = "registry+https://github.com/rust-lang/crates.io-index"
857checksum = "d8e8e042772e4e10b3785822f63c82399d0dd233825de44d2596f7fa86e023e0" 857checksum = "07731ecd4ee0654728359a5b95e2a254c857876c04b85225496a35d60345daa7"
858dependencies = [ 858dependencies = [
859 "bitflags", 859 "bitflags",
860 "serde", 860 "serde",
@@ -1577,9 +1577,9 @@ dependencies = [
1577 1577
1578[[package]] 1578[[package]]
1579name = "syn" 1579name = "syn"
1580version = "1.0.68" 1580version = "1.0.69"
1581source = "registry+https://github.com/rust-lang/crates.io-index" 1581source = "registry+https://github.com/rust-lang/crates.io-index"
1582checksum = "3ce15dd3ed8aa2f8eeac4716d6ef5ab58b6b9256db41d7e1a0224c2788e8fd87" 1582checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb"
1583dependencies = [ 1583dependencies = [
1584 "proc-macro2", 1584 "proc-macro2",
1585 "quote", 1585 "quote",
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 0afc06906..eba46a056 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -1580,11 +1580,24 @@ impl Impl {
1580 ty.equals_ctor(rref.as_ref().map_or(&self_ty.ty, |it| &it.ty)) 1580 ty.equals_ctor(rref.as_ref().map_or(&self_ty.ty, |it| &it.ty))
1581 }; 1581 };
1582 1582
1583 let fp = TyFingerprint::for_inherent_impl(&ty);
1584 let fp = if let Some(fp) = fp {
1585 fp
1586 } else {
1587 return Vec::new();
1588 };
1589
1583 let mut all = Vec::new(); 1590 let mut all = Vec::new();
1584 def_crates.iter().for_each(|&id| { 1591 def_crates.iter().for_each(|&id| {
1585 all.extend(db.inherent_impls_in_crate(id).all_impls().map(Self::from).filter(filter)) 1592 all.extend(
1593 db.inherent_impls_in_crate(id)
1594 .for_self_ty(&ty)
1595 .into_iter()
1596 .cloned()
1597 .map(Self::from)
1598 .filter(filter),
1599 )
1586 }); 1600 });
1587 let fp = TyFingerprint::for_impl(&ty);
1588 for id in def_crates 1601 for id in def_crates
1589 .iter() 1602 .iter()
1590 .flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db)) 1603 .flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db))
@@ -1592,13 +1605,12 @@ impl Impl {
1592 .chain(def_crates.iter().copied()) 1605 .chain(def_crates.iter().copied())
1593 .unique() 1606 .unique()
1594 { 1607 {
1595 match fp { 1608 all.extend(
1596 Some(fp) => all.extend( 1609 db.trait_impls_in_crate(id)
1597 db.trait_impls_in_crate(id).for_self_ty(fp).map(Self::from).filter(filter), 1610 .for_self_ty_without_blanket_impls(fp)
1598 ), 1611 .map(Self::from)
1599 None => all 1612 .filter(filter),
1600 .extend(db.trait_impls_in_crate(id).all_impls().map(Self::from).filter(filter)), 1613 );
1601 }
1602 } 1614 }
1603 all 1615 all
1604 } 1616 }
@@ -1825,7 +1837,7 @@ impl Type {
1825 Solution::Unique(s) => s 1837 Solution::Unique(s) => s
1826 .value 1838 .value
1827 .subst 1839 .subst
1828 .interned() 1840 .as_slice(&Interner)
1829 .first() 1841 .first()
1830 .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone())), 1842 .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone())),
1831 Solution::Ambig(_) => None, 1843 Solution::Ambig(_) => None,
@@ -1903,7 +1915,9 @@ impl Type {
1903 | TyKind::Dyn(_) 1915 | TyKind::Dyn(_)
1904 | TyKind::Function(_) 1916 | TyKind::Function(_)
1905 | TyKind::Alias(_) 1917 | TyKind::Alias(_)
1906 | TyKind::Foreign(_) => false, 1918 | TyKind::Foreign(_)
1919 | TyKind::Generator(..)
1920 | TyKind::GeneratorWitness(..) => false,
1907 } 1921 }
1908 } 1922 }
1909 } 1923 }
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index d9df7564d..786fad6e1 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -9,7 +9,7 @@ use std::{
9use base_db::CrateId; 9use base_db::CrateId;
10use cfg::{CfgExpr, CfgOptions}; 10use cfg::{CfgExpr, CfgOptions};
11use either::Either; 11use either::Either;
12use hir_expand::{hygiene::Hygiene, name::AsName, AstId, InFile}; 12use hir_expand::{hygiene::Hygiene, name::AsName, AstId, AttrId, InFile};
13use itertools::Itertools; 13use itertools::Itertools;
14use la_arena::ArenaMap; 14use la_arena::ArenaMap;
15use mbe::ast_to_token_tree; 15use mbe::ast_to_token_tree;
@@ -98,13 +98,16 @@ impl RawAttrs {
98 pub(crate) fn new(owner: &dyn ast::AttrsOwner, hygiene: &Hygiene) -> Self { 98 pub(crate) fn new(owner: &dyn ast::AttrsOwner, hygiene: &Hygiene) -> Self {
99 let entries = collect_attrs(owner) 99 let entries = collect_attrs(owner)
100 .enumerate() 100 .enumerate()
101 .flat_map(|(i, attr)| match attr { 101 .flat_map(|(i, attr)| {
102 Either::Left(attr) => Attr::from_src(attr, hygiene, i as u32), 102 let index = AttrId(i as u32);
103 Either::Right(comment) => comment.doc_comment().map(|doc| Attr { 103 match attr {
104 index: i as u32, 104 Either::Left(attr) => Attr::from_src(attr, hygiene, index),
105 input: Some(AttrInput::Literal(SmolStr::new(doc))), 105 Either::Right(comment) => comment.doc_comment().map(|doc| Attr {
106 path: Interned::new(ModPath::from(hir_expand::name!(doc))), 106 id: index,
107 }), 107 input: Some(AttrInput::Literal(SmolStr::new(doc))),
108 path: Interned::new(ModPath::from(hir_expand::name!(doc))),
109 }),
110 }
108 }) 111 })
109 .collect::<Arc<_>>(); 112 .collect::<Arc<_>>();
110 113
@@ -161,7 +164,7 @@ impl RawAttrs {
161 let cfg = parts.next().unwrap(); 164 let cfg = parts.next().unwrap();
162 let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() }; 165 let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() };
163 let cfg = CfgExpr::parse(&cfg); 166 let cfg = CfgExpr::parse(&cfg);
164 let index = attr.index; 167 let index = attr.id;
165 let attrs = parts.filter(|a| !a.is_empty()).filter_map(|attr| { 168 let attrs = parts.filter(|a| !a.is_empty()).filter_map(|attr| {
166 let tree = Subtree { delimiter: None, token_trees: attr.to_vec() }; 169 let tree = Subtree { delimiter: None, token_trees: attr.to_vec() };
167 let attr = ast::Attr::parse(&format!("#[{}]", tree)).ok()?; 170 let attr = ast::Attr::parse(&format!("#[{}]", tree)).ok()?;
@@ -468,7 +471,7 @@ impl AttrsWithOwner {
468 ) -> Option<(Documentation, DocsRangeMap)> { 471 ) -> Option<(Documentation, DocsRangeMap)> {
469 // FIXME: code duplication in `docs` above 472 // FIXME: code duplication in `docs` above
470 let docs = self.by_key("doc").attrs().flat_map(|attr| match attr.input.as_ref()? { 473 let docs = self.by_key("doc").attrs().flat_map(|attr| match attr.input.as_ref()? {
471 AttrInput::Literal(s) => Some((s, attr.index)), 474 AttrInput::Literal(s) => Some((s, attr.id)),
472 AttrInput::TokenTree(_) => None, 475 AttrInput::TokenTree(_) => None,
473 }); 476 });
474 let indent = docs 477 let indent = docs
@@ -560,8 +563,8 @@ impl AttrSourceMap {
560 /// the attribute represented by `Attr`. 563 /// the attribute represented by `Attr`.
561 pub fn source_of(&self, attr: &Attr) -> InFile<&Either<ast::Attr, ast::Comment>> { 564 pub fn source_of(&self, attr: &Attr) -> InFile<&Either<ast::Attr, ast::Comment>> {
562 self.attrs 565 self.attrs
563 .get(attr.index as usize) 566 .get(attr.id.0 as usize)
564 .unwrap_or_else(|| panic!("cannot find `Attr` at index {}", attr.index)) 567 .unwrap_or_else(|| panic!("cannot find `Attr` at index {:?}", attr.id))
565 .as_ref() 568 .as_ref()
566 } 569 }
567} 570}
@@ -572,7 +575,7 @@ pub struct DocsRangeMap {
572 // (docstring-line-range, attr_index, attr-string-range) 575 // (docstring-line-range, attr_index, attr-string-range)
573 // a mapping from the text range of a line of the [`Documentation`] to the attribute index and 576 // a mapping from the text range of a line of the [`Documentation`] to the attribute index and
574 // the original (untrimmed) syntax doc line 577 // the original (untrimmed) syntax doc line
575 mapping: Vec<(TextRange, u32, TextRange)>, 578 mapping: Vec<(TextRange, AttrId, TextRange)>,
576} 579}
577 580
578impl DocsRangeMap { 581impl DocsRangeMap {
@@ -585,7 +588,7 @@ impl DocsRangeMap {
585 588
586 let relative_range = range - line_docs_range.start(); 589 let relative_range = range - line_docs_range.start();
587 590
588 let &InFile { file_id, value: ref source } = &self.source[idx as usize]; 591 let &InFile { file_id, value: ref source } = &self.source[idx.0 as usize];
589 match source { 592 match source {
590 Either::Left(_) => None, // FIXME, figure out a nice way to handle doc attributes here 593 Either::Left(_) => None, // FIXME, figure out a nice way to handle doc attributes here
591 // as well as for whats done in syntax highlight doc injection 594 // as well as for whats done in syntax highlight doc injection
@@ -606,7 +609,7 @@ impl DocsRangeMap {
606 609
607#[derive(Debug, Clone, PartialEq, Eq)] 610#[derive(Debug, Clone, PartialEq, Eq)]
608pub struct Attr { 611pub struct Attr {
609 index: u32, 612 pub(crate) id: AttrId,
610 pub(crate) path: Interned<ModPath>, 613 pub(crate) path: Interned<ModPath>,
611 pub(crate) input: Option<AttrInput>, 614 pub(crate) input: Option<AttrInput>,
612} 615}
@@ -620,7 +623,7 @@ pub enum AttrInput {
620} 623}
621 624
622impl Attr { 625impl Attr {
623 fn from_src(ast: ast::Attr, hygiene: &Hygiene, index: u32) -> Option<Attr> { 626 fn from_src(ast: ast::Attr, hygiene: &Hygiene, id: AttrId) -> Option<Attr> {
624 let path = Interned::new(ModPath::from_src(ast.path()?, hygiene)?); 627 let path = Interned::new(ModPath::from_src(ast.path()?, hygiene)?);
625 let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() { 628 let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() {
626 let value = match lit.kind() { 629 let value = match lit.kind() {
@@ -633,7 +636,7 @@ impl Attr {
633 } else { 636 } else {
634 None 637 None
635 }; 638 };
636 Some(Attr { index, path, input }) 639 Some(Attr { id, path, input })
637 } 640 }
638 641
639 /// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths 642 /// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths
@@ -748,9 +751,7 @@ fn collect_attrs(
748 .chain(inner_docs.into_iter().flatten()) 751 .chain(inner_docs.into_iter().flatten())
749 .map(|docs_text| (docs_text.syntax().text_range().start(), Either::Right(docs_text))); 752 .map(|docs_text| (docs_text.syntax().text_range().start(), Either::Right(docs_text)));
750 // sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved 753 // sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved
751 let attrs: Vec<_> = docs.chain(attrs).sorted_by_key(|&(offset, _)| offset).collect(); 754 docs.chain(attrs).sorted_by_key(|&(offset, _)| offset).map(|(_, attr)| attr)
752
753 attrs.into_iter().map(|(_, attr)| attr)
754} 755}
755 756
756pub(crate) fn variants_attrs_source_map( 757pub(crate) fn variants_attrs_source_map(
diff --git a/crates/hir_def/src/child_by_source.rs b/crates/hir_def/src/child_by_source.rs
index f40a7f80d..f2e809ca9 100644
--- a/crates/hir_def/src/child_by_source.rs
+++ b/crates/hir_def/src/child_by_source.rs
@@ -80,6 +80,10 @@ impl ChildBySource for ModuleId {
80impl ChildBySource for ItemScope { 80impl ChildBySource for ItemScope {
81 fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { 81 fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) {
82 self.declarations().for_each(|item| add_module_def(db, res, item)); 82 self.declarations().for_each(|item| add_module_def(db, res, item));
83 self.unnamed_consts().for_each(|konst| {
84 let src = konst.lookup(db).source(db);
85 res[keys::CONST].insert(src, konst);
86 });
83 self.impls().for_each(|imp| add_impl(db, res, imp)); 87 self.impls().for_each(|imp| add_impl(db, res, imp));
84 88
85 fn add_module_def(db: &dyn DefDatabase, map: &mut DynMap, item: ModuleDefId) { 89 fn add_module_def(db: &dyn DefDatabase, map: &mut DynMap, item: ModuleDefId) {
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs
index e2af0e514..d69116d51 100644
--- a/crates/hir_def/src/lib.rs
+++ b/crates/hir_def/src/lib.rs
@@ -62,7 +62,7 @@ use hir_expand::{
62 ast_id_map::FileAstId, 62 ast_id_map::FileAstId,
63 eager::{expand_eager_macro, ErrorEmitted, ErrorSink}, 63 eager::{expand_eager_macro, ErrorEmitted, ErrorSink},
64 hygiene::Hygiene, 64 hygiene::Hygiene,
65 AstId, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, 65 AstId, AttrId, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
66}; 66};
67use la_arena::Idx; 67use la_arena::Idx;
68use nameres::DefMap; 68use nameres::DefMap;
@@ -690,13 +690,16 @@ fn macro_call_as_call_id(
690 ) 690 )
691 .map(MacroCallId::from) 691 .map(MacroCallId::from)
692 } else { 692 } else {
693 Ok(def.as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike(call.ast_id)).into()) 693 Ok(def
694 .as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike { ast_id: call.ast_id })
695 .into())
694 }; 696 };
695 Ok(res) 697 Ok(res)
696} 698}
697 699
698fn derive_macro_as_call_id( 700fn derive_macro_as_call_id(
699 item_attr: &AstIdWithPath<ast::Item>, 701 item_attr: &AstIdWithPath<ast::Item>,
702 derive_attr: AttrId,
700 db: &dyn db::DefDatabase, 703 db: &dyn db::DefDatabase,
701 krate: CrateId, 704 krate: CrateId,
702 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, 705 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
@@ -707,7 +710,11 @@ fn derive_macro_as_call_id(
707 .as_lazy_macro( 710 .as_lazy_macro(
708 db.upcast(), 711 db.upcast(),
709 krate, 712 krate,
710 MacroCallKind::Derive(item_attr.ast_id, last_segment.to_string()), 713 MacroCallKind::Derive {
714 ast_id: item_attr.ast_id,
715 derive_name: last_segment.to_string(),
716 derive_attr,
717 },
711 ) 718 )
712 .into(); 719 .into();
713 Ok(res) 720 Ok(res)
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs
index 7dd68219f..9e181751c 100644
--- a/crates/hir_def/src/nameres.rs
+++ b/crates/hir_def/src/nameres.rs
@@ -613,12 +613,12 @@ mod diagnostics {
613 DiagnosticKind::UnresolvedProcMacro { ast } => { 613 DiagnosticKind::UnresolvedProcMacro { ast } => {
614 let mut precise_location = None; 614 let mut precise_location = None;
615 let (file, ast, name) = match ast { 615 let (file, ast, name) = match ast {
616 MacroCallKind::FnLike(ast) => { 616 MacroCallKind::FnLike { ast_id } => {
617 let node = ast.to_node(db.upcast()); 617 let node = ast_id.to_node(db.upcast());
618 (ast.file_id, SyntaxNodePtr::from(AstPtr::new(&node)), None) 618 (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)), None)
619 } 619 }
620 MacroCallKind::Derive(ast, name) => { 620 MacroCallKind::Derive { ast_id, derive_name, .. } => {
621 let node = ast.to_node(db.upcast()); 621 let node = ast_id.to_node(db.upcast());
622 622
623 // Compute the precise location of the macro name's token in the derive 623 // Compute the precise location of the macro name's token in the derive
624 // list. 624 // list.
@@ -639,7 +639,7 @@ mod diagnostics {
639 }); 639 });
640 for token in tokens { 640 for token in tokens {
641 if token.kind() == SyntaxKind::IDENT 641 if token.kind() == SyntaxKind::IDENT
642 && token.text() == name.as_str() 642 && token.text() == derive_name.as_str()
643 { 643 {
644 precise_location = Some(token.text_range()); 644 precise_location = Some(token.text_range());
645 break 'outer; 645 break 'outer;
@@ -648,9 +648,9 @@ mod diagnostics {
648 } 648 }
649 649
650 ( 650 (
651 ast.file_id, 651 ast_id.file_id,
652 SyntaxNodePtr::from(AstPtr::new(&node)), 652 SyntaxNodePtr::from(AstPtr::new(&node)),
653 Some(name.clone()), 653 Some(derive_name.clone()),
654 ) 654 )
655 } 655 }
656 }; 656 };
@@ -669,13 +669,13 @@ mod diagnostics {
669 669
670 DiagnosticKind::MacroError { ast, message } => { 670 DiagnosticKind::MacroError { ast, message } => {
671 let (file, ast) = match ast { 671 let (file, ast) = match ast {
672 MacroCallKind::FnLike(ast) => { 672 MacroCallKind::FnLike { ast_id, .. } => {
673 let node = ast.to_node(db.upcast()); 673 let node = ast_id.to_node(db.upcast());
674 (ast.file_id, SyntaxNodePtr::from(AstPtr::new(&node))) 674 (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)))
675 } 675 }
676 MacroCallKind::Derive(ast, _) => { 676 MacroCallKind::Derive { ast_id, .. } => {
677 let node = ast.to_node(db.upcast()); 677 let node = ast_id.to_node(db.upcast());
678 (ast.file_id, SyntaxNodePtr::from(AstPtr::new(&node))) 678 (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)))
679 } 679 }
680 }; 680 };
681 sink.push(MacroError { file, node: ast, message: message.clone() }); 681 sink.push(MacroError { file, node: ast, message: message.clone() });
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 492d8c71f..fb4ddff5e 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 AttrId, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
17}; 17};
18use hir_expand::{InFile, MacroCallLoc}; 18use hir_expand::{InFile, MacroCallLoc};
19use rustc_hash::{FxHashMap, FxHashSet}; 19use rustc_hash::{FxHashMap, FxHashSet};
@@ -216,7 +216,7 @@ struct MacroDirective {
216#[derive(Clone, Debug, Eq, PartialEq)] 216#[derive(Clone, Debug, Eq, PartialEq)]
217enum MacroDirectiveKind { 217enum MacroDirectiveKind {
218 FnLike { ast_id: AstIdWithPath<ast::MacroCall> }, 218 FnLike { ast_id: AstIdWithPath<ast::MacroCall> },
219 Derive { ast_id: AstIdWithPath<ast::Item> }, 219 Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId },
220} 220}
221 221
222struct DefData<'a> { 222struct DefData<'a> {
@@ -478,7 +478,7 @@ impl DefCollector<'_> {
478 self.def_map.edition, 478 self.def_map.edition,
479 ); 479 );
480 480
481 let res = self.def_map.resolve_name_in_extern_prelude(&extern_crate.name); 481 let res = self.def_map.resolve_name_in_extern_prelude(self.db, &extern_crate.name);
482 482
483 if let Some(ModuleDefId::ModuleId(m)) = res.take_types() { 483 if let Some(ModuleDefId::ModuleId(m)) = res.take_types() {
484 cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use); 484 cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use);
@@ -534,6 +534,7 @@ impl DefCollector<'_> {
534 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition); 534 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition);
535 if import.is_extern_crate { 535 if import.is_extern_crate {
536 let res = self.def_map.resolve_name_in_extern_prelude( 536 let res = self.def_map.resolve_name_in_extern_prelude(
537 self.db,
537 &import 538 &import
538 .path 539 .path
539 .as_ident() 540 .as_ident()
@@ -831,12 +832,16 @@ impl DefCollector<'_> {
831 Err(UnresolvedMacro) | Ok(Err(_)) => {} 832 Err(UnresolvedMacro) | Ok(Err(_)) => {}
832 } 833 }
833 } 834 }
834 MacroDirectiveKind::Derive { ast_id } => { 835 MacroDirectiveKind::Derive { ast_id, derive_attr } => {
835 match derive_macro_as_call_id(ast_id, self.db, self.def_map.krate, |path| { 836 match derive_macro_as_call_id(
836 self.resolve_derive_macro(directive.module_id, &path) 837 ast_id,
837 }) { 838 *derive_attr,
839 self.db,
840 self.def_map.krate,
841 |path| self.resolve_derive_macro(directive.module_id, &path),
842 ) {
838 Ok(call_id) => { 843 Ok(call_id) => {
839 resolved.push((directive.module_id, call_id, 0)); 844 resolved.push((directive.module_id, call_id, directive.depth));
840 res = ReachedFixedPoint::No; 845 res = ReachedFixedPoint::No;
841 return false; 846 return false;
842 } 847 }
@@ -1368,7 +1373,7 @@ impl ModCollector<'_, '_> {
1368 self.def_collector.unexpanded_macros.push(MacroDirective { 1373 self.def_collector.unexpanded_macros.push(MacroDirective {
1369 module_id: self.module_id, 1374 module_id: self.module_id,
1370 depth: self.macro_depth + 1, 1375 depth: self.macro_depth + 1,
1371 kind: MacroDirectiveKind::Derive { ast_id }, 1376 kind: MacroDirectiveKind::Derive { ast_id, derive_attr: derive.id },
1372 }); 1377 });
1373 } 1378 }
1374 } 1379 }
@@ -1520,7 +1525,7 @@ impl ModCollector<'_, '_> {
1520 // Built-in macro failed eager expansion. 1525 // Built-in macro failed eager expansion.
1521 self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error( 1526 self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error(
1522 self.module_id, 1527 self.module_id,
1523 MacroCallKind::FnLike(ast_id.ast_id), 1528 MacroCallKind::FnLike { ast_id: ast_id.ast_id },
1524 error.unwrap().to_string(), 1529 error.unwrap().to_string(),
1525 )); 1530 ));
1526 return; 1531 return;
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs
index 60471937c..ccc9f22eb 100644
--- a/crates/hir_def/src/nameres/path_resolution.rs
+++ b/crates/hir_def/src/nameres/path_resolution.rs
@@ -60,12 +60,26 @@ impl ResolvePathResult {
60} 60}
61 61
62impl DefMap { 62impl DefMap {
63 pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs { 63 pub(super) fn resolve_name_in_extern_prelude(
64 &self,
65 db: &dyn DefDatabase,
66 name: &Name,
67 ) -> PerNs {
64 if name == &name!(self) { 68 if name == &name!(self) {
65 cov_mark::hit!(extern_crate_self_as); 69 cov_mark::hit!(extern_crate_self_as);
66 return PerNs::types(self.module_id(self.root).into(), Visibility::Public); 70 return PerNs::types(self.module_id(self.root).into(), Visibility::Public);
67 } 71 }
68 self.extern_prelude 72
73 let arc;
74 let root = match self.block {
75 Some(_) => {
76 arc = self.crate_root(db).def_map(db);
77 &*arc
78 }
79 None => self,
80 };
81
82 root.extern_prelude
69 .get(name) 83 .get(name)
70 .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)) 84 .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public))
71 } 85 }
@@ -191,7 +205,7 @@ impl DefMap {
191 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), 205 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
192 }; 206 };
193 log::debug!("resolving {:?} in crate root (+ extern prelude)", segment); 207 log::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
194 self.resolve_name_in_crate_root_or_extern_prelude(&segment) 208 self.resolve_name_in_crate_root_or_extern_prelude(db, &segment)
195 } 209 }
196 PathKind::Plain => { 210 PathKind::Plain => {
197 let (_, segment) = match segments.next() { 211 let (_, segment) = match segments.next() {
@@ -384,24 +398,31 @@ impl DefMap {
384 } 398 }
385 } 399 }
386 }; 400 };
387 // Give precedence to names in outer `DefMap`s over the extern prelude; only check prelude 401 let from_extern_prelude = self
388 // from the crate DefMap. 402 .extern_prelude
389 let from_extern_prelude = match self.block { 403 .get(name)
390 Some(_) => PerNs::none(), 404 .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public));
391 None => self
392 .extern_prelude
393 .get(name)
394 .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)),
395 };
396 405
397 let from_prelude = self.resolve_in_prelude(db, name); 406 let from_prelude = self.resolve_in_prelude(db, name);
398 407
399 from_legacy_macro.or(from_scope_or_builtin).or(from_extern_prelude).or(from_prelude) 408 from_legacy_macro.or(from_scope_or_builtin).or(from_extern_prelude).or(from_prelude)
400 } 409 }
401 410
402 fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs { 411 fn resolve_name_in_crate_root_or_extern_prelude(
403 let from_crate_root = self[self.root].scope.get(name); 412 &self,
404 let from_extern_prelude = self.resolve_name_in_extern_prelude(name); 413 db: &dyn DefDatabase,
414 name: &Name,
415 ) -> PerNs {
416 let arc;
417 let crate_def_map = match self.block {
418 Some(_) => {
419 arc = self.crate_root(db).def_map(db);
420 &arc
421 }
422 None => self,
423 };
424 let from_crate_root = crate_def_map[crate_def_map.root].scope.get(name);
425 let from_extern_prelude = self.resolve_name_in_extern_prelude(db, name);
405 426
406 from_crate_root.or(from_extern_prelude) 427 from_crate_root.or(from_extern_prelude)
407 } 428 }
diff --git a/crates/hir_expand/src/builtin_derive.rs b/crates/hir_expand/src/builtin_derive.rs
index 6ece4b289..537c03028 100644
--- a/crates/hir_expand/src/builtin_derive.rs
+++ b/crates/hir_expand/src/builtin_derive.rs
@@ -269,7 +269,7 @@ mod tests {
269 use expect_test::{expect, Expect}; 269 use expect_test::{expect, Expect};
270 use name::AsName; 270 use name::AsName;
271 271
272 use crate::{test_db::TestDB, AstId, MacroCallId, MacroCallKind, MacroCallLoc}; 272 use crate::{test_db::TestDB, AstId, AttrId, MacroCallId, MacroCallKind, MacroCallLoc};
273 273
274 use super::*; 274 use super::*;
275 275
@@ -308,7 +308,7 @@ $0
308 308
309 let expander = BuiltinDeriveExpander::find_by_name(&name).unwrap(); 309 let expander = BuiltinDeriveExpander::find_by_name(&name).unwrap();
310 310
311 let attr_id = AstId::new(file_id.into(), ast_id_map.ast_id(&items[0])); 311 let ast_id = AstId::new(file_id.into(), ast_id_map.ast_id(&items[0]));
312 312
313 let loc = MacroCallLoc { 313 let loc = MacroCallLoc {
314 def: MacroDefId { 314 def: MacroDefId {
@@ -317,7 +317,11 @@ $0
317 local_inner: false, 317 local_inner: false,
318 }, 318 },
319 krate: CrateId(0), 319 krate: CrateId(0),
320 kind: MacroCallKind::Derive(attr_id, name.to_string()), 320 kind: MacroCallKind::Derive {
321 ast_id,
322 derive_name: name.to_string(),
323 derive_attr: AttrId(0),
324 },
321 }; 325 };
322 326
323 let id: MacroCallId = db.intern_macro(loc).into(); 327 let id: MacroCallId = db.intern_macro(loc).into();
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs
index a7d0f5b1f..80365fc16 100644
--- a/crates/hir_expand/src/builtin_macro.rs
+++ b/crates/hir_expand/src/builtin_macro.rs
@@ -566,10 +566,9 @@ mod tests {
566 let loc = MacroCallLoc { 566 let loc = MacroCallLoc {
567 def, 567 def,
568 krate, 568 krate,
569 kind: MacroCallKind::FnLike(AstId::new( 569 kind: MacroCallKind::FnLike {
570 file_id.into(), 570 ast_id: AstId::new(file_id.into(), ast_id_map.ast_id(&macro_call)),
571 ast_id_map.ast_id(&macro_call), 571 },
572 )),
573 }; 572 };
574 573
575 let id: MacroCallId = db.intern_macro(loc).into(); 574 let id: MacroCallId = db.intern_macro(loc).into();
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index 10fe60821..95dc12744 100644
--- a/crates/hir_expand/src/db.rs
+++ b/crates/hir_expand/src/db.rs
@@ -14,9 +14,9 @@ use syntax::{
14}; 14};
15 15
16use crate::{ 16use crate::{
17 ast_id_map::AstIdMap, hygiene::HygieneFrame, BuiltinDeriveExpander, BuiltinFnLikeExpander, 17 ast_id_map::AstIdMap, hygiene::HygieneFrame, input::process_macro_input, BuiltinDeriveExpander,
18 EagerCallLoc, EagerMacroId, HirFileId, HirFileIdRepr, LazyMacroId, MacroCallId, MacroCallLoc, 18 BuiltinFnLikeExpander, EagerCallLoc, EagerMacroId, HirFileId, HirFileIdRepr, LazyMacroId,
19 MacroDefId, MacroDefKind, MacroFile, ProcMacroExpander, 19 MacroCallId, MacroCallLoc, MacroDefId, MacroDefKind, MacroFile, ProcMacroExpander,
20}; 20};
21 21
22/// Total limit on the number of tokens produced by any macro invocation. 22/// Total limit on the number of tokens produced by any macro invocation.
@@ -191,6 +191,7 @@ fn macro_arg_text(db: &dyn AstDatabase, id: MacroCallId) -> Option<GreenNode> {
191 }; 191 };
192 let loc = db.lookup_intern_macro(id); 192 let loc = db.lookup_intern_macro(id);
193 let arg = loc.kind.arg(db)?; 193 let arg = loc.kind.arg(db)?;
194 let arg = process_macro_input(db, arg, id);
194 Some(arg.green()) 195 Some(arg.green())
195} 196}
196 197
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs
index 9705526fa..ef126e4ad 100644
--- a/crates/hir_expand/src/eager.rs
+++ b/crates/hir_expand/src/eager.rs
@@ -174,8 +174,9 @@ fn lazy_expand(
174) -> ExpandResult<Option<InFile<SyntaxNode>>> { 174) -> ExpandResult<Option<InFile<SyntaxNode>>> {
175 let ast_id = db.ast_id_map(macro_call.file_id).ast_id(&macro_call.value); 175 let ast_id = db.ast_id_map(macro_call.file_id).ast_id(&macro_call.value);
176 176
177 let id: MacroCallId = 177 let id: MacroCallId = def
178 def.as_lazy_macro(db, krate, MacroCallKind::FnLike(macro_call.with_value(ast_id))).into(); 178 .as_lazy_macro(db, krate, MacroCallKind::FnLike { ast_id: macro_call.with_value(ast_id) })
179 .into();
179 180
180 let err = db.macro_expand_error(id); 181 let err = db.macro_expand_error(id);
181 let value = db.parse_or_expand(id.as_file()).map(|node| InFile::new(id.as_file(), node)); 182 let value = db.parse_or_expand(id.as_file()).map(|node| InFile::new(id.as_file(), node));
diff --git a/crates/hir_expand/src/input.rs b/crates/hir_expand/src/input.rs
new file mode 100644
index 000000000..d1f22aba4
--- /dev/null
+++ b/crates/hir_expand/src/input.rs
@@ -0,0 +1,95 @@
1//! Macro input conditioning.
2
3use syntax::{
4 ast::{self, AttrsOwner},
5 AstNode, SyntaxNode,
6};
7
8use crate::{
9 db::AstDatabase,
10 name::{name, AsName},
11 AttrId, LazyMacroId, MacroCallKind, MacroCallLoc,
12};
13
14pub(crate) fn process_macro_input(
15 db: &dyn AstDatabase,
16 node: SyntaxNode,
17 id: LazyMacroId,
18) -> SyntaxNode {
19 let loc: MacroCallLoc = db.lookup_intern_macro(id);
20
21 match loc.kind {
22 MacroCallKind::FnLike { .. } => node,
23 MacroCallKind::Derive { derive_attr, .. } => {
24 let item = match ast::Item::cast(node.clone()) {
25 Some(item) => item,
26 None => return node,
27 };
28
29 remove_derives_up_to(item, derive_attr).syntax().clone()
30 }
31 }
32}
33
34/// Removes `#[derive]` attributes from `item`, up to `attr`.
35fn remove_derives_up_to(item: ast::Item, attr: AttrId) -> ast::Item {
36 let item = item.clone_for_update();
37 let idx = attr.0 as usize;
38 for attr in item.attrs().take(idx + 1) {
39 if let Some(name) =
40 attr.path().and_then(|path| path.as_single_segment()).and_then(|seg| seg.name_ref())
41 {
42 if name.as_name() == name![derive] {
43 attr.syntax().detach();
44 }
45 }
46 }
47 item
48}
49
50#[cfg(test)]
51mod tests {
52 use base_db::fixture::WithFixture;
53 use base_db::SourceDatabase;
54 use expect_test::{expect, Expect};
55
56 use crate::test_db::TestDB;
57
58 use super::*;
59
60 fn test_remove_derives_up_to(attr: AttrId, ra_fixture: &str, expect: Expect) {
61 let (db, file_id) = TestDB::with_single_file(&ra_fixture);
62 let parsed = db.parse(file_id);
63
64 let mut items: Vec<_> =
65 parsed.syntax_node().descendants().filter_map(ast::Item::cast).collect();
66 assert_eq!(items.len(), 1);
67
68 let item = remove_derives_up_to(items.pop().unwrap(), attr);
69 expect.assert_eq(&item.to_string());
70 }
71
72 #[test]
73 fn remove_derive() {
74 test_remove_derives_up_to(
75 AttrId(2),
76 r#"
77#[allow(unused)]
78#[derive(Copy)]
79#[derive(Hello)]
80#[derive(Clone)]
81struct A {
82 bar: u32
83}
84 "#,
85 expect![[r#"
86#[allow(unused)]
87
88
89#[derive(Clone)]
90struct A {
91 bar: u32
92}"#]],
93 );
94 }
95}
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs
index 3e332ee47..7349fdfe4 100644
--- a/crates/hir_expand/src/lib.rs
+++ b/crates/hir_expand/src/lib.rs
@@ -14,6 +14,7 @@ pub mod builtin_macro;
14pub mod proc_macro; 14pub mod proc_macro;
15pub mod quote; 15pub mod quote;
16pub mod eager; 16pub mod eager;
17mod input;
17 18
18use either::Either; 19use either::Either;
19pub use mbe::{ExpandError, ExpandResult}; 20pub use mbe::{ExpandError, ExpandResult};
@@ -290,22 +291,27 @@ pub struct MacroCallLoc {
290 291
291#[derive(Debug, Clone, PartialEq, Eq, Hash)] 292#[derive(Debug, Clone, PartialEq, Eq, Hash)]
292pub enum MacroCallKind { 293pub enum MacroCallKind {
293 FnLike(AstId<ast::MacroCall>), 294 FnLike { ast_id: AstId<ast::MacroCall> },
294 Derive(AstId<ast::Item>, String), 295 Derive { ast_id: AstId<ast::Item>, derive_name: String, derive_attr: AttrId },
295} 296}
296 297
298#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
299pub struct AttrId(pub u32);
300
297impl MacroCallKind { 301impl MacroCallKind {
298 fn file_id(&self) -> HirFileId { 302 fn file_id(&self) -> HirFileId {
299 match self { 303 match self {
300 MacroCallKind::FnLike(ast_id) => ast_id.file_id, 304 MacroCallKind::FnLike { ast_id, .. } => ast_id.file_id,
301 MacroCallKind::Derive(ast_id, _) => ast_id.file_id, 305 MacroCallKind::Derive { ast_id, .. } => ast_id.file_id,
302 } 306 }
303 } 307 }
304 308
305 fn node(&self, db: &dyn db::AstDatabase) -> InFile<SyntaxNode> { 309 fn node(&self, db: &dyn db::AstDatabase) -> InFile<SyntaxNode> {
306 match self { 310 match self {
307 MacroCallKind::FnLike(ast_id) => ast_id.with_value(ast_id.to_node(db).syntax().clone()), 311 MacroCallKind::FnLike { ast_id, .. } => {
308 MacroCallKind::Derive(ast_id, _) => { 312 ast_id.with_value(ast_id.to_node(db).syntax().clone())
313 }
314 MacroCallKind::Derive { ast_id, .. } => {
309 ast_id.with_value(ast_id.to_node(db).syntax().clone()) 315 ast_id.with_value(ast_id.to_node(db).syntax().clone())
310 } 316 }
311 } 317 }
@@ -313,10 +319,10 @@ impl MacroCallKind {
313 319
314 fn arg(&self, db: &dyn db::AstDatabase) -> Option<SyntaxNode> { 320 fn arg(&self, db: &dyn db::AstDatabase) -> Option<SyntaxNode> {
315 match self { 321 match self {
316 MacroCallKind::FnLike(ast_id) => { 322 MacroCallKind::FnLike { ast_id, .. } => {
317 Some(ast_id.to_node(db).token_tree()?.syntax().clone()) 323 Some(ast_id.to_node(db).token_tree()?.syntax().clone())
318 } 324 }
319 MacroCallKind::Derive(ast_id, _) => Some(ast_id.to_node(db).syntax().clone()), 325 MacroCallKind::Derive { ast_id, .. } => Some(ast_id.to_node(db).syntax().clone()),
320 } 326 }
321 } 327 }
322} 328}
diff --git a/crates/hir_expand/src/proc_macro.rs b/crates/hir_expand/src/proc_macro.rs
index 75e950816..d5643393a 100644
--- a/crates/hir_expand/src/proc_macro.rs
+++ b/crates/hir_expand/src/proc_macro.rs
@@ -2,7 +2,6 @@
2 2
3use crate::db::AstDatabase; 3use crate::db::AstDatabase;
4use base_db::{CrateId, ProcMacroId}; 4use base_db::{CrateId, ProcMacroId};
5use tt::buffer::{Cursor, TokenBuffer};
6 5
7#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] 6#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
8pub struct ProcMacroExpander { 7pub struct ProcMacroExpander {
@@ -44,9 +43,6 @@ impl ProcMacroExpander {
44 .clone() 43 .clone()
45 .ok_or_else(|| err!("No derive macro found."))?; 44 .ok_or_else(|| err!("No derive macro found."))?;
46 45
47 let tt = remove_derive_attrs(tt)
48 .ok_or_else(|| err!("Fail to remove derive for custom derive"))?;
49
50 // Proc macros have access to the environment variables of the invoking crate. 46 // Proc macros have access to the environment variables of the invoking crate.
51 let env = &krate_graph[calling_crate].env; 47 let env = &krate_graph[calling_crate].env;
52 48
@@ -56,101 +52,3 @@ impl ProcMacroExpander {
56 } 52 }
57 } 53 }
58} 54}
59
60fn eat_punct(cursor: &mut Cursor, c: char) -> bool {
61 if let Some(tt::buffer::TokenTreeRef::Leaf(tt::Leaf::Punct(punct), _)) = cursor.token_tree() {
62 if punct.char == c {
63 *cursor = cursor.bump();
64 return true;
65 }
66 }
67 false
68}
69
70fn eat_subtree(cursor: &mut Cursor, kind: tt::DelimiterKind) -> bool {
71 if let Some(tt::buffer::TokenTreeRef::Subtree(subtree, _)) = cursor.token_tree() {
72 if Some(kind) == subtree.delimiter_kind() {
73 *cursor = cursor.bump_subtree();
74 return true;
75 }
76 }
77 false
78}
79
80fn eat_ident(cursor: &mut Cursor, t: &str) -> bool {
81 if let Some(tt::buffer::TokenTreeRef::Leaf(tt::Leaf::Ident(ident), _)) = cursor.token_tree() {
82 if t == ident.text.as_str() {
83 *cursor = cursor.bump();
84 return true;
85 }
86 }
87 false
88}
89
90fn remove_derive_attrs(tt: &tt::Subtree) -> Option<tt::Subtree> {
91 let buffer = TokenBuffer::from_tokens(&tt.token_trees);
92 let mut p = buffer.begin();
93 let mut result = tt::Subtree::default();
94
95 while !p.eof() {
96 let curr = p;
97
98 if eat_punct(&mut p, '#') {
99 eat_punct(&mut p, '!');
100 let parent = p;
101 if eat_subtree(&mut p, tt::DelimiterKind::Bracket) {
102 if eat_ident(&mut p, "derive") {
103 p = parent.bump();
104 continue;
105 }
106 }
107 }
108
109 result.token_trees.push(curr.token_tree()?.cloned());
110 p = curr.bump();
111 }
112
113 Some(result)
114}
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119 use test_utils::assert_eq_text;
120
121 #[test]
122 fn test_remove_derive_attrs() {
123 let tt = mbe::parse_to_token_tree(
124 r#"
125 #[allow(unused)]
126 #[derive(Copy)]
127 #[derive(Hello)]
128 struct A {
129 bar: u32
130 }
131"#,
132 )
133 .unwrap()
134 .0;
135 let result = format!("{:#?}", remove_derive_attrs(&tt).unwrap());
136
137 assert_eq_text!(
138 r#"
139SUBTREE $
140 PUNCH # [alone] 0
141 SUBTREE [] 1
142 IDENT allow 2
143 SUBTREE () 3
144 IDENT unused 4
145 IDENT struct 15
146 IDENT A 16
147 SUBTREE {} 17
148 IDENT bar 18
149 PUNCH : [alone] 19
150 IDENT u32 20
151"#
152 .trim(),
153 &result
154 );
155 }
156}
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs
index f8e9db9ae..71bc436e6 100644
--- a/crates/hir_ty/src/autoderef.rs
+++ b/crates/hir_ty/src/autoderef.rs
@@ -6,14 +6,15 @@
6use std::iter::successors; 6use std::iter::successors;
7 7
8use base_db::CrateId; 8use base_db::CrateId;
9use chalk_ir::cast::Cast; 9use chalk_ir::{cast::Cast, fold::Fold, interner::HasInterner, VariableKind};
10use hir_def::lang_item::LangItemTarget; 10use hir_def::lang_item::LangItemTarget;
11use hir_expand::name::name; 11use hir_expand::name::name;
12use log::{info, warn}; 12use log::{info, warn};
13 13
14use crate::{ 14use crate::{
15 db::HirDatabase, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, 15 db::HirDatabase, static_lifetime, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds,
16 InEnvironment, Interner, ProjectionTyExt, Solution, Ty, TyBuilder, TyKind, 16 DebruijnIndex, InEnvironment, Interner, ProjectionTyExt, Solution, Substitution, Ty, TyBuilder,
17 TyKind,
17}; 18};
18 19
19const AUTODEREF_RECURSION_LIMIT: usize = 10; 20const AUTODEREF_RECURSION_LIMIT: usize = 10;
@@ -103,7 +104,7 @@ fn deref_by_trait(
103 binders: CanonicalVarKinds::from_iter( 104 binders: CanonicalVarKinds::from_iter(
104 &Interner, 105 &Interner,
105 ty.goal.binders.iter(&Interner).cloned().chain(Some(chalk_ir::WithKind::new( 106 ty.goal.binders.iter(&Interner).cloned().chain(Some(chalk_ir::WithKind::new(
106 chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), 107 VariableKind::Ty(chalk_ir::TyVariableKind::General),
107 chalk_ir::UniverseIndex::ROOT, 108 chalk_ir::UniverseIndex::ROOT,
108 ))), 109 ))),
109 ), 110 ),
@@ -136,7 +137,9 @@ fn deref_by_trait(
136 return None; 137 return None;
137 } 138 }
138 } 139 }
139 Some(Canonical { 140 // FIXME: we remove lifetime variables here since they can confuse
141 // the method resolution code later
142 Some(fixup_lifetime_variables(Canonical {
140 value: vars 143 value: vars
141 .value 144 .value
142 .subst 145 .subst
@@ -144,7 +147,7 @@ fn deref_by_trait(
144 .assert_ty_ref(&Interner) 147 .assert_ty_ref(&Interner)
145 .clone(), 148 .clone(),
146 binders: vars.binders.clone(), 149 binders: vars.binders.clone(),
147 }) 150 }))
148 } 151 }
149 Solution::Ambig(_) => { 152 Solution::Ambig(_) => {
150 info!("Ambiguous solution for derefing {:?}: {:?}", ty.goal, solution); 153 info!("Ambiguous solution for derefing {:?}: {:?}", ty.goal, solution);
@@ -152,3 +155,32 @@ fn deref_by_trait(
152 } 155 }
153 } 156 }
154} 157}
158
159fn fixup_lifetime_variables<T: Fold<Interner, Result = T> + HasInterner<Interner = Interner>>(
160 c: Canonical<T>,
161) -> Canonical<T> {
162 // Removes lifetime variables from the Canonical, replacing them by static lifetimes.
163 let mut i = 0;
164 let subst = Substitution::from_iter(
165 &Interner,
166 c.binders.iter(&Interner).map(|vk| match vk.kind {
167 VariableKind::Ty(_) => {
168 let index = i;
169 i += 1;
170 BoundVar::new(DebruijnIndex::INNERMOST, index).to_ty(&Interner).cast(&Interner)
171 }
172 VariableKind::Lifetime => static_lifetime().cast(&Interner),
173 VariableKind::Const(_) => unimplemented!(),
174 }),
175 );
176 let binders = CanonicalVarKinds::from_iter(
177 &Interner,
178 c.binders.iter(&Interner).filter(|vk| match vk.kind {
179 VariableKind::Ty(_) => true,
180 VariableKind::Lifetime => false,
181 VariableKind::Const(_) => true,
182 }),
183 );
184 let value = subst.apply(c.value, &Interner);
185 Canonical { binders, value }
186}
diff --git a/crates/hir_ty/src/builder.rs b/crates/hir_ty/src/builder.rs
index 09512d1ce..e25ef866d 100644
--- a/crates/hir_ty/src/builder.rs
+++ b/crates/hir_ty/src/builder.rs
@@ -4,6 +4,7 @@ use std::iter;
4 4
5use chalk_ir::{ 5use chalk_ir::{
6 cast::{Cast, CastTo, Caster}, 6 cast::{Cast, CastTo, Caster},
7 fold::Fold,
7 interner::HasInterner, 8 interner::HasInterner,
8 AdtId, BoundVar, DebruijnIndex, Safety, Scalar, 9 AdtId, BoundVar, DebruijnIndex, Safety, Scalar,
9}; 10};
@@ -13,7 +14,7 @@ use smallvec::SmallVec;
13use crate::{ 14use crate::{
14 db::HirDatabase, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders, 15 db::HirDatabase, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders,
15 CallableSig, FnPointer, FnSig, FnSubst, GenericArg, Interner, ProjectionTy, Substitution, 16 CallableSig, FnPointer, FnSig, FnSubst, GenericArg, Interner, ProjectionTy, Substitution,
16 TraitRef, Ty, TyDefId, TyExt, TyKind, TypeWalk, ValueTyDefId, 17 TraitRef, Ty, TyDefId, TyExt, TyKind, ValueTyDefId,
17}; 18};
18 19
19/// This is a builder for `Ty` or anything that needs a `Substitution`. 20/// This is a builder for `Ty` or anything that needs a `Substitution`.
@@ -32,8 +33,7 @@ impl<D> TyBuilder<D> {
32 33
33 fn build_internal(self) -> (D, Substitution) { 34 fn build_internal(self) -> (D, Substitution) {
34 assert_eq!(self.vec.len(), self.param_count); 35 assert_eq!(self.vec.len(), self.param_count);
35 // FIXME: would be good to have a way to construct a chalk_ir::Substitution from the interned form 36 let subst = Substitution::from_iter(&Interner, self.vec);
36 let subst = Substitution::intern(self.vec);
37 (self.data, subst) 37 (self.data, subst)
38 } 38 }
39 39
@@ -141,7 +141,7 @@ impl TyBuilder<hir_def::AdtId> {
141 self.vec.push(fallback().cast(&Interner)); 141 self.vec.push(fallback().cast(&Interner));
142 } else { 142 } else {
143 // each default can depend on the previous parameters 143 // each default can depend on the previous parameters
144 let subst_so_far = Substitution::intern(self.vec.clone()); 144 let subst_so_far = Substitution::from_iter(&Interner, self.vec.clone());
145 self.vec 145 self.vec
146 .push(default_ty.clone().substitute(&Interner, &subst_so_far).cast(&Interner)); 146 .push(default_ty.clone().substitute(&Interner, &subst_so_far).cast(&Interner));
147 } 147 }
@@ -196,13 +196,13 @@ impl TyBuilder<TypeAliasId> {
196 } 196 }
197} 197}
198 198
199impl<T: TypeWalk + HasInterner<Interner = Interner>> TyBuilder<Binders<T>> { 199impl<T: HasInterner<Interner = Interner> + Fold<Interner>> TyBuilder<Binders<T>> {
200 fn subst_binders(b: Binders<T>) -> Self { 200 fn subst_binders(b: Binders<T>) -> Self {
201 let param_count = b.binders.len(&Interner); 201 let param_count = b.binders.len(&Interner);
202 TyBuilder::new(b, param_count) 202 TyBuilder::new(b, param_count)
203 } 203 }
204 204
205 pub fn build(self) -> T { 205 pub fn build(self) -> <T as Fold<Interner>>::Result {
206 let (b, subst) = self.build_internal(); 206 let (b, subst) = self.build_internal();
207 b.substitute(&Interner, &subst) 207 b.substitute(&Interner, &subst)
208 } 208 }
diff --git a/crates/hir_ty/src/chalk_cast.rs b/crates/hir_ty/src/chalk_cast.rs
deleted file mode 100644
index df6492113..000000000
--- a/crates/hir_ty/src/chalk_cast.rs
+++ /dev/null
@@ -1,73 +0,0 @@
1//! Implementations of the Chalk `Cast` trait for our types.
2
3use chalk_ir::{
4 cast::{Cast, CastTo},
5 interner::HasInterner,
6};
7
8use crate::{AliasEq, DomainGoal, GenericArg, GenericArgData, Interner, TraitRef, Ty, WhereClause};
9
10macro_rules! has_interner {
11 ($t:ty) => {
12 impl HasInterner for $t {
13 type Interner = crate::Interner;
14 }
15 };
16}
17
18has_interner!(WhereClause);
19has_interner!(DomainGoal);
20has_interner!(GenericArg);
21has_interner!(Ty);
22
23impl CastTo<WhereClause> for TraitRef {
24 fn cast_to(self, _interner: &Interner) -> WhereClause {
25 WhereClause::Implemented(self)
26 }
27}
28
29impl CastTo<WhereClause> for AliasEq {
30 fn cast_to(self, _interner: &Interner) -> WhereClause {
31 WhereClause::AliasEq(self)
32 }
33}
34
35impl CastTo<DomainGoal> for WhereClause {
36 fn cast_to(self, _interner: &Interner) -> DomainGoal {
37 DomainGoal::Holds(self)
38 }
39}
40
41impl CastTo<GenericArg> for Ty {
42 fn cast_to(self, interner: &Interner) -> GenericArg {
43 GenericArg::new(interner, GenericArgData::Ty(self))
44 }
45}
46
47macro_rules! transitive_impl {
48 ($a:ty, $b:ty, $c:ty) => {
49 impl CastTo<$c> for $a {
50 fn cast_to(self, interner: &Interner) -> $c {
51 self.cast::<$b>(interner).cast(interner)
52 }
53 }
54 };
55}
56
57// In Chalk, these can be done as blanket impls, but that doesn't work here
58// because of coherence
59
60transitive_impl!(TraitRef, WhereClause, DomainGoal);
61transitive_impl!(AliasEq, WhereClause, DomainGoal);
62
63macro_rules! reflexive_impl {
64 ($a:ty) => {
65 impl CastTo<$a> for $a {
66 fn cast_to(self, _interner: &Interner) -> $a {
67 self
68 }
69 }
70 };
71}
72
73reflexive_impl!(GenericArg);
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/chalk_db.rs
index 090f6492b..8f054d06b 100644
--- a/crates/hir_ty/src/traits/chalk.rs
+++ b/crates/hir_ty/src/chalk_db.rs
@@ -1,52 +1,47 @@
1//! Conversion code from/to Chalk. 1//! The implementation of `RustIrDatabase` for Chalk, which provides information
2//! about the code that Chalk needs.
2use std::sync::Arc; 3use std::sync::Arc;
3 4
4use log::debug; 5use log::debug;
5 6
6use chalk_ir::{fold::shift::Shift, CanonicalVarKinds}; 7use chalk_ir::{cast::Cast, fold::shift::Shift, CanonicalVarKinds};
7use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait}; 8use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait};
8 9
9use base_db::{salsa::InternKey, CrateId}; 10use base_db::CrateId;
10use hir_def::{ 11use hir_def::{
11 lang_item::{lang_attr, LangItemTarget}, 12 lang_item::{lang_attr, LangItemTarget},
12 AssocContainerId, AssocItemId, HasModule, Lookup, TypeAliasId, 13 AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId,
13}; 14};
14use hir_expand::name::name; 15use hir_expand::name::name;
15 16
16use super::ChalkContext;
17use crate::{ 17use crate::{
18 db::HirDatabase, 18 db::HirDatabase,
19 display::HirDisplay, 19 display::HirDisplay,
20 from_assoc_type_id, 20 from_assoc_type_id, from_chalk_trait_id, make_only_type_binders,
21 mapping::{from_chalk, ToChalk, TypeAliasAsValue},
21 method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, 22 method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
22 to_assoc_type_id, to_chalk_trait_id, 23 to_assoc_type_id, to_chalk_trait_id,
24 traits::ChalkContext,
23 utils::generics, 25 utils::generics,
24 AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, ProjectionTy, Substitution, 26 AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, Interner, ProjectionTy,
25 TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, WhereClause, 27 ProjectionTyExt, QuantifiedWhereClause, Substitution, TraitRef, TraitRefExt, Ty, TyBuilder,
28 TyExt, TyKind, WhereClause,
26}; 29};
27use mapping::{
28 convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue,
29};
30
31pub use self::interner::Interner;
32pub(crate) use self::interner::*;
33
34pub(super) mod tls;
35mod interner;
36mod mapping;
37
38pub(crate) trait ToChalk {
39 type Chalk;
40 fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk;
41 fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self;
42}
43 30
44pub(crate) fn from_chalk<T, ChalkT>(db: &dyn HirDatabase, chalk: ChalkT) -> T 31pub(crate) type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>;
45where 32pub(crate) type TraitDatum = chalk_solve::rust_ir::TraitDatum<Interner>;
46 T: ToChalk<Chalk = ChalkT>, 33pub(crate) type StructDatum = chalk_solve::rust_ir::AdtDatum<Interner>;
47{ 34pub(crate) type ImplDatum = chalk_solve::rust_ir::ImplDatum<Interner>;
48 T::from_chalk(db, chalk) 35pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum<Interner>;
49} 36
37pub(crate) type AssocTypeId = chalk_ir::AssocTypeId<Interner>;
38pub(crate) type TraitId = chalk_ir::TraitId<Interner>;
39pub(crate) type AdtId = chalk_ir::AdtId<Interner>;
40pub(crate) type ImplId = chalk_ir::ImplId<Interner>;
41pub(crate) type AssociatedTyValueId = chalk_solve::rust_ir::AssociatedTyValueId<Interner>;
42pub(crate) type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue<Interner>;
43pub(crate) type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>;
44pub(crate) type Variances = chalk_ir::Variances<Interner>;
50 45
51impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { 46impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
52 fn associated_ty_data(&self, id: AssocTypeId) -> Arc<AssociatedTyDatum> { 47 fn associated_ty_data(&self, id: AssocTypeId) -> Arc<AssociatedTyDatum> {
@@ -84,9 +79,9 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
84 binders: &CanonicalVarKinds<Interner>, 79 binders: &CanonicalVarKinds<Interner>,
85 ) -> Vec<ImplId> { 80 ) -> Vec<ImplId> {
86 debug!("impls_for_trait {:?}", trait_id); 81 debug!("impls_for_trait {:?}", trait_id);
87 let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); 82 let trait_: hir_def::TraitId = from_chalk_trait_id(trait_id);
88 83
89 let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref(&Interner).clone()); 84 let ty: Ty = parameters[0].assert_ty_ref(&Interner).clone();
90 85
91 fn binder_kind( 86 fn binder_kind(
92 ty: &Ty, 87 ty: &Ty,
@@ -103,7 +98,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
103 None 98 None
104 } 99 }
105 100
106 let self_ty_fp = TyFingerprint::for_impl(&ty); 101 let self_ty_fp = TyFingerprint::for_trait_impl(&ty);
107 let fps: &[TyFingerprint] = match binder_kind(&ty, binders) { 102 let fps: &[TyFingerprint] = match binder_kind(&ty, binders) {
108 Some(chalk_ir::TyVariableKind::Integer) => &ALL_INT_FPS, 103 Some(chalk_ir::TyVariableKind::Integer) => &ALL_INT_FPS,
109 Some(chalk_ir::TyVariableKind::Float) => &ALL_FLOAT_FPS, 104 Some(chalk_ir::TyVariableKind::Float) => &ALL_FLOAT_FPS,
@@ -166,7 +161,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
166 Some(LangItemTarget::TraitId(trait_)) => trait_, 161 Some(LangItemTarget::TraitId(trait_)) => trait_,
167 _ => return None, 162 _ => return None,
168 }; 163 };
169 Some(trait_.to_chalk(self.db)) 164 Some(to_chalk_trait_id(trait_))
170 } 165 }
171 166
172 fn program_clauses_for_env( 167 fn program_clauses_for_env(
@@ -187,16 +182,11 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
187 let (datas, binders) = (*datas).as_ref().into_value_and_skipped_binders(); 182 let (datas, binders) = (*datas).as_ref().into_value_and_skipped_binders();
188 let data = &datas.impl_traits[idx as usize]; 183 let data = &datas.impl_traits[idx as usize];
189 let bound = OpaqueTyDatumBound { 184 let bound = OpaqueTyDatumBound {
190 bounds: make_binders( 185 bounds: make_only_type_binders(
191 data.bounds
192 .skip_binders()
193 .iter()
194 .cloned()
195 .map(|b| b.to_chalk(self.db))
196 .collect(),
197 1, 186 1,
187 data.bounds.skip_binders().iter().cloned().collect(),
198 ), 188 ),
199 where_clauses: make_binders(vec![], 0), 189 where_clauses: make_only_type_binders(0, vec![]),
200 }; 190 };
201 chalk_ir::Binders::new(binders, bound) 191 chalk_ir::Binders::new(binders, bound)
202 } 192 }
@@ -244,25 +234,25 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
244 .intern(&Interner), 234 .intern(&Interner),
245 }); 235 });
246 let bound = OpaqueTyDatumBound { 236 let bound = OpaqueTyDatumBound {
247 bounds: make_binders( 237 bounds: make_only_type_binders(
238 1,
248 vec![ 239 vec![
249 crate::wrap_empty_binders(impl_bound).to_chalk(self.db), 240 crate::wrap_empty_binders(impl_bound),
250 crate::wrap_empty_binders(proj_bound).to_chalk(self.db), 241 crate::wrap_empty_binders(proj_bound),
251 ], 242 ],
252 1,
253 ), 243 ),
254 where_clauses: make_binders(vec![], 0), 244 where_clauses: make_only_type_binders(0, vec![]),
255 }; 245 };
256 // The opaque type has 1 parameter. 246 // The opaque type has 1 parameter.
257 make_binders(bound, 1) 247 make_only_type_binders(1, bound)
258 } else { 248 } else {
259 // If failed to find Symbol’s value as variable is void: Future::Output, return empty bounds as fallback. 249 // If failed to find Symbol’s value as variable is void: Future::Output, return empty bounds as fallback.
260 let bound = OpaqueTyDatumBound { 250 let bound = OpaqueTyDatumBound {
261 bounds: make_binders(vec![], 0), 251 bounds: make_only_type_binders(0, vec![]),
262 where_clauses: make_binders(vec![], 0), 252 where_clauses: make_only_type_binders(0, vec![]),
263 }; 253 };
264 // The opaque type has 1 parameter. 254 // The opaque type has 1 parameter.
265 make_binders(bound, 1) 255 make_only_type_binders(1, bound)
266 } 256 }
267 } 257 }
268 }; 258 };
@@ -272,7 +262,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
272 262
273 fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId<Interner>) -> chalk_ir::Ty<Interner> { 263 fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId<Interner>) -> chalk_ir::Ty<Interner> {
274 // FIXME: actually provide the hidden type; it is relevant for auto traits 264 // FIXME: actually provide the hidden type; it is relevant for auto traits
275 TyKind::Error.intern(&Interner).to_chalk(self.db) 265 TyKind::Error.intern(&Interner)
276 } 266 }
277 267
278 fn is_object_safe(&self, _trait_id: chalk_ir::TraitId<Interner>) -> bool { 268 fn is_object_safe(&self, _trait_id: chalk_ir::TraitId<Interner>) -> bool {
@@ -293,33 +283,32 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
293 _closure_id: chalk_ir::ClosureId<Interner>, 283 _closure_id: chalk_ir::ClosureId<Interner>,
294 substs: &chalk_ir::Substitution<Interner>, 284 substs: &chalk_ir::Substitution<Interner>,
295 ) -> chalk_ir::Binders<rust_ir::FnDefInputsAndOutputDatum<Interner>> { 285 ) -> chalk_ir::Binders<rust_ir::FnDefInputsAndOutputDatum<Interner>> {
296 let sig_ty: Ty = 286 let sig_ty = substs.at(&Interner, 0).assert_ty_ref(&Interner).clone();
297 from_chalk(self.db, substs.at(&Interner, 0).assert_ty_ref(&Interner).clone());
298 let sig = &sig_ty.callable_sig(self.db).expect("first closure param should be fn ptr"); 287 let sig = &sig_ty.callable_sig(self.db).expect("first closure param should be fn ptr");
299 let io = rust_ir::FnDefInputsAndOutputDatum { 288 let io = rust_ir::FnDefInputsAndOutputDatum {
300 argument_types: sig.params().iter().map(|ty| ty.clone().to_chalk(self.db)).collect(), 289 argument_types: sig.params().iter().cloned().collect(),
301 return_type: sig.ret().clone().to_chalk(self.db), 290 return_type: sig.ret().clone(),
302 }; 291 };
303 make_binders(io.shifted_in(&Interner), 0) 292 make_only_type_binders(0, io.shifted_in(&Interner))
304 } 293 }
305 fn closure_upvars( 294 fn closure_upvars(
306 &self, 295 &self,
307 _closure_id: chalk_ir::ClosureId<Interner>, 296 _closure_id: chalk_ir::ClosureId<Interner>,
308 _substs: &chalk_ir::Substitution<Interner>, 297 _substs: &chalk_ir::Substitution<Interner>,
309 ) -> chalk_ir::Binders<chalk_ir::Ty<Interner>> { 298 ) -> chalk_ir::Binders<chalk_ir::Ty<Interner>> {
310 let ty = TyBuilder::unit().to_chalk(self.db); 299 let ty = TyBuilder::unit();
311 make_binders(ty, 0) 300 make_only_type_binders(0, ty)
312 } 301 }
313 fn closure_fn_substitution( 302 fn closure_fn_substitution(
314 &self, 303 &self,
315 _closure_id: chalk_ir::ClosureId<Interner>, 304 _closure_id: chalk_ir::ClosureId<Interner>,
316 _substs: &chalk_ir::Substitution<Interner>, 305 _substs: &chalk_ir::Substitution<Interner>,
317 ) -> chalk_ir::Substitution<Interner> { 306 ) -> chalk_ir::Substitution<Interner> {
318 Substitution::empty(&Interner).to_chalk(self.db) 307 Substitution::empty(&Interner)
319 } 308 }
320 309
321 fn trait_name(&self, trait_id: chalk_ir::TraitId<Interner>) -> String { 310 fn trait_name(&self, trait_id: chalk_ir::TraitId<Interner>) -> String {
322 let id = from_chalk(self.db, trait_id); 311 let id = from_chalk_trait_id(trait_id);
323 self.db.trait_data(id).name.to_string() 312 self.db.trait_data(id).name.to_string()
324 } 313 }
325 fn adt_name(&self, chalk_ir::AdtId(adt_id): AdtId) -> String { 314 fn adt_name(&self, chalk_ir::AdtId(adt_id): AdtId) -> String {
@@ -410,10 +399,10 @@ pub(crate) fn associated_ty_data_query(
410 let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars); 399 let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars);
411 let bound_data = rust_ir::AssociatedTyDatumBound { bounds, where_clauses }; 400 let bound_data = rust_ir::AssociatedTyDatumBound { bounds, where_clauses };
412 let datum = AssociatedTyDatum { 401 let datum = AssociatedTyDatum {
413 trait_id: trait_.to_chalk(db), 402 trait_id: to_chalk_trait_id(trait_),
414 id, 403 id,
415 name: type_alias, 404 name: type_alias,
416 binders: make_binders(bound_data, generic_params.len()), 405 binders: make_only_type_binders(generic_params.len(), bound_data),
417 }; 406 };
418 Arc::new(datum) 407 Arc::new(datum)
419} 408}
@@ -424,7 +413,7 @@ pub(crate) fn trait_datum_query(
424 trait_id: TraitId, 413 trait_id: TraitId,
425) -> Arc<TraitDatum> { 414) -> Arc<TraitDatum> {
426 debug!("trait_datum {:?}", trait_id); 415 debug!("trait_datum {:?}", trait_id);
427 let trait_: hir_def::TraitId = from_chalk(db, trait_id); 416 let trait_ = from_chalk_trait_id(trait_id);
428 let trait_data = db.trait_data(trait_); 417 let trait_data = db.trait_data(trait_);
429 debug!("trait {:?} = {:?}", trait_id, trait_data.name); 418 debug!("trait {:?} = {:?}", trait_id, trait_data.name);
430 let generic_params = generics(db.upcast(), trait_.into()); 419 let generic_params = generics(db.upcast(), trait_.into());
@@ -446,7 +435,7 @@ pub(crate) fn trait_datum_query(
446 lang_attr(db.upcast(), trait_).and_then(|name| well_known_trait_from_lang_attr(&name)); 435 lang_attr(db.upcast(), trait_).and_then(|name| well_known_trait_from_lang_attr(&name));
447 let trait_datum = TraitDatum { 436 let trait_datum = TraitDatum {
448 id: trait_id, 437 id: trait_id,
449 binders: make_binders(trait_datum_bound, bound_vars.len(&Interner)), 438 binders: make_only_type_binders(bound_vars.len(&Interner), trait_datum_bound),
450 flags, 439 flags,
451 associated_ty_ids, 440 associated_ty_ids,
452 well_known, 441 well_known,
@@ -515,7 +504,7 @@ pub(crate) fn struct_datum_query(
515 // FIXME set ADT kind 504 // FIXME set ADT kind
516 kind: rust_ir::AdtKind::Struct, 505 kind: rust_ir::AdtKind::Struct,
517 id: struct_id, 506 id: struct_id,
518 binders: make_binders(struct_datum_bound, num_params), 507 binders: make_only_type_binders(num_params, struct_datum_bound),
519 flags, 508 flags,
520 }; 509 };
521 Arc::new(struct_datum) 510 Arc::new(struct_datum)
@@ -563,7 +552,6 @@ fn impl_def_datum(
563 trait_ref.display(db), 552 trait_ref.display(db),
564 where_clauses 553 where_clauses
565 ); 554 );
566 let trait_ref = trait_ref.to_chalk(db);
567 555
568 let polarity = if negative { rust_ir::Polarity::Negative } else { rust_ir::Polarity::Positive }; 556 let polarity = if negative { rust_ir::Polarity::Negative } else { rust_ir::Polarity::Positive };
569 557
@@ -585,7 +573,7 @@ fn impl_def_datum(
585 .collect(); 573 .collect();
586 debug!("impl_datum: {:?}", impl_datum_bound); 574 debug!("impl_datum: {:?}", impl_datum_bound);
587 let impl_datum = ImplDatum { 575 let impl_datum = ImplDatum {
588 binders: make_binders(impl_datum_bound, bound_vars.len(&Interner)), 576 binders: make_only_type_binders(bound_vars.len(&Interner), impl_datum_bound),
589 impl_type, 577 impl_type,
590 polarity, 578 polarity,
591 associated_ty_value_ids, 579 associated_ty_value_ids,
@@ -624,7 +612,7 @@ fn type_alias_associated_ty_value(
624 .associated_type_by_name(&type_alias_data.name) 612 .associated_type_by_name(&type_alias_data.name)
625 .expect("assoc ty value should not exist"); // validated when building the impl data as well 613 .expect("assoc ty value should not exist"); // validated when building the impl data as well
626 let (ty, binders) = db.ty(type_alias.into()).into_value_and_skipped_binders(); 614 let (ty, binders) = db.ty(type_alias.into()).into_value_and_skipped_binders();
627 let value_bound = rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) }; 615 let value_bound = rust_ir::AssociatedTyValueBound { ty };
628 let value = rust_ir::AssociatedTyValue { 616 let value = rust_ir::AssociatedTyValue {
629 impl_id: impl_id.to_chalk(db), 617 impl_id: impl_id.to_chalk(db),
630 associated_ty_id: to_assoc_type_id(assoc_ty), 618 associated_ty_id: to_assoc_type_id(assoc_ty),
@@ -645,13 +633,13 @@ pub(crate) fn fn_def_datum_query(
645 let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars); 633 let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars);
646 let bound = rust_ir::FnDefDatumBound { 634 let bound = rust_ir::FnDefDatumBound {
647 // Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway 635 // Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway
648 inputs_and_output: make_binders( 636 inputs_and_output: make_only_type_binders(
637 0,
649 rust_ir::FnDefInputsAndOutputDatum { 638 rust_ir::FnDefInputsAndOutputDatum {
650 argument_types: sig.params().iter().map(|ty| ty.clone().to_chalk(db)).collect(), 639 argument_types: sig.params().iter().cloned().collect(),
651 return_type: sig.ret().clone().to_chalk(db), 640 return_type: sig.ret().clone(),
652 } 641 }
653 .shifted_in(&Interner), 642 .shifted_in(&Interner),
654 0,
655 ), 643 ),
656 where_clauses, 644 where_clauses,
657 }; 645 };
@@ -688,38 +676,65 @@ pub(crate) fn adt_variance_query(
688 ) 676 )
689} 677}
690 678
691impl From<FnDefId> for crate::db::InternedCallableDefId { 679pub(super) fn convert_where_clauses(
692 fn from(fn_def_id: FnDefId) -> Self { 680 db: &dyn HirDatabase,
693 InternKey::from_intern_id(fn_def_id.0) 681 def: GenericDefId,
694 } 682 substs: &Substitution,
695} 683) -> Vec<chalk_ir::QuantifiedWhereClause<Interner>> {
696 684 let generic_predicates = db.generic_predicates(def);
697impl From<crate::db::InternedCallableDefId> for FnDefId { 685 let mut result = Vec::with_capacity(generic_predicates.len());
698 fn from(callable_def_id: crate::db::InternedCallableDefId) -> Self { 686 for pred in generic_predicates.iter() {
699 chalk_ir::FnDefId(callable_def_id.as_intern_id()) 687 result.push(pred.clone().substitute(&Interner, substs));
700 } 688 }
701} 689 result
702
703impl From<OpaqueTyId> for crate::db::InternedOpaqueTyId {
704 fn from(id: OpaqueTyId) -> Self {
705 InternKey::from_intern_id(id.0)
706 }
707}
708
709impl From<crate::db::InternedOpaqueTyId> for OpaqueTyId {
710 fn from(id: crate::db::InternedOpaqueTyId) -> Self {
711 chalk_ir::OpaqueTyId(id.as_intern_id())
712 }
713}
714
715impl From<chalk_ir::ClosureId<Interner>> for crate::db::InternedClosureId {
716 fn from(id: chalk_ir::ClosureId<Interner>) -> Self {
717 Self::from_intern_id(id.0)
718 }
719} 690}
720 691
721impl From<crate::db::InternedClosureId> for chalk_ir::ClosureId<Interner> { 692pub(super) fn generic_predicate_to_inline_bound(
722 fn from(id: crate::db::InternedClosureId) -> Self { 693 db: &dyn HirDatabase,
723 chalk_ir::ClosureId(id.as_intern_id()) 694 pred: &QuantifiedWhereClause,
695 self_ty: &Ty,
696) -> Option<chalk_ir::Binders<rust_ir::InlineBound<Interner>>> {
697 // An InlineBound is like a GenericPredicate, except the self type is left out.
698 // We don't have a special type for this, but Chalk does.
699 let self_ty_shifted_in = self_ty.clone().shifted_in_from(&Interner, DebruijnIndex::ONE);
700 let (pred, binders) = pred.as_ref().into_value_and_skipped_binders();
701 match pred {
702 WhereClause::Implemented(trait_ref) => {
703 if trait_ref.self_type_parameter(&Interner) != self_ty_shifted_in {
704 // we can only convert predicates back to type bounds if they
705 // have the expected self type
706 return None;
707 }
708 let args_no_self = trait_ref.substitution.as_slice(&Interner)[1..]
709 .iter()
710 .map(|ty| ty.clone().cast(&Interner))
711 .collect();
712 let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self };
713 Some(chalk_ir::Binders::new(binders, rust_ir::InlineBound::TraitBound(trait_bound)))
714 }
715 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
716 if projection_ty.self_type_parameter(&Interner) != self_ty_shifted_in {
717 return None;
718 }
719 let trait_ = projection_ty.trait_(db);
720 let args_no_self = projection_ty.substitution.as_slice(&Interner)[1..]
721 .iter()
722 .map(|ty| ty.clone().cast(&Interner))
723 .collect();
724 let alias_eq_bound = rust_ir::AliasEqBound {
725 value: ty.clone(),
726 trait_bound: rust_ir::TraitBound {
727 trait_id: to_chalk_trait_id(trait_),
728 args_no_self,
729 },
730 associated_ty_id: projection_ty.associated_ty_id,
731 parameters: Vec::new(), // FIXME we don't support generic associated types yet
732 };
733 Some(chalk_ir::Binders::new(
734 binders,
735 rust_ir::InlineBound::AliasEqBound(alias_eq_bound),
736 ))
737 }
738 _ => None,
724 } 739 }
725} 740}
diff --git a/crates/hir_ty/src/chalk_ext.rs b/crates/hir_ty/src/chalk_ext.rs
index 28ed3aac6..8c4542956 100644
--- a/crates/hir_ty/src/chalk_ext.rs
+++ b/crates/hir_ty/src/chalk_ext.rs
@@ -75,7 +75,7 @@ impl TyExt for Ty {
75 } 75 }
76 fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)> { 76 fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)> {
77 match self.kind(&Interner) { 77 match self.kind(&Interner) {
78 TyKind::Ref(mutability, lifetime, ty) => Some((ty, *lifetime, *mutability)), 78 TyKind::Ref(mutability, lifetime, ty) => Some((ty, lifetime.clone(), *mutability)),
79 _ => None, 79 _ => None,
80 } 80 }
81 } 81 }
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs
index 326c20240..1690926ad 100644
--- a/crates/hir_ty/src/db.rs
+++ b/crates/hir_ty/src/db.rs
@@ -1,4 +1,5 @@
1//! FIXME: write short doc here 1//! The home of `HirDatabase`, which is the Salsa database containing all the
2//! type inference-related queries.
2 3
3use std::sync::Arc; 4use std::sync::Arc;
4 5
@@ -10,9 +11,9 @@ use hir_def::{
10use la_arena::ArenaMap; 11use la_arena::ArenaMap;
11 12
12use crate::{ 13use crate::{
14 chalk_db,
13 method_resolution::{InherentImpls, TraitImpls}, 15 method_resolution::{InherentImpls, TraitImpls},
14 traits::chalk, 16 Binders, CallableDefId, FnDefId, ImplTraitId, InferenceResult, Interner, PolyFnSig,
15 Binders, CallableDefId, FnDefId, ImplTraitId, InferenceResult, PolyFnSig,
16 QuantifiedWhereClause, ReturnTypeImplTraits, TraitRef, Ty, TyDefId, ValueTyDefId, 17 QuantifiedWhereClause, ReturnTypeImplTraits, TraitRef, Ty, TyDefId, ValueTyDefId,
17}; 18};
18use hir_expand::name::Name; 19use hir_expand::name::Name;
@@ -94,33 +95,38 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
94 #[salsa::interned] 95 #[salsa::interned]
95 fn intern_closure(&self, id: (DefWithBodyId, ExprId)) -> InternedClosureId; 96 fn intern_closure(&self, id: (DefWithBodyId, ExprId)) -> InternedClosureId;
96 97
97 #[salsa::invoke(chalk::associated_ty_data_query)] 98 #[salsa::invoke(chalk_db::associated_ty_data_query)]
98 fn associated_ty_data(&self, id: chalk::AssocTypeId) -> Arc<chalk::AssociatedTyDatum>; 99 fn associated_ty_data(&self, id: chalk_db::AssocTypeId) -> Arc<chalk_db::AssociatedTyDatum>;
99 100
100 #[salsa::invoke(chalk::trait_datum_query)] 101 #[salsa::invoke(chalk_db::trait_datum_query)]
101 fn trait_datum(&self, krate: CrateId, trait_id: chalk::TraitId) -> Arc<chalk::TraitDatum>; 102 fn trait_datum(&self, krate: CrateId, trait_id: chalk_db::TraitId)
103 -> Arc<chalk_db::TraitDatum>;
102 104
103 #[salsa::invoke(chalk::struct_datum_query)] 105 #[salsa::invoke(chalk_db::struct_datum_query)]
104 fn struct_datum(&self, krate: CrateId, struct_id: chalk::AdtId) -> Arc<chalk::StructDatum>; 106 fn struct_datum(
107 &self,
108 krate: CrateId,
109 struct_id: chalk_db::AdtId,
110 ) -> Arc<chalk_db::StructDatum>;
105 111
106 #[salsa::invoke(crate::traits::chalk::impl_datum_query)] 112 #[salsa::invoke(chalk_db::impl_datum_query)]
107 fn impl_datum(&self, krate: CrateId, impl_id: chalk::ImplId) -> Arc<chalk::ImplDatum>; 113 fn impl_datum(&self, krate: CrateId, impl_id: chalk_db::ImplId) -> Arc<chalk_db::ImplDatum>;
108 114
109 #[salsa::invoke(crate::traits::chalk::fn_def_datum_query)] 115 #[salsa::invoke(chalk_db::fn_def_datum_query)]
110 fn fn_def_datum(&self, krate: CrateId, fn_def_id: FnDefId) -> Arc<chalk::FnDefDatum>; 116 fn fn_def_datum(&self, krate: CrateId, fn_def_id: FnDefId) -> Arc<chalk_db::FnDefDatum>;
111 117
112 #[salsa::invoke(crate::traits::chalk::fn_def_variance_query)] 118 #[salsa::invoke(chalk_db::fn_def_variance_query)]
113 fn fn_def_variance(&self, krate: CrateId, fn_def_id: FnDefId) -> chalk::Variances; 119 fn fn_def_variance(&self, krate: CrateId, fn_def_id: FnDefId) -> chalk_db::Variances;
114 120
115 #[salsa::invoke(crate::traits::chalk::adt_variance_query)] 121 #[salsa::invoke(chalk_db::adt_variance_query)]
116 fn adt_variance(&self, krate: CrateId, adt_id: chalk::AdtId) -> chalk::Variances; 122 fn adt_variance(&self, krate: CrateId, adt_id: chalk_db::AdtId) -> chalk_db::Variances;
117 123
118 #[salsa::invoke(crate::traits::chalk::associated_ty_value_query)] 124 #[salsa::invoke(chalk_db::associated_ty_value_query)]
119 fn associated_ty_value( 125 fn associated_ty_value(
120 &self, 126 &self,
121 krate: CrateId, 127 krate: CrateId,
122 id: chalk::AssociatedTyValueId, 128 id: chalk_db::AssociatedTyValueId,
123 ) -> Arc<chalk::AssociatedTyValue>; 129 ) -> Arc<chalk_db::AssociatedTyValue>;
124 130
125 #[salsa::invoke(crate::traits::trait_solve_query)] 131 #[salsa::invoke(crate::traits::trait_solve_query)]
126 fn trait_solve( 132 fn trait_solve(
@@ -129,12 +135,12 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
129 goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>, 135 goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>,
130 ) -> Option<crate::Solution>; 136 ) -> Option<crate::Solution>;
131 137
132 #[salsa::invoke(crate::traits::chalk::program_clauses_for_chalk_env_query)] 138 #[salsa::invoke(chalk_db::program_clauses_for_chalk_env_query)]
133 fn program_clauses_for_chalk_env( 139 fn program_clauses_for_chalk_env(
134 &self, 140 &self,
135 krate: CrateId, 141 krate: CrateId,
136 env: chalk_ir::Environment<chalk::Interner>, 142 env: chalk_ir::Environment<Interner>,
137 ) -> chalk_ir::ProgramClauses<chalk::Interner>; 143 ) -> chalk_ir::ProgramClauses<Interner>;
138} 144}
139 145
140fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> { 146fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> {
diff --git a/crates/hir_ty/src/diagnostics.rs b/crates/hir_ty/src/diagnostics.rs
index 86f937e1d..84fc8ce14 100644
--- a/crates/hir_ty/src/diagnostics.rs
+++ b/crates/hir_ty/src/diagnostics.rs
@@ -1,4 +1,4 @@
1//! FIXME: write short doc here 1//! Type inference-based diagnostics.
2mod expr; 2mod expr;
3mod match_check; 3mod match_check;
4mod unsafe_check; 4mod unsafe_check;
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index e0ca96c6d..e7c9dabc2 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -1,4 +1,6 @@
1//! FIXME: write short doc here 1//! The `HirDisplay` trait, which serves two purposes: Turning various bits from
2//! HIR back into source code, and just displaying them for debugging/testing
3//! purposes.
2 4
3use std::{ 5use std::{
4 array, 6 array,
@@ -20,11 +22,11 @@ use hir_expand::name::Name;
20 22
21use crate::{ 23use crate::{
22 const_from_placeholder_idx, db::HirDatabase, from_assoc_type_id, from_foreign_def_id, 24 const_from_placeholder_idx, db::HirDatabase, from_assoc_type_id, from_foreign_def_id,
23 from_placeholder_idx, lt_from_placeholder_idx, primitive, subst_prefix, to_assoc_type_id, 25 from_placeholder_idx, lt_from_placeholder_idx, mapping::from_chalk, primitive, subst_prefix,
24 traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, CallableDefId, 26 to_assoc_type_id, utils::generics, AdtId, AliasEq, AliasTy, CallableDefId, CallableSig, Const,
25 CallableSig, Const, ConstValue, DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, 27 ConstValue, DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, LifetimeData,
26 LifetimeData, LifetimeOutlives, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt, 28 LifetimeOutlives, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause,
27 QuantifiedWhereClause, Scalar, TraitRef, TraitRefExt, Ty, TyExt, TyKind, WhereClause, 29 Scalar, TraitRef, TraitRefExt, Ty, TyExt, TyKind, WhereClause,
28}; 30};
29 31
30pub struct HirFormatter<'a> { 32pub struct HirFormatter<'a> {
@@ -265,7 +267,7 @@ impl HirDisplay for ProjectionTy {
265 write!(f, " as {}", trait_.name)?; 267 write!(f, " as {}", trait_.name)?;
266 if self.substitution.len(&Interner) > 1 { 268 if self.substitution.len(&Interner) > 1 {
267 write!(f, "<")?; 269 write!(f, "<")?;
268 f.write_joined(&self.substitution.interned()[1..], ", ")?; 270 f.write_joined(&self.substitution.as_slice(&Interner)[1..], ", ")?;
269 write!(f, ">")?; 271 write!(f, ">")?;
270 } 272 }
271 write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?; 273 write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?;
@@ -287,6 +289,8 @@ impl HirDisplay for GenericArg {
287 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 289 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
288 match self.interned() { 290 match self.interned() {
289 crate::GenericArgData::Ty(ty) => ty.hir_fmt(f), 291 crate::GenericArgData::Ty(ty) => ty.hir_fmt(f),
292 crate::GenericArgData::Lifetime(lt) => lt.hir_fmt(f),
293 crate::GenericArgData::Const(c) => c.hir_fmt(f),
290 } 294 }
291 } 295 }
292} 296}
@@ -414,7 +418,7 @@ impl HirDisplay for Ty {
414 write!(f, ",)")?; 418 write!(f, ",)")?;
415 } else { 419 } else {
416 write!(f, "(")?; 420 write!(f, "(")?;
417 f.write_joined(&*substs.interned(), ", ")?; 421 f.write_joined(&*substs.as_slice(&Interner), ", ")?;
418 write!(f, ")")?; 422 write!(f, ")")?;
419 } 423 }
420 } 424 }
@@ -442,7 +446,7 @@ impl HirDisplay for Ty {
442 // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self? 446 // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
443 if total_len > 0 { 447 if total_len > 0 {
444 write!(f, "<")?; 448 write!(f, "<")?;
445 f.write_joined(&parameters.interned()[..total_len], ", ")?; 449 f.write_joined(&parameters.as_slice(&Interner)[..total_len], ", ")?;
446 write!(f, ">")?; 450 write!(f, ">")?;
447 } 451 }
448 } 452 }
@@ -489,7 +493,7 @@ impl HirDisplay for Ty {
489 .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) 493 .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
490 .filter(|defaults| !defaults.is_empty()) 494 .filter(|defaults| !defaults.is_empty())
491 { 495 {
492 None => parameters.interned().as_ref(), 496 None => parameters.as_slice(&Interner),
493 Some(default_parameters) => { 497 Some(default_parameters) => {
494 let mut default_from = 0; 498 let mut default_from = 0;
495 for (i, parameter) in parameters.iter(&Interner).enumerate() { 499 for (i, parameter) in parameters.iter(&Interner).enumerate() {
@@ -513,11 +517,11 @@ impl HirDisplay for Ty {
513 } 517 }
514 } 518 }
515 } 519 }
516 &parameters.interned()[0..default_from] 520 &parameters.as_slice(&Interner)[0..default_from]
517 } 521 }
518 } 522 }
519 } else { 523 } else {
520 parameters.interned().as_ref() 524 parameters.as_slice(&Interner)
521 }; 525 };
522 if !parameters_to_write.is_empty() { 526 if !parameters_to_write.is_empty() {
523 write!(f, "<")?; 527 write!(f, "<")?;
@@ -540,7 +544,7 @@ impl HirDisplay for Ty {
540 write!(f, "{}::{}", trait_.name, type_alias_data.name)?; 544 write!(f, "{}::{}", trait_.name, type_alias_data.name)?;
541 if parameters.len(&Interner) > 0 { 545 if parameters.len(&Interner) > 0 {
542 write!(f, "<")?; 546 write!(f, "<")?;
543 f.write_joined(&*parameters.interned(), ", ")?; 547 f.write_joined(&*parameters.as_slice(&Interner), ", ")?;
544 write!(f, ">")?; 548 write!(f, ">")?;
545 } 549 }
546 } else { 550 } else {
@@ -664,6 +668,8 @@ impl HirDisplay for Ty {
664 write!(f, "{{unknown}}")?; 668 write!(f, "{{unknown}}")?;
665 } 669 }
666 TyKind::InferenceVar(..) => write!(f, "_")?, 670 TyKind::InferenceVar(..) => write!(f, "_")?,
671 TyKind::Generator(..) => write!(f, "{{generator}}")?,
672 TyKind::GeneratorWitness(..) => write!(f, "{{generator witness}}")?,
667 } 673 }
668 Ok(()) 674 Ok(())
669 } 675 }
@@ -741,17 +747,17 @@ fn write_bounds_like_dyn_trait(
741 if !first { 747 if !first {
742 write!(f, " + ")?; 748 write!(f, " + ")?;
743 } 749 }
744 // We assume that the self type is $0 (i.e. the 750 // We assume that the self type is ^0.0 (i.e. the
745 // existential) here, which is the only thing that's 751 // existential) here, which is the only thing that's
746 // possible in actual Rust, and hence don't print it 752 // possible in actual Rust, and hence don't print it
747 write!(f, "{}", f.db.trait_data(trait_).name)?; 753 write!(f, "{}", f.db.trait_data(trait_).name)?;
748 if let [_, params @ ..] = &*trait_ref.substitution.interned().as_slice() { 754 if let [_, params @ ..] = &*trait_ref.substitution.as_slice(&Interner) {
749 if is_fn_trait { 755 if is_fn_trait {
750 if let Some(args) = 756 if let Some(args) =
751 params.first().and_then(|it| it.assert_ty_ref(&Interner).as_tuple()) 757 params.first().and_then(|it| it.assert_ty_ref(&Interner).as_tuple())
752 { 758 {
753 write!(f, "(")?; 759 write!(f, "(")?;
754 f.write_joined(&*args.interned(), ", ")?; 760 f.write_joined(args.as_slice(&Interner), ", ")?;
755 write!(f, ")")?; 761 write!(f, ")")?;
756 } 762 }
757 } else if !params.is_empty() { 763 } else if !params.is_empty() {
@@ -783,6 +789,10 @@ fn write_bounds_like_dyn_trait(
783 } 789 }
784 ty.hir_fmt(f)?; 790 ty.hir_fmt(f)?;
785 } 791 }
792
793 // FIXME implement these
794 WhereClause::LifetimeOutlives(_) => {}
795 WhereClause::TypeOutlives(_) => {}
786 } 796 }
787 first = false; 797 first = false;
788 } 798 }
@@ -806,7 +816,7 @@ fn fmt_trait_ref(tr: &TraitRef, f: &mut HirFormatter, use_as: bool) -> Result<()
806 write!(f, "{}", f.db.trait_data(tr.hir_trait_id()).name)?; 816 write!(f, "{}", f.db.trait_data(tr.hir_trait_id()).name)?;
807 if tr.substitution.len(&Interner) > 1 { 817 if tr.substitution.len(&Interner) > 1 {
808 write!(f, "<")?; 818 write!(f, "<")?;
809 f.write_joined(&tr.substitution.interned()[1..], ", ")?; 819 f.write_joined(&tr.substitution.as_slice(&Interner)[1..], ", ")?;
810 write!(f, ">")?; 820 write!(f, ">")?;
811 } 821 }
812 Ok(()) 822 Ok(())
@@ -837,6 +847,10 @@ impl HirDisplay for WhereClause {
837 ty.hir_fmt(f)?; 847 ty.hir_fmt(f)?;
838 } 848 }
839 WhereClause::AliasEq(_) => write!(f, "{{error}}")?, 849 WhereClause::AliasEq(_) => write!(f, "{{error}}")?,
850
851 // FIXME implement these
852 WhereClause::TypeOutlives(..) => {}
853 WhereClause::LifetimeOutlives(..) => {}
840 } 854 }
841 Ok(()) 855 Ok(())
842 } 856 }
@@ -881,9 +895,11 @@ impl HirDisplay for DomainGoal {
881 DomainGoal::Holds(wc) => { 895 DomainGoal::Holds(wc) => {
882 write!(f, "Holds(")?; 896 write!(f, "Holds(")?;
883 wc.hir_fmt(f)?; 897 wc.hir_fmt(f)?;
884 write!(f, ")") 898 write!(f, ")")?;
885 } 899 }
900 _ => write!(f, "?")?,
886 } 901 }
902 Ok(())
887 } 903 }
888} 904}
889 905
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index 531159e54..bf2da2d4a 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -18,7 +18,7 @@ use std::mem;
18use std::ops::Index; 18use std::ops::Index;
19use std::sync::Arc; 19use std::sync::Arc;
20 20
21use chalk_ir::{cast::Cast, Mutability}; 21use chalk_ir::{cast::Cast, DebruijnIndex, Mutability};
22use hir_def::{ 22use hir_def::{
23 body::Body, 23 body::Body,
24 data::{ConstData, FunctionData, StaticData}, 24 data::{ConstData, FunctionData, StaticData},
@@ -38,11 +38,11 @@ use syntax::SmolStr;
38 38
39use super::{ 39use super::{
40 DomainGoal, Guidance, InEnvironment, ProjectionTy, Solution, TraitEnvironment, TraitRef, Ty, 40 DomainGoal, Guidance, InEnvironment, ProjectionTy, Solution, TraitEnvironment, TraitRef, Ty,
41 TypeWalk,
42}; 41};
43use crate::{ 42use crate::{
44 db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, 43 db::HirDatabase, fold_tys, infer::diagnostics::InferenceDiagnostic,
45 to_assoc_type_id, AliasEq, AliasTy, Canonical, Interner, TyBuilder, TyExt, TyKind, 44 lower::ImplTraitLoweringMode, to_assoc_type_id, AliasEq, AliasTy, Canonical, Interner,
45 TyBuilder, TyExt, TyKind,
46}; 46};
47 47
48// This lint has a false positive here. See the link below for details. 48// This lint has a false positive here. See the link below for details.
@@ -323,7 +323,7 @@ impl<'a> InferenceContext<'a> {
323 } 323 }
324 324
325 fn insert_type_vars(&mut self, ty: Ty) -> Ty { 325 fn insert_type_vars(&mut self, ty: Ty) -> Ty {
326 ty.fold(&mut |ty| self.insert_type_vars_shallow(ty)) 326 fold_tys(ty, |ty, _| self.insert_type_vars_shallow(ty), DebruijnIndex::INNERMOST)
327 } 327 }
328 328
329 fn resolve_obligations_as_possible(&mut self) { 329 fn resolve_obligations_as_possible(&mut self) {
@@ -434,12 +434,16 @@ impl<'a> InferenceContext<'a> {
434 /// to do it as well. 434 /// to do it as well.
435 fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { 435 fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty {
436 let ty = self.resolve_ty_as_possible(ty); 436 let ty = self.resolve_ty_as_possible(ty);
437 ty.fold(&mut |ty| match ty.kind(&Interner) { 437 fold_tys(
438 TyKind::Alias(AliasTy::Projection(proj_ty)) => { 438 ty,
439 self.normalize_projection_ty(proj_ty.clone()) 439 |ty, _| match ty.kind(&Interner) {
440 } 440 TyKind::Alias(AliasTy::Projection(proj_ty)) => {
441 _ => ty, 441 self.normalize_projection_ty(proj_ty.clone())
442 }) 442 }
443 _ => ty,
444 },
445 DebruijnIndex::INNERMOST,
446 )
443 } 447 }
444 448
445 fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { 449 fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs
index fd679f444..1f463a425 100644
--- a/crates/hir_ty/src/infer/coerce.rs
+++ b/crates/hir_ty/src/infer/coerce.rs
@@ -71,12 +71,14 @@ impl<'a> InferenceContext<'a> {
71 } 71 }
72 72
73 // Pointer weakening and function to pointer 73 // Pointer weakening and function to pointer
74 match (from_ty.interned_mut(), to_ty.kind(&Interner)) { 74 match (from_ty.kind(&Interner), to_ty.kind(&Interner)) {
75 // `*mut T` -> `*const T` 75 // `*mut T` -> `*const T`
76 (TyKind::Raw(_, inner), TyKind::Raw(m2 @ Mutability::Not, ..)) => {
77 from_ty = TyKind::Raw(*m2, inner.clone()).intern(&Interner);
78 }
76 // `&mut T` -> `&T` 79 // `&mut T` -> `&T`
77 (TyKind::Raw(m1, ..), TyKind::Raw(m2 @ Mutability::Not, ..)) 80 (TyKind::Ref(_, lt, inner), TyKind::Ref(m2 @ Mutability::Not, ..)) => {
78 | (TyKind::Ref(m1, ..), TyKind::Ref(m2 @ Mutability::Not, ..)) => { 81 from_ty = TyKind::Ref(*m2, lt.clone(), inner.clone()).intern(&Interner);
79 *m1 = *m2;
80 } 82 }
81 // `&T` -> `*const T` 83 // `&T` -> `*const T`
82 // `&mut T` -> `*mut T`/`*const T` 84 // `&mut T` -> `*mut T`/`*const T`
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index 9841988c5..50497eecb 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -3,7 +3,7 @@
3use std::iter::{repeat, repeat_with}; 3use std::iter::{repeat, repeat_with};
4use std::{mem, sync::Arc}; 4use std::{mem, sync::Arc};
5 5
6use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; 6use chalk_ir::{cast::Cast, fold::Shift, Mutability, TyVariableKind};
7use hir_def::{ 7use hir_def::{
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},
@@ -17,14 +17,14 @@ use syntax::ast::RangeOp;
17use crate::{ 17use crate::{
18 autoderef, dummy_usize_const, 18 autoderef, dummy_usize_const,
19 lower::lower_to_chalk_mutability, 19 lower::lower_to_chalk_mutability,
20 mapping::from_chalk,
20 method_resolution, op, 21 method_resolution, op,
21 primitive::{self, UintTy}, 22 primitive::{self, UintTy},
22 static_lifetime, to_chalk_trait_id, 23 static_lifetime, to_chalk_trait_id,
23 traits::{chalk::from_chalk, FnTrait}, 24 traits::FnTrait,
24 utils::{generics, Generics}, 25 utils::{generics, Generics},
25 AdtId, Binders, CallableDefId, FnPointer, FnSig, FnSubst, InEnvironment, Interner, 26 AdtId, Binders, CallableDefId, FnPointer, FnSig, FnSubst, InEnvironment, Interner,
26 ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind, 27 ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind,
27 TypeWalk,
28}; 28};
29 29
30use super::{ 30use super::{
@@ -463,7 +463,11 @@ impl<'a> InferenceContext<'a> {
463 }; 463 };
464 match canonicalized.decanonicalize_ty(derefed_ty.value).kind(&Interner) { 464 match canonicalized.decanonicalize_ty(derefed_ty.value).kind(&Interner) {
465 TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| { 465 TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| {
466 substs.interned().get(idx).map(|a| a.assert_ty_ref(&Interner)).cloned() 466 substs
467 .as_slice(&Interner)
468 .get(idx)
469 .map(|a| a.assert_ty_ref(&Interner))
470 .cloned()
467 }), 471 }),
468 TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { 472 TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => {
469 let local_id = self.db.struct_data(*s).variant_data.field(name)?; 473 let local_id = self.db.struct_data(*s).variant_data.field(name)?;
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index a41e8e116..aea354cde 100644
--- a/crates/hir_ty/src/infer/pat.rs
+++ b/crates/hir_ty/src/infer/pat.rs
@@ -122,7 +122,7 @@ impl<'a> InferenceContext<'a> {
122 let ty = match &body[pat] { 122 let ty = match &body[pat] {
123 &Pat::Tuple { ref args, ellipsis } => { 123 &Pat::Tuple { ref args, ellipsis } => {
124 let expectations = match expected.as_tuple() { 124 let expectations = match expected.as_tuple() {
125 Some(parameters) => &*parameters.interned().as_slice(), 125 Some(parameters) => &*parameters.as_slice(&Interner),
126 _ => &[], 126 _ => &[],
127 }; 127 };
128 128
@@ -242,7 +242,7 @@ impl<'a> InferenceContext<'a> {
242 let (inner_ty, alloc_ty) = match expected.as_adt() { 242 let (inner_ty, alloc_ty) = match expected.as_adt() {
243 Some((adt, subst)) if adt == box_adt => ( 243 Some((adt, subst)) if adt == box_adt => (
244 subst.at(&Interner, 0).assert_ty_ref(&Interner).clone(), 244 subst.at(&Interner, 0).assert_ty_ref(&Interner).clone(),
245 subst.interned().get(1).and_then(|a| a.ty(&Interner).cloned()), 245 subst.as_slice(&Interner).get(1).and_then(|a| a.ty(&Interner).cloned()),
246 ), 246 ),
247 _ => (self.result.standard_types.unknown.clone(), None), 247 _ => (self.result.standard_types.unknown.clone(), None),
248 }; 248 };
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs
index f8955aa32..495282eba 100644
--- a/crates/hir_ty/src/infer/path.rs
+++ b/crates/hir_ty/src/infer/path.rs
@@ -101,7 +101,7 @@ impl<'a> InferenceContext<'a> {
101 let substs = ctx.substs_from_path(path, typable, true); 101 let substs = ctx.substs_from_path(path, typable, true);
102 let ty = TyBuilder::value_ty(self.db, typable) 102 let ty = TyBuilder::value_ty(self.db, typable)
103 .use_parent_substs(&parent_substs) 103 .use_parent_substs(&parent_substs)
104 .fill(substs.interned()[parent_substs.len(&Interner)..].iter().cloned()) 104 .fill(substs.as_slice(&Interner)[parent_substs.len(&Interner)..].iter().cloned())
105 .build(); 105 .build();
106 Some(ty) 106 Some(ty)
107 } 107 }
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs
index 2ea9dd920..a887e20b0 100644
--- a/crates/hir_ty/src/infer/unify.rs
+++ b/crates/hir_ty/src/infer/unify.rs
@@ -2,14 +2,17 @@
2 2
3use std::borrow::Cow; 3use std::borrow::Cow;
4 4
5use chalk_ir::{FloatTy, IntTy, TyVariableKind, UniverseIndex, VariableKind}; 5use chalk_ir::{
6 cast::Cast, fold::Fold, interner::HasInterner, FloatTy, IntTy, TyVariableKind, UniverseIndex,
7 VariableKind,
8};
6use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; 9use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
7 10
8use super::{DomainGoal, InferenceContext}; 11use super::{DomainGoal, InferenceContext};
9use crate::{ 12use crate::{
10 AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, FnSubst, 13 fold_tys, static_lifetime, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds,
11 InEnvironment, InferenceVar, Interner, Scalar, Substitution, Ty, TyExt, TyKind, TypeWalk, 14 DebruijnIndex, FnPointer, FnSubst, InEnvironment, InferenceVar, Interner, Scalar, Substitution,
12 WhereClause, 15 Ty, TyExt, TyKind, WhereClause,
13}; 16};
14 17
15impl<'a> InferenceContext<'a> { 18impl<'a> InferenceContext<'a> {
@@ -34,7 +37,10 @@ where
34} 37}
35 38
36#[derive(Debug)] 39#[derive(Debug)]
37pub(super) struct Canonicalized<T> { 40pub(super) struct Canonicalized<T>
41where
42 T: HasInterner<Interner = Interner>,
43{
38 pub(super) value: Canonical<T>, 44 pub(super) value: Canonical<T>,
39 free_vars: Vec<(InferenceVar, TyVariableKind)>, 45 free_vars: Vec<(InferenceVar, TyVariableKind)>,
40} 46}
@@ -48,9 +54,14 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
48 }) 54 })
49 } 55 }
50 56
51 fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: DebruijnIndex) -> T { 57 fn do_canonicalize<T: Fold<Interner, Result = T> + HasInterner<Interner = Interner>>(
52 t.fold_binders( 58 &mut self,
53 &mut |ty, binders| match ty.kind(&Interner) { 59 t: T,
60 binders: DebruijnIndex,
61 ) -> T {
62 fold_tys(
63 t,
64 |ty, binders| match ty.kind(&Interner) {
54 &TyKind::InferenceVar(var, kind) => { 65 &TyKind::InferenceVar(var, kind) => {
55 let inner = from_inference_var(var); 66 let inner = from_inference_var(var);
56 if self.var_stack.contains(&inner) { 67 if self.var_stack.contains(&inner) {
@@ -76,7 +87,10 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
76 ) 87 )
77 } 88 }
78 89
79 fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { 90 fn into_canonicalized<T: HasInterner<Interner = Interner>>(
91 self,
92 result: T,
93 ) -> Canonicalized<T> {
80 let kinds = self 94 let kinds = self
81 .free_vars 95 .free_vars
82 .iter() 96 .iter()
@@ -103,28 +117,18 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
103 DomainGoal::Holds(wc) => { 117 DomainGoal::Holds(wc) => {
104 DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST)) 118 DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST))
105 } 119 }
120 _ => unimplemented!(),
106 }; 121 };
107 self.into_canonicalized(InEnvironment { goal: result, environment: obligation.environment }) 122 self.into_canonicalized(InEnvironment { goal: result, environment: obligation.environment })
108 } 123 }
109} 124}
110 125
111impl<T> Canonicalized<T> { 126impl<T: HasInterner<Interner = Interner>> Canonicalized<T> {
112 pub(super) fn decanonicalize_ty(&self, ty: Ty) -> Ty { 127 pub(super) fn decanonicalize_ty(&self, ty: Ty) -> Ty {
113 ty.fold_binders( 128 crate::fold_free_vars(ty, |bound, _binders| {
114 &mut |ty, binders| { 129 let (v, k) = self.free_vars[bound.index];
115 if let TyKind::BoundVar(bound) = ty.kind(&Interner) { 130 TyKind::InferenceVar(v, k).intern(&Interner)
116 if bound.debruijn >= binders { 131 })
117 let (v, k) = self.free_vars[bound.index];
118 TyKind::InferenceVar(v, k).intern(&Interner)
119 } else {
120 ty
121 }
122 } else {
123 ty
124 }
125 },
126 DebruijnIndex::INNERMOST,
127 )
128 } 132 }
129 133
130 pub(super) fn apply_solution( 134 pub(super) fn apply_solution(
@@ -136,15 +140,17 @@ impl<T> Canonicalized<T> {
136 let new_vars = Substitution::from_iter( 140 let new_vars = Substitution::from_iter(
137 &Interner, 141 &Interner,
138 solution.binders.iter(&Interner).map(|k| match k.kind { 142 solution.binders.iter(&Interner).map(|k| match k.kind {
139 VariableKind::Ty(TyVariableKind::General) => ctx.table.new_type_var(), 143 VariableKind::Ty(TyVariableKind::General) => {
140 VariableKind::Ty(TyVariableKind::Integer) => ctx.table.new_integer_var(), 144 ctx.table.new_type_var().cast(&Interner)
141 VariableKind::Ty(TyVariableKind::Float) => ctx.table.new_float_var(), 145 }
142 // HACK: Chalk can sometimes return new lifetime variables. We 146 VariableKind::Ty(TyVariableKind::Integer) => {
143 // want to just skip them, but to not mess up the indices of 147 ctx.table.new_integer_var().cast(&Interner)
144 // other variables, we'll just create a new type variable in 148 }
145 // their place instead. This should not matter (we never see the 149 VariableKind::Ty(TyVariableKind::Float) => {
146 // actual *uses* of the lifetime variable). 150 ctx.table.new_float_var().cast(&Interner)
147 VariableKind::Lifetime => ctx.table.new_type_var(), 151 }
152 // Chalk can sometimes return new lifetime variables. We just use the static lifetime everywhere
153 VariableKind::Lifetime => static_lifetime().cast(&Interner),
148 _ => panic!("const variable in solution"), 154 _ => panic!("const variable in solution"),
149 }), 155 }),
150 ); 156 );
@@ -488,55 +494,63 @@ impl InferenceTable {
488 /// be resolved as far as possible, i.e. contain no type variables with 494 /// be resolved as far as possible, i.e. contain no type variables with
489 /// known type. 495 /// known type.
490 fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { 496 fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
491 ty.fold(&mut |ty| match ty.kind(&Interner) { 497 fold_tys(
492 &TyKind::InferenceVar(tv, kind) => { 498 ty,
493 let inner = from_inference_var(tv); 499 |ty, _| match ty.kind(&Interner) {
494 if tv_stack.contains(&inner) { 500 &TyKind::InferenceVar(tv, kind) => {
495 cov_mark::hit!(type_var_cycles_resolve_as_possible); 501 let inner = from_inference_var(tv);
496 // recursive type 502 if tv_stack.contains(&inner) {
497 return self.type_variable_table.fallback_value(tv, kind); 503 cov_mark::hit!(type_var_cycles_resolve_as_possible);
498 } 504 // recursive type
499 if let Some(known_ty) = 505 return self.type_variable_table.fallback_value(tv, kind);
500 self.var_unification_table.inlined_probe_value(inner).known() 506 }
501 { 507 if let Some(known_ty) =
502 // known_ty may contain other variables that are known by now 508 self.var_unification_table.inlined_probe_value(inner).known()
503 tv_stack.push(inner); 509 {
504 let result = self.resolve_ty_as_possible_inner(tv_stack, known_ty.clone()); 510 // known_ty may contain other variables that are known by now
505 tv_stack.pop(); 511 tv_stack.push(inner);
506 result 512 let result = self.resolve_ty_as_possible_inner(tv_stack, known_ty.clone());
507 } else { 513 tv_stack.pop();
508 ty 514 result
515 } else {
516 ty
517 }
509 } 518 }
510 } 519 _ => ty,
511 _ => ty, 520 },
512 }) 521 DebruijnIndex::INNERMOST,
522 )
513 } 523 }
514 524
515 /// Resolves the type completely; type variables without known type are 525 /// Resolves the type completely; type variables without known type are
516 /// replaced by TyKind::Unknown. 526 /// replaced by TyKind::Unknown.
517 fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { 527 fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
518 ty.fold(&mut |ty| match ty.kind(&Interner) { 528 fold_tys(
519 &TyKind::InferenceVar(tv, kind) => { 529 ty,
520 let inner = from_inference_var(tv); 530 |ty, _| match ty.kind(&Interner) {
521 if tv_stack.contains(&inner) { 531 &TyKind::InferenceVar(tv, kind) => {
522 cov_mark::hit!(type_var_cycles_resolve_completely); 532 let inner = from_inference_var(tv);
523 // recursive type 533 if tv_stack.contains(&inner) {
524 return self.type_variable_table.fallback_value(tv, kind); 534 cov_mark::hit!(type_var_cycles_resolve_completely);
525 } 535 // recursive type
526 if let Some(known_ty) = 536 return self.type_variable_table.fallback_value(tv, kind);
527 self.var_unification_table.inlined_probe_value(inner).known() 537 }
528 { 538 if let Some(known_ty) =
529 // known_ty may contain other variables that are known by now 539 self.var_unification_table.inlined_probe_value(inner).known()
530 tv_stack.push(inner); 540 {
531 let result = self.resolve_ty_completely_inner(tv_stack, known_ty.clone()); 541 // known_ty may contain other variables that are known by now
532 tv_stack.pop(); 542 tv_stack.push(inner);
533 result 543 let result = self.resolve_ty_completely_inner(tv_stack, known_ty.clone());
534 } else { 544 tv_stack.pop();
535 self.type_variable_table.fallback_value(tv, kind) 545 result
546 } else {
547 self.type_variable_table.fallback_value(tv, kind)
548 }
536 } 549 }
537 } 550 _ => ty,
538 _ => ty, 551 },
539 }) 552 DebruijnIndex::INNERMOST,
553 )
540 } 554 }
541} 555}
542 556
diff --git a/crates/hir_ty/src/traits/chalk/interner.rs b/crates/hir_ty/src/interner.rs
index bd9395b7e..a1656115d 100644
--- a/crates/hir_ty/src/traits/chalk/interner.rs
+++ b/crates/hir_ty/src/interner.rs
@@ -1,61 +1,83 @@
1//! Implementation of the Chalk `Interner` trait, which allows customizing the 1//! Implementation of the Chalk `Interner` trait, which allows customizing the
2//! representation of the various objects Chalk deals with (types, goals etc.). 2//! representation of the various objects Chalk deals with (types, goals etc.).
3 3
4use super::tls; 4use crate::{chalk_db, tls, GenericArg};
5use base_db::salsa::InternId; 5use base_db::salsa::InternId;
6use chalk_ir::{GenericArg, Goal, GoalData}; 6use chalk_ir::{Goal, GoalData};
7use hir_def::TypeAliasId; 7use hir_def::{
8 intern::{impl_internable, InternStorage, Internable, Interned},
9 TypeAliasId,
10};
8use smallvec::SmallVec; 11use smallvec::SmallVec;
9use std::{fmt, sync::Arc}; 12use std::{fmt, sync::Arc};
10 13
11#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] 14#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
12pub struct Interner; 15pub struct Interner;
13 16
14pub(crate) type AssocTypeId = chalk_ir::AssocTypeId<Interner>; 17#[derive(PartialEq, Eq, Hash, Debug)]
15pub(crate) type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>; 18pub struct InternedWrapper<T>(T);
16pub(crate) type TraitId = chalk_ir::TraitId<Interner>; 19
17pub(crate) type TraitDatum = chalk_solve::rust_ir::TraitDatum<Interner>; 20impl<T> std::ops::Deref for InternedWrapper<T> {
18pub(crate) type AdtId = chalk_ir::AdtId<Interner>; 21 type Target = T;
19pub(crate) type StructDatum = chalk_solve::rust_ir::AdtDatum<Interner>; 22
20pub(crate) type ImplId = chalk_ir::ImplId<Interner>; 23 fn deref(&self) -> &Self::Target {
21pub(crate) type ImplDatum = chalk_solve::rust_ir::ImplDatum<Interner>; 24 &self.0
22pub(crate) type AssociatedTyValueId = chalk_solve::rust_ir::AssociatedTyValueId<Interner>; 25 }
23pub(crate) type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue<Interner>; 26}
24pub(crate) type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>; 27
25pub(crate) type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; 28impl_internable!(
26pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum<Interner>; 29 InternedWrapper<Vec<chalk_ir::VariableKind<Interner>>>,
27pub(crate) type Variances = chalk_ir::Variances<Interner>; 30 InternedWrapper<SmallVec<[GenericArg; 2]>>,
31 InternedWrapper<chalk_ir::TyData<Interner>>,
32 InternedWrapper<chalk_ir::LifetimeData<Interner>>,
33 InternedWrapper<chalk_ir::ConstData<Interner>>,
34 InternedWrapper<Vec<chalk_ir::CanonicalVarKind<Interner>>>,
35 InternedWrapper<Vec<chalk_ir::ProgramClause<Interner>>>,
36 InternedWrapper<Vec<chalk_ir::QuantifiedWhereClause<Interner>>>,
37 InternedWrapper<Vec<chalk_ir::Variance>>,
38);
28 39
29impl chalk_ir::interner::Interner for Interner { 40impl chalk_ir::interner::Interner for Interner {
30 type InternedType = Arc<chalk_ir::TyData<Self>>; 41 type InternedType = Interned<InternedWrapper<chalk_ir::TyData<Interner>>>;
31 type InternedLifetime = chalk_ir::LifetimeData<Self>; 42 type InternedLifetime = Interned<InternedWrapper<chalk_ir::LifetimeData<Self>>>;
32 type InternedConst = Arc<chalk_ir::ConstData<Self>>; 43 type InternedConst = Interned<InternedWrapper<chalk_ir::ConstData<Self>>>;
33 type InternedConcreteConst = (); 44 type InternedConcreteConst = ();
34 type InternedGenericArg = chalk_ir::GenericArgData<Self>; 45 type InternedGenericArg = chalk_ir::GenericArgData<Self>;
35 type InternedGoal = Arc<GoalData<Self>>; 46 type InternedGoal = Arc<GoalData<Self>>;
36 type InternedGoals = Vec<Goal<Self>>; 47 type InternedGoals = Vec<Goal<Self>>;
37 type InternedSubstitution = SmallVec<[GenericArg<Self>; 2]>; 48 type InternedSubstitution = Interned<InternedWrapper<SmallVec<[GenericArg; 2]>>>;
38 type InternedProgramClause = Arc<chalk_ir::ProgramClauseData<Self>>; 49 type InternedProgramClause = chalk_ir::ProgramClauseData<Self>;
39 type InternedProgramClauses = Arc<[chalk_ir::ProgramClause<Self>]>; 50 type InternedProgramClauses = Interned<InternedWrapper<Vec<chalk_ir::ProgramClause<Self>>>>;
40 type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>; 51 type InternedQuantifiedWhereClauses =
41 type InternedVariableKinds = Vec<chalk_ir::VariableKind<Self>>; 52 Interned<InternedWrapper<Vec<chalk_ir::QuantifiedWhereClause<Self>>>>;
42 type InternedCanonicalVarKinds = Vec<chalk_ir::CanonicalVarKind<Self>>; 53 type InternedVariableKinds = Interned<InternedWrapper<Vec<chalk_ir::VariableKind<Interner>>>>;
54 type InternedCanonicalVarKinds =
55 Interned<InternedWrapper<Vec<chalk_ir::CanonicalVarKind<Self>>>>;
43 type InternedConstraints = Vec<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>>; 56 type InternedConstraints = Vec<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>>;
44 type InternedVariances = Arc<[chalk_ir::Variance]>; 57 type InternedVariances = Interned<InternedWrapper<Vec<chalk_ir::Variance>>>;
45 type DefId = InternId; 58 type DefId = InternId;
46 type InternedAdtId = hir_def::AdtId; 59 type InternedAdtId = hir_def::AdtId;
47 type Identifier = TypeAliasId; 60 type Identifier = TypeAliasId;
48 type FnAbi = (); 61 type FnAbi = ();
49 62
50 fn debug_adt_id(type_kind_id: AdtId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { 63 fn debug_adt_id(
64 type_kind_id: chalk_db::AdtId,
65 fmt: &mut fmt::Formatter<'_>,
66 ) -> Option<fmt::Result> {
51 tls::with_current_program(|prog| Some(prog?.debug_struct_id(type_kind_id, fmt))) 67 tls::with_current_program(|prog| Some(prog?.debug_struct_id(type_kind_id, fmt)))
52 } 68 }
53 69
54 fn debug_trait_id(type_kind_id: TraitId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { 70 fn debug_trait_id(
71 type_kind_id: chalk_db::TraitId,
72 fmt: &mut fmt::Formatter<'_>,
73 ) -> Option<fmt::Result> {
55 tls::with_current_program(|prog| Some(prog?.debug_trait_id(type_kind_id, fmt))) 74 tls::with_current_program(|prog| Some(prog?.debug_trait_id(type_kind_id, fmt)))
56 } 75 }
57 76
58 fn debug_assoc_type_id(id: AssocTypeId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { 77 fn debug_assoc_type_id(
78 id: chalk_db::AssocTypeId,
79 fmt: &mut fmt::Formatter<'_>,
80 ) -> Option<fmt::Result> {
59 tls::with_current_program(|prog| Some(prog?.debug_assoc_type_id(id, fmt))) 81 tls::with_current_program(|prog| Some(prog?.debug_assoc_type_id(id, fmt)))
60 } 82 }
61 83
@@ -99,7 +121,7 @@ impl chalk_ir::interner::Interner for Interner {
99 } 121 }
100 122
101 fn debug_generic_arg( 123 fn debug_generic_arg(
102 parameter: &GenericArg<Interner>, 124 parameter: &GenericArg,
103 fmt: &mut fmt::Formatter<'_>, 125 fmt: &mut fmt::Formatter<'_>,
104 ) -> Option<fmt::Result> { 126 ) -> Option<fmt::Result> {
105 tls::with_current_program(|prog| Some(prog?.debug_generic_arg(parameter, fmt))) 127 tls::with_current_program(|prog| Some(prog?.debug_generic_arg(parameter, fmt)))
@@ -194,30 +216,30 @@ impl chalk_ir::interner::Interner for Interner {
194 216
195 fn intern_ty(&self, kind: chalk_ir::TyKind<Self>) -> Self::InternedType { 217 fn intern_ty(&self, kind: chalk_ir::TyKind<Self>) -> Self::InternedType {
196 let flags = kind.compute_flags(self); 218 let flags = kind.compute_flags(self);
197 Arc::new(chalk_ir::TyData { kind, flags }) 219 Interned::new(InternedWrapper(chalk_ir::TyData { kind, flags }))
198 } 220 }
199 221
200 fn ty_data<'a>(&self, ty: &'a Self::InternedType) -> &'a chalk_ir::TyData<Self> { 222 fn ty_data<'a>(&self, ty: &'a Self::InternedType) -> &'a chalk_ir::TyData<Self> {
201 ty 223 &ty.0
202 } 224 }
203 225
204 fn intern_lifetime(&self, lifetime: chalk_ir::LifetimeData<Self>) -> Self::InternedLifetime { 226 fn intern_lifetime(&self, lifetime: chalk_ir::LifetimeData<Self>) -> Self::InternedLifetime {
205 lifetime 227 Interned::new(InternedWrapper(lifetime))
206 } 228 }
207 229
208 fn lifetime_data<'a>( 230 fn lifetime_data<'a>(
209 &self, 231 &self,
210 lifetime: &'a Self::InternedLifetime, 232 lifetime: &'a Self::InternedLifetime,
211 ) -> &'a chalk_ir::LifetimeData<Self> { 233 ) -> &'a chalk_ir::LifetimeData<Self> {
212 lifetime 234 &lifetime.0
213 } 235 }
214 236
215 fn intern_const(&self, constant: chalk_ir::ConstData<Self>) -> Self::InternedConst { 237 fn intern_const(&self, constant: chalk_ir::ConstData<Self>) -> Self::InternedConst {
216 Arc::new(constant) 238 Interned::new(InternedWrapper(constant))
217 } 239 }
218 240
219 fn const_data<'a>(&self, constant: &'a Self::InternedConst) -> &'a chalk_ir::ConstData<Self> { 241 fn const_data<'a>(&self, constant: &'a Self::InternedConst) -> &'a chalk_ir::ConstData<Self> {
220 constant 242 &constant.0
221 } 243 }
222 244
223 fn const_eq( 245 fn const_eq(
@@ -264,23 +286,23 @@ impl chalk_ir::interner::Interner for Interner {
264 286
265 fn intern_substitution<E>( 287 fn intern_substitution<E>(
266 &self, 288 &self,
267 data: impl IntoIterator<Item = Result<GenericArg<Self>, E>>, 289 data: impl IntoIterator<Item = Result<GenericArg, E>>,
268 ) -> Result<Self::InternedSubstitution, E> { 290 ) -> Result<Self::InternedSubstitution, E> {
269 data.into_iter().collect() 291 Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
270 } 292 }
271 293
272 fn substitution_data<'a>( 294 fn substitution_data<'a>(
273 &self, 295 &self,
274 substitution: &'a Self::InternedSubstitution, 296 substitution: &'a Self::InternedSubstitution,
275 ) -> &'a [GenericArg<Self>] { 297 ) -> &'a [GenericArg] {
276 substitution 298 &substitution.as_ref().0
277 } 299 }
278 300
279 fn intern_program_clause( 301 fn intern_program_clause(
280 &self, 302 &self,
281 data: chalk_ir::ProgramClauseData<Self>, 303 data: chalk_ir::ProgramClauseData<Self>,
282 ) -> Self::InternedProgramClause { 304 ) -> Self::InternedProgramClause {
283 Arc::new(data) 305 data
284 } 306 }
285 307
286 fn program_clause_data<'a>( 308 fn program_clause_data<'a>(
@@ -294,7 +316,7 @@ impl chalk_ir::interner::Interner for Interner {
294 &self, 316 &self,
295 data: impl IntoIterator<Item = Result<chalk_ir::ProgramClause<Self>, E>>, 317 data: impl IntoIterator<Item = Result<chalk_ir::ProgramClause<Self>, E>>,
296 ) -> Result<Self::InternedProgramClauses, E> { 318 ) -> Result<Self::InternedProgramClauses, E> {
297 data.into_iter().collect() 319 Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
298 } 320 }
299 321
300 fn program_clauses_data<'a>( 322 fn program_clauses_data<'a>(
@@ -308,7 +330,7 @@ impl chalk_ir::interner::Interner for Interner {
308 &self, 330 &self,
309 data: impl IntoIterator<Item = Result<chalk_ir::QuantifiedWhereClause<Self>, E>>, 331 data: impl IntoIterator<Item = Result<chalk_ir::QuantifiedWhereClause<Self>, E>>,
310 ) -> Result<Self::InternedQuantifiedWhereClauses, E> { 332 ) -> Result<Self::InternedQuantifiedWhereClauses, E> {
311 data.into_iter().collect() 333 Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
312 } 334 }
313 335
314 fn quantified_where_clauses_data<'a>( 336 fn quantified_where_clauses_data<'a>(
@@ -322,21 +344,21 @@ impl chalk_ir::interner::Interner for Interner {
322 &self, 344 &self,
323 data: impl IntoIterator<Item = Result<chalk_ir::VariableKind<Self>, E>>, 345 data: impl IntoIterator<Item = Result<chalk_ir::VariableKind<Self>, E>>,
324 ) -> Result<Self::InternedVariableKinds, E> { 346 ) -> Result<Self::InternedVariableKinds, E> {
325 data.into_iter().collect() 347 Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
326 } 348 }
327 349
328 fn variable_kinds_data<'a>( 350 fn variable_kinds_data<'a>(
329 &self, 351 &self,
330 parameter_kinds: &'a Self::InternedVariableKinds, 352 parameter_kinds: &'a Self::InternedVariableKinds,
331 ) -> &'a [chalk_ir::VariableKind<Self>] { 353 ) -> &'a [chalk_ir::VariableKind<Self>] {
332 &parameter_kinds 354 &parameter_kinds.as_ref().0
333 } 355 }
334 356
335 fn intern_canonical_var_kinds<E>( 357 fn intern_canonical_var_kinds<E>(
336 &self, 358 &self,
337 data: impl IntoIterator<Item = Result<chalk_ir::CanonicalVarKind<Self>, E>>, 359 data: impl IntoIterator<Item = Result<chalk_ir::CanonicalVarKind<Self>, E>>,
338 ) -> Result<Self::InternedCanonicalVarKinds, E> { 360 ) -> Result<Self::InternedCanonicalVarKinds, E> {
339 data.into_iter().collect() 361 Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
340 } 362 }
341 363
342 fn canonical_var_kinds_data<'a>( 364 fn canonical_var_kinds_data<'a>(
@@ -376,7 +398,7 @@ impl chalk_ir::interner::Interner for Interner {
376 &self, 398 &self,
377 data: impl IntoIterator<Item = Result<chalk_ir::Variance, E>>, 399 data: impl IntoIterator<Item = Result<chalk_ir::Variance, E>>,
378 ) -> Result<Self::InternedVariances, E> { 400 ) -> Result<Self::InternedVariances, E> {
379 data.into_iter().collect() 401 Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
380 } 402 }
381 403
382 fn variances_data<'a>( 404 fn variances_data<'a>(
@@ -390,3 +412,12 @@ impl chalk_ir::interner::Interner for Interner {
390impl chalk_ir::interner::HasInterner for Interner { 412impl chalk_ir::interner::HasInterner for Interner {
391 type Interner = Self; 413 type Interner = Self;
392} 414}
415
416#[macro_export]
417macro_rules! has_interner {
418 ($t:ty) => {
419 impl HasInterner for $t {
420 type Interner = crate::Interner;
421 }
422 };
423}
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index 87f10e9d5..113234fa4 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -1,27 +1,29 @@
1//! The type system. We currently use this to infer types for completion, hover 1//! The type system. We currently use this to infer types for completion, hover
2//! information and various assists. 2//! information and various assists.
3
3#[allow(unused)] 4#[allow(unused)]
4macro_rules! eprintln { 5macro_rules! eprintln {
5 ($($tt:tt)*) => { stdx::eprintln!($($tt)*) }; 6 ($($tt:tt)*) => { stdx::eprintln!($($tt)*) };
6} 7}
7 8
8mod autoderef; 9mod autoderef;
9pub mod primitive;
10pub mod traits;
11pub mod method_resolution;
12mod op;
13mod lower;
14pub(crate) mod infer;
15pub(crate) mod utils;
16mod chalk_cast;
17mod chalk_ext;
18mod builder; 10mod builder;
11mod chalk_db;
12mod chalk_ext;
13mod infer;
14mod interner;
15mod lower;
16mod mapping;
17mod op;
18mod tls;
19mod utils;
19mod walk; 20mod walk;
20mod types;
21
22pub mod display;
23pub mod db; 21pub mod db;
24pub mod diagnostics; 22pub mod diagnostics;
23pub mod display;
24pub mod method_resolution;
25pub mod primitive;
26pub mod traits;
25 27
26#[cfg(test)] 28#[cfg(test)]
27mod tests; 29mod tests;
@@ -30,12 +32,12 @@ mod test_db;
30 32
31use std::sync::Arc; 33use std::sync::Arc;
32 34
33use base_db::salsa; 35use chalk_ir::{
34use chalk_ir::UintTy; 36 fold::{Fold, Shift},
35use hir_def::{ 37 interner::HasInterner,
36 expr::ExprId, type_ref::Rawness, ConstParamId, LifetimeParamId, TraitId, TypeAliasId, 38 UintTy,
37 TypeParamId,
38}; 39};
40use hir_def::{expr::ExprId, type_ref::Rawness, TypeParamId};
39 41
40use crate::{db::HirDatabase, display::HirDisplay, utils::generics}; 42use crate::{db::HirDatabase, display::HirDisplay, utils::generics};
41 43
@@ -43,12 +45,17 @@ pub use autoderef::autoderef;
43pub use builder::TyBuilder; 45pub use builder::TyBuilder;
44pub use chalk_ext::*; 46pub use chalk_ext::*;
45pub use infer::{could_unify, InferenceResult}; 47pub use infer::{could_unify, InferenceResult};
48pub use interner::Interner;
46pub use lower::{ 49pub use lower::{
47 associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, 50 associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode,
48 TyDefId, TyLoweringContext, ValueTyDefId, 51 TyDefId, TyLoweringContext, ValueTyDefId,
49}; 52};
50pub use traits::{chalk::Interner, TraitEnvironment}; 53pub use mapping::{
51pub use types::*; 54 const_from_placeholder_idx, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
55 from_placeholder_idx, lt_from_placeholder_idx, to_assoc_type_id, to_chalk_trait_id,
56 to_foreign_def_id, to_placeholder_idx,
57};
58pub use traits::TraitEnvironment;
52pub use walk::TypeWalk; 59pub use walk::TypeWalk;
53 60
54pub use chalk_ir::{ 61pub use chalk_ir::{
@@ -65,6 +72,21 @@ pub type PlaceholderIndex = chalk_ir::PlaceholderIndex;
65pub type VariableKind = chalk_ir::VariableKind<Interner>; 72pub type VariableKind = chalk_ir::VariableKind<Interner>;
66pub type VariableKinds = chalk_ir::VariableKinds<Interner>; 73pub type VariableKinds = chalk_ir::VariableKinds<Interner>;
67pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>; 74pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>;
75pub type Binders<T> = chalk_ir::Binders<T>;
76pub type Substitution = chalk_ir::Substitution<Interner>;
77pub type GenericArg = chalk_ir::GenericArg<Interner>;
78pub type GenericArgData = chalk_ir::GenericArgData<Interner>;
79
80pub type Ty = chalk_ir::Ty<Interner>;
81pub type TyKind = chalk_ir::TyKind<Interner>;
82pub type DynTy = chalk_ir::DynTy<Interner>;
83pub type FnPointer = chalk_ir::FnPointer<Interner>;
84// pub type FnSubst = chalk_ir::FnSubst<Interner>;
85pub use chalk_ir::FnSubst;
86pub type ProjectionTy = chalk_ir::ProjectionTy<Interner>;
87pub type AliasTy = chalk_ir::AliasTy<Interner>;
88pub type OpaqueTy = chalk_ir::OpaqueTy<Interner>;
89pub type InferenceVar = chalk_ir::InferenceVar;
68 90
69pub type Lifetime = chalk_ir::Lifetime<Interner>; 91pub type Lifetime = chalk_ir::Lifetime<Interner>;
70pub type LifetimeData = chalk_ir::LifetimeData<Interner>; 92pub type LifetimeData = chalk_ir::LifetimeData<Interner>;
@@ -76,12 +98,27 @@ pub type ConstValue = chalk_ir::ConstValue<Interner>;
76pub type ConcreteConst = chalk_ir::ConcreteConst<Interner>; 98pub type ConcreteConst = chalk_ir::ConcreteConst<Interner>;
77 99
78pub type ChalkTraitId = chalk_ir::TraitId<Interner>; 100pub type ChalkTraitId = chalk_ir::TraitId<Interner>;
101pub type TraitRef = chalk_ir::TraitRef<Interner>;
102pub type QuantifiedWhereClause = Binders<WhereClause>;
103pub type QuantifiedWhereClauses = chalk_ir::QuantifiedWhereClauses<Interner>;
104pub type Canonical<T> = chalk_ir::Canonical<T>;
79 105
80pub type FnSig = chalk_ir::FnSig<Interner>; 106pub type FnSig = chalk_ir::FnSig<Interner>;
81 107
108pub type InEnvironment<T> = chalk_ir::InEnvironment<T>;
109pub type DomainGoal = chalk_ir::DomainGoal<Interner>;
110pub type AliasEq = chalk_ir::AliasEq<Interner>;
111pub type Solution = chalk_solve::Solution<Interner>;
112pub type ConstrainedSubst = chalk_ir::ConstrainedSubst<Interner>;
113pub type Guidance = chalk_solve::Guidance<Interner>;
114pub type WhereClause = chalk_ir::WhereClause<Interner>;
115
82// FIXME: get rid of this 116// FIXME: get rid of this
83pub fn subst_prefix(s: &Substitution, n: usize) -> Substitution { 117pub fn subst_prefix(s: &Substitution, n: usize) -> Substitution {
84 Substitution::intern(s.interned()[..std::cmp::min(s.len(&Interner), n)].into()) 118 Substitution::from_iter(
119 &Interner,
120 s.as_slice(&Interner)[..std::cmp::min(s.len(&Interner), n)].iter().cloned(),
121 )
85} 122}
86 123
87/// Return an index of a parameter in the generic type parameter list by it's id. 124/// Return an index of a parameter in the generic type parameter list by it's id.
@@ -89,14 +126,17 @@ pub fn param_idx(db: &dyn HirDatabase, id: TypeParamId) -> Option<usize> {
89 generics(db.upcast(), id.parent).param_idx(id) 126 generics(db.upcast(), id.parent).param_idx(id)
90} 127}
91 128
92pub fn wrap_empty_binders<T>(value: T) -> Binders<T> 129pub(crate) fn wrap_empty_binders<T>(value: T) -> Binders<T>
93where 130where
94 T: TypeWalk, 131 T: Fold<Interner, Result = T> + HasInterner<Interner = Interner>,
95{ 132{
96 Binders::empty(&Interner, value.shifted_in_from(DebruijnIndex::ONE)) 133 Binders::empty(&Interner, value.shifted_in_from(&Interner, DebruijnIndex::ONE))
97} 134}
98 135
99pub fn make_only_type_binders<T>(num_vars: usize, value: T) -> Binders<T> { 136pub(crate) fn make_only_type_binders<T: HasInterner<Interner = Interner>>(
137 num_vars: usize,
138 value: T,
139) -> Binders<T> {
100 Binders::new( 140 Binders::new(
101 VariableKinds::from_iter( 141 VariableKinds::from_iter(
102 &Interner, 142 &Interner,
@@ -108,7 +148,7 @@ pub fn make_only_type_binders<T>(num_vars: usize, value: T) -> Binders<T> {
108} 148}
109 149
110// FIXME: get rid of this 150// FIXME: get rid of this
111pub fn make_canonical<T>( 151pub fn make_canonical<T: HasInterner<Interner = Interner>>(
112 value: T, 152 value: T,
113 kinds: impl IntoIterator<Item = TyVariableKind>, 153 kinds: impl IntoIterator<Item = TyVariableKind>,
114) -> Canonical<T> { 154) -> Canonical<T> {
@@ -129,6 +169,8 @@ pub struct CallableSig {
129 is_varargs: bool, 169 is_varargs: bool,
130} 170}
131 171
172has_interner!(CallableSig);
173
132/// A polymorphic function signature. 174/// A polymorphic function signature.
133pub type PolyFnSig = Binders<CallableSig>; 175pub type PolyFnSig = Binders<CallableSig>;
134 176
@@ -144,10 +186,10 @@ impl CallableSig {
144 params_and_return: fn_ptr 186 params_and_return: fn_ptr
145 .substitution 187 .substitution
146 .clone() 188 .clone()
147 .shifted_out_to(DebruijnIndex::ONE) 189 .shifted_out_to(&Interner, DebruijnIndex::ONE)
148 .expect("unexpected lifetime vars in fn ptr") 190 .expect("unexpected lifetime vars in fn ptr")
149 .0 191 .0
150 .interned() 192 .as_slice(&Interner)
151 .iter() 193 .iter()
152 .map(|arg| arg.assert_ty_ref(&Interner).clone()) 194 .map(|arg| arg.assert_ty_ref(&Interner).clone())
153 .collect(), 195 .collect(),
@@ -164,7 +206,22 @@ impl CallableSig {
164 } 206 }
165} 207}
166 208
167impl Ty {} 209impl Fold<Interner> for CallableSig {
210 type Result = CallableSig;
211
212 fn fold_with<'i>(
213 self,
214 folder: &mut dyn chalk_ir::fold::Folder<'i, Interner>,
215 outer_binder: DebruijnIndex,
216 ) -> chalk_ir::Fallible<Self::Result>
217 where
218 Interner: 'i,
219 {
220 let vec = self.params_and_return.to_vec();
221 let folded = vec.fold_with(folder, outer_binder)?;
222 Ok(CallableSig { params_and_return: folded.into(), is_varargs: self.is_varargs })
223 }
224}
168 225
169#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] 226#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
170pub enum ImplTraitId { 227pub enum ImplTraitId {
@@ -177,70 +234,75 @@ pub struct ReturnTypeImplTraits {
177 pub(crate) impl_traits: Vec<ReturnTypeImplTrait>, 234 pub(crate) impl_traits: Vec<ReturnTypeImplTrait>,
178} 235}
179 236
237has_interner!(ReturnTypeImplTraits);
238
180#[derive(Clone, PartialEq, Eq, Debug, Hash)] 239#[derive(Clone, PartialEq, Eq, Debug, Hash)]
181pub(crate) struct ReturnTypeImplTrait { 240pub(crate) struct ReturnTypeImplTrait {
182 pub(crate) bounds: Binders<Vec<QuantifiedWhereClause>>, 241 pub(crate) bounds: Binders<Vec<QuantifiedWhereClause>>,
183} 242}
184 243
185pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId { 244pub fn static_lifetime() -> Lifetime {
186 chalk_ir::ForeignDefId(salsa::InternKey::as_intern_id(&id)) 245 LifetimeData::Static.intern(&Interner)
187}
188
189pub fn from_foreign_def_id(id: ForeignDefId) -> TypeAliasId {
190 salsa::InternKey::from_intern_id(id.0)
191}
192
193pub fn to_assoc_type_id(id: TypeAliasId) -> AssocTypeId {
194 chalk_ir::AssocTypeId(salsa::InternKey::as_intern_id(&id))
195}
196
197pub fn from_assoc_type_id(id: AssocTypeId) -> TypeAliasId {
198 salsa::InternKey::from_intern_id(id.0)
199}
200
201pub fn from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> TypeParamId {
202 assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
203 let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx));
204 db.lookup_intern_type_param_id(interned_id)
205} 246}
206 247
207pub fn to_placeholder_idx(db: &dyn HirDatabase, id: TypeParamId) -> PlaceholderIndex { 248pub fn dummy_usize_const() -> Const {
208 let interned_id = db.intern_type_param_id(id); 249 let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner);
209 PlaceholderIndex { 250 chalk_ir::ConstData {
210 ui: chalk_ir::UniverseIndex::ROOT, 251 ty: usize_ty,
211 idx: salsa::InternKey::as_intern_id(&interned_id).as_usize(), 252 value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { interned: () }),
212 } 253 }
254 .intern(&Interner)
213} 255}
214 256
215pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> LifetimeParamId { 257pub(crate) fn fold_free_vars<T: HasInterner<Interner = Interner> + Fold<Interner>>(
216 assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT); 258 t: T,
217 let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx)); 259 f: impl FnMut(BoundVar, DebruijnIndex) -> Ty,
218 db.lookup_intern_lifetime_param_id(interned_id) 260) -> T::Result {
219} 261 use chalk_ir::{fold::Folder, Fallible};
262 struct FreeVarFolder<F>(F);
263 impl<'i, F: FnMut(BoundVar, D