aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/hir/src/lib.rs21
-rw-r--r--crates/hir_def/src/attr.rs11
-rw-r--r--crates/hir_def/src/item_tree.rs35
-rw-r--r--crates/hir_def/src/item_tree/lower.rs56
-rw-r--r--crates/hir_def/src/item_tree/pretty.rs525
-rw-r--r--crates/hir_def/src/item_tree/tests.rs244
-rw-r--r--crates/hir_def/src/nameres/collector.rs314
-rw-r--r--crates/hir_def/src/nameres/tests/diagnostics.rs17
-rw-r--r--crates/hir_def/src/nameres/tests/macros.rs74
-rw-r--r--crates/hir_def/src/path.rs9
-rw-r--r--crates/hir_expand/src/name.rs2
-rw-r--r--crates/hir_ty/src/builder.rs16
-rw-r--r--crates/hir_ty/src/chalk_db.rs15
-rw-r--r--crates/hir_ty/src/chalk_ext.rs5
-rw-r--r--crates/hir_ty/src/db.rs10
-rw-r--r--crates/hir_ty/src/infer.rs192
-rw-r--r--crates/hir_ty/src/infer/coerce.rs480
-rw-r--r--crates/hir_ty/src/infer/expr.rs142
-rw-r--r--crates/hir_ty/src/infer/pat.rs19
-rw-r--r--crates/hir_ty/src/infer/path.rs6
-rw-r--r--crates/hir_ty/src/infer/unify.rs861
-rw-r--r--crates/hir_ty/src/interner.rs49
-rw-r--r--crates/hir_ty/src/lib.rs71
-rw-r--r--crates/hir_ty/src/lower.rs4
-rw-r--r--crates/hir_ty/src/method_resolution.rs47
-rw-r--r--crates/hir_ty/src/tests/coercion.rs56
-rw-r--r--crates/hir_ty/src/tests/patterns.rs2
-rw-r--r--crates/hir_ty/src/tests/regression.rs69
-rw-r--r--crates/hir_ty/src/tests/simple.rs36
-rw-r--r--crates/hir_ty/src/tests/traits.rs2
-rw-r--r--crates/hir_ty/src/tls.rs138
-rw-r--r--crates/hir_ty/src/traits.rs40
-rw-r--r--crates/ide/src/lib.rs5
-rw-r--r--crates/ide/src/view_item_tree.rs16
-rw-r--r--crates/ide_assists/src/handlers/auto_import.rs17
-rw-r--r--crates/ide_assists/src/handlers/merge_imports.rs14
-rw-r--r--crates/ide_assists/src/tests.rs8
-rw-r--r--crates/ide_completion/src/render.rs2
-rw-r--r--crates/ide_completion/src/test_utils.rs8
-rw-r--r--crates/ide_db/src/helpers/insert_use.rs105
-rw-r--r--crates/ide_db/src/helpers/insert_use/tests.rs141
-rw-r--r--crates/ide_db/src/helpers/merge_imports.rs21
-rw-r--r--crates/rust-analyzer/src/config.rs46
-rw-r--r--crates/rust-analyzer/src/handlers.rs10
-rw-r--r--crates/rust-analyzer/src/integrated_benchmarks.rs11
-rw-r--r--crates/rust-analyzer/src/lsp_ext.rs14
-rw-r--r--crates/rust-analyzer/src/main_loop.rs1
-rw-r--r--crates/rust-analyzer/src/to_proto.rs14
-rw-r--r--crates/stdx/src/lib.rs28
-rw-r--r--crates/syntax/src/ast/node_ext.rs23
50 files changed, 2773 insertions, 1279 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index d443b124c..52d72c3c5 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -1712,15 +1712,17 @@ impl Type {
1712 resolver: &Resolver, 1712 resolver: &Resolver,
1713 ty: Ty, 1713 ty: Ty,
1714 ) -> Type { 1714 ) -> Type {
1715 let environment = 1715 let environment = resolver
1716 resolver.generic_def().map_or_else(Default::default, |d| db.trait_environment(d)); 1716 .generic_def()
1717 .map_or_else(|| Arc::new(TraitEnvironment::empty(krate)), |d| db.trait_environment(d));
1717 Type { krate, env: environment, ty } 1718 Type { krate, env: environment, ty }
1718 } 1719 }
1719 1720
1720 fn new(db: &dyn HirDatabase, krate: CrateId, lexical_env: impl HasResolver, ty: Ty) -> Type { 1721 fn new(db: &dyn HirDatabase, krate: CrateId, lexical_env: impl HasResolver, ty: Ty) -> Type {
1721 let resolver = lexical_env.resolver(db.upcast()); 1722 let resolver = lexical_env.resolver(db.upcast());
1722 let environment = 1723 let environment = resolver
1723 resolver.generic_def().map_or_else(Default::default, |d| db.trait_environment(d)); 1724 .generic_def()
1725 .map_or_else(|| Arc::new(TraitEnvironment::empty(krate)), |d| db.trait_environment(d));
1724 Type { krate, env: environment, ty } 1726 Type { krate, env: environment, ty }
1725 } 1727 }
1726 1728
@@ -2051,11 +2053,7 @@ impl Type {
2051 name: Option<&Name>, 2053 name: Option<&Name>,
2052 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>, 2054 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
2053 ) -> Option<T> { 2055 ) -> Option<T> {
2054 // There should be no inference vars in types passed here 2056 let canonical = hir_ty::replace_errors_with_variables(self.ty.clone());
2055 // FIXME check that?
2056 // FIXME replace Unknown by bound vars here
2057 let canonical =
2058 Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(&Interner) };
2059 2057
2060 let env = self.env.clone(); 2058 let env = self.env.clone();
2061 let krate = krate.id; 2059 let krate = krate.id;
@@ -2223,8 +2221,9 @@ impl Type {
2223 walk_type(db, self, &mut cb); 2221 walk_type(db, self, &mut cb);
2224 } 2222 }
2225 2223
2226 pub fn could_unify_with(&self, other: &Type) -> bool { 2224 pub fn could_unify_with(&self, db: &dyn HirDatabase, other: &Type) -> bool {
2227 could_unify(&self.ty, &other.ty) 2225 let tys = hir_ty::replace_errors_with_variables((self.ty.clone(), other.ty.clone()));
2226 could_unify(db, self.env.clone(), &tys)
2228 } 2227 }
2229} 2228}
2230 2229
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index aadd4e44a..89a1ea770 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -2,7 +2,7 @@
2 2
3use std::{ 3use std::{
4 convert::{TryFrom, TryInto}, 4 convert::{TryFrom, TryInto},
5 ops, 5 fmt, ops,
6 sync::Arc, 6 sync::Arc,
7}; 7};
8 8
@@ -648,6 +648,15 @@ pub enum AttrInput {
648 TokenTree(Subtree), 648 TokenTree(Subtree),
649} 649}
650 650
651impl fmt::Display for AttrInput {
652 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
653 match self {
654 AttrInput::Literal(lit) => write!(f, " = \"{}\"", lit.escape_debug()),
655 AttrInput::TokenTree(subtree) => subtree.fmt(f),
656 }
657 }
658}
659
651impl Attr { 660impl Attr {
652 fn from_src( 661 fn from_src(
653 db: &dyn DefDatabase, 662 db: &dyn DefDatabase,
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index cad8a7479..528270d49 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -1,6 +1,9 @@
1//! A simplified AST that only contains items. 1//! A simplified AST that only contains items.
2 2
3mod lower; 3mod lower;
4mod pretty;
5#[cfg(test)]
6mod tests;
4 7
5use std::{ 8use std::{
6 any::type_name, 9 any::type_name,
@@ -132,6 +135,7 @@ impl ItemTree {
132 let ItemTreeData { 135 let ItemTreeData {
133 imports, 136 imports,
134 extern_crates, 137 extern_crates,
138 extern_blocks,
135 functions, 139 functions,
136 params, 140 params,
137 structs, 141 structs,
@@ -154,6 +158,7 @@ impl ItemTree {
154 158
155 imports.shrink_to_fit(); 159 imports.shrink_to_fit();
156 extern_crates.shrink_to_fit(); 160 extern_crates.shrink_to_fit();
161 extern_blocks.shrink_to_fit();
157 functions.shrink_to_fit(); 162 functions.shrink_to_fit();
158 params.shrink_to_fit(); 163 params.shrink_to_fit();
159 structs.shrink_to_fit(); 164 structs.shrink_to_fit();
@@ -203,6 +208,10 @@ impl ItemTree {
203 } 208 }
204 } 209 }
205 210
211 pub fn pretty_print(&self) -> String {
212 pretty::print_item_tree(self)
213 }
214
206 fn data(&self) -> &ItemTreeData { 215 fn data(&self) -> &ItemTreeData {
207 self.data.as_ref().expect("attempted to access data of empty ItemTree") 216 self.data.as_ref().expect("attempted to access data of empty ItemTree")
208 } 217 }
@@ -239,6 +248,7 @@ static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module(ModPath::from_kind(P
239struct ItemTreeData { 248struct ItemTreeData {
240 imports: Arena<Import>, 249 imports: Arena<Import>,
241 extern_crates: Arena<ExternCrate>, 250 extern_crates: Arena<ExternCrate>,
251 extern_blocks: Arena<ExternBlock>,
242 functions: Arena<Function>, 252 functions: Arena<Function>,
243 params: Arena<Param>, 253 params: Arena<Param>,
244 structs: Arena<Struct>, 254 structs: Arena<Struct>,
@@ -432,6 +442,7 @@ macro_rules! mod_items {
432mod_items! { 442mod_items! {
433 Import in imports -> ast::Use, 443 Import in imports -> ast::Use,
434 ExternCrate in extern_crates -> ast::ExternCrate, 444 ExternCrate in extern_crates -> ast::ExternCrate,
445 ExternBlock in extern_blocks -> ast::ExternBlock,
435 Function in functions -> ast::Fn, 446 Function in functions -> ast::Fn,
436 Struct in structs -> ast::Struct, 447 Struct in structs -> ast::Struct,
437 Union in unions -> ast::Union, 448 Union in unions -> ast::Union,
@@ -508,6 +519,13 @@ pub struct ExternCrate {
508} 519}
509 520
510#[derive(Debug, Clone, Eq, PartialEq)] 521#[derive(Debug, Clone, Eq, PartialEq)]
522pub struct ExternBlock {
523 pub abi: Option<Interned<str>>,
524 pub ast_id: FileAstId<ast::ExternBlock>,
525 pub children: Box<[ModItem]>,
526}
527
528#[derive(Debug, Clone, Eq, PartialEq)]
511pub struct Function { 529pub struct Function {
512 pub name: Name, 530 pub name: Name,
513 pub visibility: RawVisibilityId, 531 pub visibility: RawVisibilityId,
@@ -549,17 +567,6 @@ pub struct Struct {
549 pub generic_params: Interned<GenericParams>, 567 pub generic_params: Interned<GenericParams>,
550 pub fields: Fields, 568 pub fields: Fields,
551 pub ast_id: FileAstId<ast::Struct>, 569 pub ast_id: FileAstId<ast::Struct>,
552 pub kind: StructDefKind,
553}
554
555#[derive(Debug, Clone, Eq, PartialEq)]
556pub enum StructDefKind {
557 /// `struct S { ... }` - type namespace only.
558 Record,
559 /// `struct S(...);`
560 Tuple,
561 /// `struct S;`
562 Unit,
563} 570}
564 571
565#[derive(Debug, Clone, Eq, PartialEq)] 572#[derive(Debug, Clone, Eq, PartialEq)]
@@ -691,6 +698,7 @@ impl ModItem {
691 match self { 698 match self {
692 ModItem::Import(_) 699 ModItem::Import(_)
693 | ModItem::ExternCrate(_) 700 | ModItem::ExternCrate(_)
701 | ModItem::ExternBlock(_)
694 | ModItem::Struct(_) 702 | ModItem::Struct(_)
695 | ModItem::Union(_) 703 | ModItem::Union(_)
696 | ModItem::Enum(_) 704 | ModItem::Enum(_)
@@ -715,6 +723,7 @@ impl ModItem {
715 match self { 723 match self {
716 ModItem::Import(it) => tree[it.index].ast_id().upcast(), 724 ModItem::Import(it) => tree[it.index].ast_id().upcast(),
717 ModItem::ExternCrate(it) => tree[it.index].ast_id().upcast(), 725 ModItem::ExternCrate(it) => tree[it.index].ast_id().upcast(),
726 ModItem::ExternBlock(it) => tree[it.index].ast_id().upcast(),
718 ModItem::Function(it) => tree[it.index].ast_id().upcast(), 727 ModItem::Function(it) => tree[it.index].ast_id().upcast(),
719 ModItem::Struct(it) => tree[it.index].ast_id().upcast(), 728 ModItem::Struct(it) => tree[it.index].ast_id().upcast(),
720 ModItem::Union(it) => tree[it.index].ast_id().upcast(), 729 ModItem::Union(it) => tree[it.index].ast_id().upcast(),
@@ -774,6 +783,10 @@ impl<T> IdRange<T> {
774 fn new(range: Range<Idx<T>>) -> Self { 783 fn new(range: Range<Idx<T>>) -> Self {
775 Self { range: range.start.into_raw().into()..range.end.into_raw().into(), _p: PhantomData } 784 Self { range: range.start.into_raw().into()..range.end.into_raw().into(), _p: PhantomData }
776 } 785 }
786
787 fn is_empty(&self) -> bool {
788 self.range.is_empty()
789 }
777} 790}
778 791
779impl<T> Iterator for IdRange<T> { 792impl<T> Iterator for IdRange<T> {
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index fe348091d..91cf75371 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -147,9 +147,7 @@ impl<'a> Ctx<'a> {
147 ast::Item::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into), 147 ast::Item::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into),
148 ast::Item::MacroRules(ast) => self.lower_macro_rules(ast).map(Into::into), 148 ast::Item::MacroRules(ast) => self.lower_macro_rules(ast).map(Into::into),
149 ast::Item::MacroDef(ast) => self.lower_macro_def(ast).map(Into::into), 149 ast::Item::MacroDef(ast) => self.lower_macro_def(ast).map(Into::into),
150 ast::Item::ExternBlock(ast) => { 150 ast::Item::ExternBlock(ast) => Some(self.lower_extern_block(ast).into()),
151 Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>()))
152 }
153 }; 151 };
154 152
155 if !attrs.is_empty() { 153 if !attrs.is_empty() {
@@ -230,12 +228,7 @@ impl<'a> Ctx<'a> {
230 let generic_params = self.lower_generic_params(GenericsOwner::Struct, strukt); 228 let generic_params = self.lower_generic_params(GenericsOwner::Struct, strukt);
231 let fields = self.lower_fields(&strukt.kind()); 229 let fields = self.lower_fields(&strukt.kind());
232 let ast_id = self.source_ast_id_map.ast_id(strukt); 230 let ast_id = self.source_ast_id_map.ast_id(strukt);
233 let kind = match strukt.kind() { 231 let res = Struct { name, visibility, generic_params, fields, ast_id };
234 ast::StructKind::Record(_) => StructDefKind::Record,
235 ast::StructKind::Tuple(_) => StructDefKind::Tuple,
236 ast::StructKind::Unit => StructDefKind::Unit,
237 };
238 let res = Struct { name, visibility, generic_params, fields, ast_id, kind };
239 Some(id(self.data().structs.alloc(res))) 232 Some(id(self.data().structs.alloc(res)))
240 } 233 }
241 234
@@ -397,19 +390,7 @@ impl<'a> Ctx<'a> {
397 ret_type 390 ret_type
398 }; 391 };
399 392
400 let abi = func.abi().map(|abi| { 393 let abi = func.abi().map(lower_abi);
401 // FIXME: Abi::abi() -> Option<SyntaxToken>?
402 match abi.syntax().last_token() {
403 Some(tok) if tok.kind() == SyntaxKind::STRING => {
404 // FIXME: Better way to unescape?
405 Interned::new_str(tok.text().trim_matches('"'))
406 }
407 _ => {
408 // `extern` default to be `extern "C"`.
409 Interned::new_str("C")
410 }
411 }
412 });
413 394
414 let ast_id = self.source_ast_id_map.ast_id(func); 395 let ast_id = self.source_ast_id_map.ast_id(func);
415 396
@@ -647,8 +628,10 @@ impl<'a> Ctx<'a> {
647 Some(id(self.data().macro_defs.alloc(res))) 628 Some(id(self.data().macro_defs.alloc(res)))
648 } 629 }
649 630
650 fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> { 631 fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> FileItemTreeId<ExternBlock> {
651 block.extern_item_list().map_or(Vec::new(), |list| { 632 let ast_id = self.source_ast_id_map.ast_id(block);
633 let abi = block.abi().map(lower_abi);
634 let children: Box<[_]> = block.extern_item_list().map_or(Box::new([]), |list| {
652 list.extern_items() 635 list.extern_items()
653 .filter_map(|item| { 636 .filter_map(|item| {
654 self.collect_inner_items(item.syntax()); 637 self.collect_inner_items(item.syntax());
@@ -673,13 +656,20 @@ impl<'a> Ctx<'a> {
673 self.data().type_aliases[foreign_ty.index].is_extern = true; 656 self.data().type_aliases[foreign_ty.index].is_extern = true;
674 foreign_ty.into() 657 foreign_ty.into()
675 } 658 }
676 ast::ExternItem::MacroCall(_) => return None, 659 ast::ExternItem::MacroCall(call) => {
660 // FIXME: we need some way of tracking that the macro call is in an
661 // extern block
662 self.lower_macro_call(&call)?.into()
663 }
677 }; 664 };
678 self.add_attrs(id.into(), attrs); 665 self.add_attrs(id.into(), attrs);
679 Some(id) 666 Some(id)
680 }) 667 })
681 .collect() 668 .collect()
682 }) 669 });
670
671 let res = ExternBlock { abi, ast_id, children };
672 id(self.data().extern_blocks.alloc(res))
683 } 673 }
684 674
685 /// Lowers generics defined on `node` and collects inner items defined within. 675 /// Lowers generics defined on `node` and collects inner items defined within.
@@ -879,3 +869,17 @@ fn is_intrinsic_fn_unsafe(name: &Name) -> bool {
879 ] 869 ]
880 .contains(&name) 870 .contains(&name)
881} 871}
872
873fn lower_abi(abi: ast::Abi) -> Interned<str> {
874 // FIXME: Abi::abi() -> Option<SyntaxToken>?
875 match abi.syntax().last_token() {
876 Some(tok) if tok.kind() == SyntaxKind::STRING => {
877 // FIXME: Better way to unescape?
878 Interned::new_str(tok.text().trim_matches('"'))
879 }
880 _ => {
881 // `extern` default to be `extern "C"`.
882 Interned::new_str("C")
883 }
884 }
885}
diff --git a/crates/hir_def/src/item_tree/pretty.rs b/crates/hir_def/src/item_tree/pretty.rs
new file mode 100644
index 000000000..5ec02d1be
--- /dev/null
+++ b/crates/hir_def/src/item_tree/pretty.rs
@@ -0,0 +1,525 @@
1//! `ItemTree` debug printer.
2
3use std::fmt::{self, Write};
4
5use crate::{attr::RawAttrs, visibility::RawVisibility};
6
7use super::*;
8
9pub(super) fn print_item_tree(tree: &ItemTree) -> String {
10 let mut p = Printer { tree, buf: String::new(), indent_level: 0, needs_indent: true };
11
12 if let Some(attrs) = tree.attrs.get(&AttrOwner::TopLevel) {
13 p.print_attrs(attrs, true);
14 }
15 p.blank();
16
17 for item in tree.top_level_items() {
18 p.print_mod_item(*item);
19 }
20
21 let mut s = p.buf.trim_end_matches('\n').to_string();
22 s.push('\n');
23 s
24}
25
26macro_rules! w {
27 ($dst:expr, $($arg:tt)*) => {
28 drop(write!($dst, $($arg)*))
29 };
30}
31
32macro_rules! wln {
33 ($dst:expr) => {
34 drop(writeln!($dst))
35 };
36 ($dst:expr, $($arg:tt)*) => {
37 drop(writeln!($dst, $($arg)*))
38 };
39}
40
41struct Printer<'a> {
42 tree: &'a ItemTree,
43 buf: String,
44 indent_level: usize,
45 needs_indent: bool,
46}
47
48impl<'a> Printer<'a> {
49 fn indented(&mut self, f: impl FnOnce(&mut Self)) {
50 self.indent_level += 1;
51 wln!(self);
52 f(self);
53 self.indent_level -= 1;
54 self.buf = self.buf.trim_end_matches('\n').to_string();
55 }
56
57 /// Ensures that a blank line is output before the next text.
58 fn blank(&mut self) {
59 let mut iter = self.buf.chars().rev().fuse();
60 match (iter.next(), iter.next()) {
61 (Some('\n'), Some('\n')) | (Some('\n'), None) | (None, None) => {}
62 (Some('\n'), Some(_)) => {
63 self.buf.push('\n');
64 }
65 (Some(_), _) => {
66 self.buf.push('\n');
67 self.buf.push('\n');
68 }
69 (None, Some(_)) => unreachable!(),
70 }
71 }
72
73 fn print_attrs(&mut self, attrs: &RawAttrs, inner: bool) {
74 let inner = if inner { "!" } else { "" };
75 for attr in &**attrs {
76 wln!(
77 self,
78 "#{}[{}{}] // {:?}",
79 inner,
80 attr.path,
81 attr.input.as_ref().map(|it| it.to_string()).unwrap_or_default(),
82 attr.id,
83 );
84 }
85 }
86
87 fn print_attrs_of(&mut self, of: impl Into<AttrOwner>) {
88 if let Some(attrs) = self.tree.attrs.get(&of.into()) {
89 self.print_attrs(attrs, false);
90 }
91 }
92
93 fn print_visibility(&mut self, vis: RawVisibilityId) {
94 match &self.tree[vis] {
95 RawVisibility::Module(path) => w!(self, "pub({}) ", path),
96 RawVisibility::Public => w!(self, "pub "),
97 };
98 }
99
100 fn print_fields(&mut self, fields: &Fields) {
101 match fields {
102 Fields::Record(fields) => {
103 w!(self, " {{");
104 self.indented(|this| {
105 for field in fields.clone() {
106 let Field { visibility, name, type_ref } = &this.tree[field];
107 this.print_attrs_of(field);
108 this.print_visibility(*visibility);
109 w!(this, "{}: ", name);
110 this.print_type_ref(type_ref);
111 wln!(this, ",");
112 }
113 });
114 w!(self, "}}");
115 }
116 Fields::Tuple(fields) => {
117 w!(self, "(");
118 self.indented(|this| {
119 for field in fields.clone() {
120 let Field { visibility, name, type_ref } = &this.tree[field];
121 this.print_attrs_of(field);
122 this.print_visibility(*visibility);
123 w!(this, "{}: ", name);
124 this.print_type_ref(type_ref);
125 wln!(this, ",");
126 }
127 });
128 w!(self, ")");
129 }
130 Fields::Unit => {}
131 }
132 }
133
134 fn print_mod_item(&mut self, item: ModItem) {
135 self.print_attrs_of(item);
136
137 match item {
138 ModItem::Import(it) => {
139 let Import { visibility, path, is_glob, alias, ast_id: _, index } = &self.tree[it];
140 self.print_visibility(*visibility);
141 w!(self, "use {}", path);
142 if *is_glob {
143 w!(self, "::*");
144 }
145 if let Some(alias) = alias {
146 w!(self, " as {}", alias);
147 }
148 wln!(self, "; // {}", index);
149 }
150 ModItem::ExternCrate(it) => {
151 let ExternCrate { name, alias, visibility, ast_id: _ } = &self.tree[it];
152 self.print_visibility(*visibility);
153 w!(self, "extern crate {}", name);
154 if let Some(alias) = alias {
155 w!(self, " as {}", alias);
156 }
157 wln!(self, ";");
158 }
159 ModItem::ExternBlock(it) => {
160 let ExternBlock { abi, ast_id: _, children } = &self.tree[it];
161 w!(self, "extern ");
162 if let Some(abi) = abi {
163 w!(self, "\"{}\" ", abi);
164 }
165 w!(self, "{{");
166 self.indented(|this| {
167 for child in &**children {
168 this.print_mod_item(*child);
169 }
170 });
171 wln!(self, "}}");
172 }
173 ModItem::Function(it) => {
174 let Function {
175 name,
176 visibility,
177 generic_params: _, // FIXME print these somehow
178 abi,
179 params,
180 ret_type,
181 ast_id: _,
182 flags,
183 } = &self.tree[it];
184 if flags.bits != 0 {
185 wln!(self, "// flags = 0x{:X}", flags.bits);
186 }
187 self.print_visibility(*visibility);
188 if let Some(abi) = abi {
189 w!(self, "extern \"{}\" ", abi);
190 }
191 w!(self, "fn {}(", name);
192 if !params.is_empty() {
193 self.indented(|this| {
194 for param in params.clone() {
195 this.print_attrs_of(param);
196 match &this.tree[param] {
197 Param::Normal(ty) => {
198 w!(this, "_: ");
199 this.print_type_ref(ty);
200 wln!(this, ",");
201 }
202 Param::Varargs => {
203 wln!(this, "...");
204 }
205 };
206 }
207 });
208 }
209 w!(self, ") -> ");
210 self.print_type_ref(ret_type);
211 wln!(self, ";");
212 }
213 ModItem::Struct(it) => {
214 let Struct { visibility, name, fields, generic_params: _, ast_id: _ } =
215 &self.tree[it];
216 self.print_visibility(*visibility);
217 w!(self, "struct {}", name);
218 self.print_fields(fields);
219 if matches!(fields, Fields::Record(_)) {
220 wln!(self);
221 } else {
222 wln!(self, ";");
223 }
224 }
225 ModItem::Union(it) => {
226 let Union { name, visibility, fields, generic_params: _, ast_id: _ } =
227 &self.tree[it];
228 self.print_visibility(*visibility);
229 w!(self, "union {}", name);
230 self.print_fields(fields);
231 if matches!(fields, Fields::Record(_)) {
232 wln!(self);
233 } else {
234 wln!(self, ";");
235 }
236 }
237 ModItem::Enum(it) => {
238 let Enum { name, visibility, variants, generic_params: _, ast_id: _ } =
239 &self.tree[it];
240 self.print_visibility(*visibility);
241 w!(self, "enum {} {{", name);
242 self.indented(|this| {
243 for variant in variants.clone() {
244 let Variant { name, fields } = &this.tree[variant];
245 this.print_attrs_of(variant);
246 w!(this, "{}", name);
247 this.print_fields(fields);
248 wln!(this, ",");
249 }
250 });
251 wln!(self, "}}");
252 }
253 ModItem::Const(it) => {
254 let Const { name, visibility, type_ref, ast_id: _ } = &self.tree[it];
255 self.print_visibility(*visibility);
256 w!(self, "const ");
257 match name {
258 Some(name) => w!(self, "{}", name),
259 None => w!(self, "_"),
260 }
261 w!(self, ": ");
262 self.print_type_ref(type_ref);
263 wln!(self, " = _;");
264 }
265 ModItem::Static(it) => {
266 let Static { name, visibility, mutable, is_extern, type_ref, ast_id: _ } =
267 &self.tree[it];
268 self.print_visibility(*visibility);
269 w!(self, "static ");
270 if *mutable {
271 w!(self, "mut ");
272 }
273 w!(self, "{}: ", name);
274 self.print_type_ref(type_ref);
275 w!(self, " = _;");
276 if *is_extern {
277 w!(self, " // extern");
278 }
279 wln!(self);
280 }
281 ModItem::Trait(it) => {
282 let Trait {
283 name,
284 visibility,
285 is_auto,
286 is_unsafe,
287 bounds,
288 items,
289 generic_params: _,
290 ast_id: _,
291 } = &self.tree[it];
292 self.print_visibility(*visibility);
293 if *is_unsafe {
294 w!(self, "unsafe ");
295 }
296 if *is_auto {
297 w!(self, "auto ");
298 }
299 w!(self, "trait {}", name);
300 if !bounds.is_empty() {
301 w!(self, ": ");
302 self.print_type_bounds(bounds);
303 }
304 w!(self, " {{");
305 self.indented(|this| {
306 for item in &**items {
307 this.print_mod_item((*item).into());
308 }
309 });
310 wln!(self, "}}");
311 }
312 ModItem::Impl(it) => {
313 let Impl {
314 target_trait,
315 self_ty,
316 is_negative,
317 items,
318 generic_params: _,
319 ast_id: _,
320 } = &self.tree[it];
321 w!(self, "impl ");
322 if *is_negative {
323 w!(self, "!");
324 }
325 if let Some(tr) = target_trait {
326 self.print_path(&tr.path);
327 w!(self, " for ");
328 }
329 self.print_type_ref(self_ty);
330 w!(self, " {{");
331 self.indented(|this| {
332 for item in &**items {
333 this.print_mod_item((*item).into());
334 }
335 });
336 wln!(self, "}}");
337 }
338 ModItem::TypeAlias(it) => {
339 let TypeAlias {
340 name,
341 visibility,
342 bounds,
343 type_ref,
344 is_extern,
345 generic_params: _,
346 ast_id: _,
347 } = &self.tree[it];
348 self.print_visibility(*visibility);
349 w!(self, "type {}", name);
350 if !bounds.is_empty() {
351 w!(self, ": ");
352 self.print_type_bounds(bounds);
353 }
354 if let Some(ty) = type_ref {
355 w!(self, " = ");
356 self.print_type_ref(ty);
357 }
358 w!(self, ";");
359 if *is_extern {
360 w!(self, " // extern");
361 }
362 wln!(self);
363 }
364 ModItem::Mod(it) => {
365 let Mod { name, visibility, kind, ast_id: _ } = &self.tree[it];
366 self.print_visibility(*visibility);
367 w!(self, "mod {}", name);
368 match kind {
369 ModKind::Inline { items } => {
370 w!(self, " {{");
371 self.indented(|this| {
372 for item in &**items {
373 this.print_mod_item((*item).into());
374 }
375 });
376 wln!(self, "}}");
377 }
378 ModKind::Outline {} => {
379 wln!(self, ";");
380 }
381 }
382 }
383 ModItem::MacroCall(it) => {
384 let MacroCall { path, ast_id: _, fragment: _ } = &self.tree[it];
385 wln!(self, "{}!(...);", path);
386 }
387 ModItem::MacroRules(it) => {
388 let MacroRules { name, ast_id: _ } = &self.tree[it];
389 wln!(self, "macro_rules! {} {{ ... }}", name);
390 }
391 ModItem::MacroDef(it) => {
392 let MacroDef { name, visibility, ast_id: _ } = &self.tree[it];
393 self.print_visibility(*visibility);
394 wln!(self, "macro {} {{ ... }}", name);
395 }
396 }
397
398 self.blank();
399 }
400
401 fn print_type_ref(&mut self, type_ref: &TypeRef) {
402 // FIXME: deduplicate with `HirDisplay` impl
403 match type_ref {
404 TypeRef::Never => w!(self, "!"),
405 TypeRef::Placeholder => w!(self, "_"),
406 TypeRef::Tuple(fields) => {
407 w!(self, "(");
408 for (i, field) in fields.iter().enumerate() {
409 if i != 0 {
410 w!(self, ", ");
411 }
412 self.print_type_ref(field);
413 }
414 w!(self, ")");
415 }
416 TypeRef::Path(path) => self.print_path(path),
417 TypeRef::RawPtr(pointee, mtbl) => {
418 let mtbl = match mtbl {
419 Mutability::Shared => "*const",
420 Mutability::Mut => "*mut",
421 };
422 w!(self, "{} ", mtbl);
423 self.print_type_ref(pointee);
424 }
425 TypeRef::Reference(pointee, lt, mtbl) => {
426 let mtbl = match mtbl {
427 Mutability::Shared => "",
428 Mutability::Mut => "mut ",
429 };
430 w!(self, "&");
431 if let Some(lt) = lt {
432 w!(self, "{} ", lt.name);
433 }
434 w!(self, "{}", mtbl);
435 self.print_type_ref(pointee);
436 }
437 TypeRef::Array(elem, len) => {
438 w!(self, "[");
439 self.print_type_ref(elem);
440 w!(self, "; {}]", len);
441 }
442 TypeRef::Slice(elem) => {
443 w!(self, "[");
444 self.print_type_ref(elem);
445 w!(self, "]");
446 }
447 TypeRef::Fn(args_and_ret, varargs) => {
448 let (ret, args) =
449 args_and_ret.split_last().expect("TypeRef::Fn is missing return type");
450 w!(self, "fn(");
451 for (i, arg) in args.iter().enumerate() {
452 if i != 0 {
453 w!(self, ", ");
454 }
455 self.print_type_ref(arg);
456 }
457 if *varargs {
458 if !args.is_empty() {
459 w!(self, ", ");
460 }
461 w!(self, "...");
462 }
463 w!(self, ") -> ");
464 self.print_type_ref(ret);
465 }
466 TypeRef::Macro(_ast_id) => {
467 w!(self, "<macro>");
468 }
469 TypeRef::Error => drop(write!(self, "{{unknown}}")),
470 TypeRef::ImplTrait(bounds) => {
471 w!(self, "impl ");
472 self.print_type_bounds(bounds);
473 }
474 TypeRef::DynTrait(bounds) => {
475 w!(self, "dyn ");
476 self.print_type_bounds(bounds);
477 }
478 }
479 }
480
481 fn print_type_bounds(&mut self, bounds: &[TypeBound]) {
482 for (i, bound) in bounds.iter().enumerate() {
483 if i != 0 {
484 w!(self, " + ");
485 }
486
487 match bound {
488 TypeBound::Path(path) => self.print_path(path),
489 TypeBound::Lifetime(lt) => w!(self, "{}", lt.name),
490 TypeBound::Error => w!(self, "{{unknown}}"),
491 }
492 }
493 }
494
495 fn print_path(&mut self, path: &Path) {
496 if path.type_anchor().is_none()
497 && path.segments().iter().all(|seg| seg.args_and_bindings.is_none())
498 {
499 w!(self, "{}", path.mod_path());
500 } else {
501 // too complicated, just use `Debug`
502 w!(self, "{:?}", path);
503 }
504 }
505}
506
507impl<'a> Write for Printer<'a> {
508 fn write_str(&mut self, s: &str) -> fmt::Result {
509 for line in s.split_inclusive('\n') {
510 if self.needs_indent {
511 match self.buf.chars().last() {
512 Some('\n') | None => {}
513 _ => self.buf.push('\n'),
514 }
515 self.buf.push_str(&" ".repeat(self.indent_level));
516 self.needs_indent = false;
517 }
518
519 self.buf.push_str(line);
520 self.needs_indent = line.ends_with('\n');
521 }
522
523 Ok(())
524 }
525}
diff --git a/crates/hir_def/src/item_tree/tests.rs b/crates/hir_def/src/item_tree/tests.rs
new file mode 100644
index 000000000..100ae9b97
--- /dev/null
+++ b/crates/hir_def/src/item_tree/tests.rs
@@ -0,0 +1,244 @@
1use base_db::fixture::WithFixture;
2use expect_test::{expect, Expect};
3
4use crate::{db::DefDatabase, test_db::TestDB};
5
6fn check(ra_fixture: &str, expect: Expect) {
7 let (db, file_id) = TestDB::with_single_file(ra_fixture);
8 let item_tree = db.file_item_tree(file_id.into());
9 let pretty = item_tree.pretty_print();
10 expect.assert_eq(&pretty);
11}
12
13#[test]
14fn imports() {
15 check(
16 r#"
17//! file comment
18#![no_std]
19//! another file comment
20
21extern crate self as renamed;
22pub(super) extern crate bli;
23
24pub use crate::path::{nested, items as renamed, Trait as _};
25use globs::*;
26
27/// docs on import
28use crate::{A, B};
29 "#,
30 expect![[r##"
31 #![doc = " file comment"] // AttrId { is_doc_comment: true, ast_index: 0 }
32 #![no_std] // AttrId { is_doc_comment: false, ast_index: 0 }
33 #![doc = " another file comment"] // AttrId { is_doc_comment: true, ast_index: 1 }
34
35 pub(self) extern crate self as renamed;
36
37 pub(super) extern crate bli;
38
39 pub use crate::path::nested; // 0
40
41 pub use crate::path::items as renamed; // 1
42
43 pub use crate::path::Trait as _; // 2
44
45 pub(self) use globs::*; // 0
46
47 #[doc = " docs on import"] // AttrId { is_doc_comment: true, ast_index: 0 }
48 pub(self) use crate::A; // 0
49
50 #[doc = " docs on import"] // AttrId { is_doc_comment: true, ast_index: 0 }
51 pub(self) use crate::B; // 1
52 "##]],
53 );
54}
55
56#[test]
57fn extern_blocks() {
58 check(
59 r#"
60#[on_extern_block]
61extern "C" {
62 #[on_extern_type]
63 type ExType;
64
65 #[on_extern_static]
66 static EX_STATIC: u8;
67
68 #[on_extern_fn]
69 fn ex_fn();
70}
71 "#,
72 expect![[r##"
73 #[on_extern_block] // AttrId { is_doc_comment: false, ast_index: 0 }
74 extern "C" {
75 #[on_extern_type] // AttrId { is_doc_comment: false, ast_index: 0 }
76 pub(self) type ExType; // extern
77
78 #[on_extern_static] // AttrId { is_doc_comment: false, ast_index: 0 }
79 pub(self) static EX_STATIC: u8 = _; // extern
80
81 #[on_extern_fn] // AttrId { is_doc_comment: false, ast_index: 0 }
82 // flags = 0x60
83 pub(self) fn ex_fn() -> ();
84 }
85 "##]],
86 );
87}
88
89#[test]
90fn adts() {
91 check(
92 r#"
93struct Unit;
94
95#[derive(Debug)]
96struct Struct {
97 /// fld docs
98 fld: (),
99}
100
101struct Tuple(#[attr] u8);
102
103union Ize {
104 a: (),
105 b: (),
106}
107
108enum E {
109 /// comment on Unit
110 Unit,
111 /// comment on Tuple
112 Tuple(u8),
113 Struct {
114 /// comment on a: u8
115 a: u8,
116 }
117}
118 "#,
119 expect![[r##"
120 pub(self) struct Unit;
121
122 #[derive(Debug)] // AttrId { is_doc_comment: false, ast_index: 0 }
123 pub(self) struct Struct {
124 #[doc = " fld docs"] // AttrId { is_doc_comment: true, ast_index: 0 }
125 pub(self) fld: (),
126 }
127
128 pub(self) struct Tuple(
129 #[attr] // AttrId { is_doc_comment: false, ast_index: 0 }
130 pub(self) 0: u8,
131 );
132
133 pub(self) union Ize {
134 pub(self) a: (),
135 pub(self) b: (),
136 }
137
138 pub(self) enum E {
139 #[doc = " comment on Unit"] // AttrId { is_doc_comment: true, ast_index: 0 }
140 Unit,
141 #[doc = " comment on Tuple"] // AttrId { is_doc_comment: true, ast_index: 0 }
142 Tuple(
143 pub(self) 0: u8,
144 ),
145 Struct {
146 #[doc = " comment on a: u8"] // AttrId { is_doc_comment: true, ast_index: 0 }
147 pub(self) a: u8,
148 },
149 }
150 "##]],
151 );
152}
153
154#[test]
155fn misc() {
156 check(
157 r#"
158pub static mut ST: () = ();
159
160const _: Anon = ();
161
162#[attr]
163fn f(#[attr] arg: u8, _: ()) {
164 #![inner_attr_in_fn]
165}
166
167trait Tr: SuperTrait + 'lifetime {
168 type Assoc: AssocBound = Default;
169 fn method(&self);
170}
171 "#,
172 expect![[r##"
173 pub static mut ST: () = _;
174
175 pub(self) const _: Anon = _;
176
177 #[attr] // AttrId { is_doc_comment: false, ast_index: 0 }
178 #[inner_attr_in_fn] // AttrId { is_doc_comment: false, ast_index: 1 }
179 // flags = 0x2
180 pub(self) fn f(
181 #[attr] // AttrId { is_doc_comment: false, ast_index: 0 }
182 _: u8,
183 _: (),
184 ) -> ();
185
186 pub(self) trait Tr: SuperTrait + 'lifetime {
187 pub(self) type Assoc: AssocBound = Default;
188
189 // flags = 0x1
190 pub(self) fn method(
191 _: &Self,
192 ) -> ();
193 }
194 "##]],
195 );
196}
197
198#[test]
199fn modules() {
200 check(
201 r#"
202/// outer
203mod inline {
204 //! inner
205
206 use super::*;
207
208 fn fn_in_module() {}
209}
210 "#,
211 expect![[r##"
212 #[doc = " outer"] // AttrId { is_doc_comment: true, ast_index: 0 }
213 #[doc = " inner"] // AttrId { is_doc_comment: true, ast_index: 1 }
214 pub(self) mod inline {
215 pub(self) use super::*; // 0
216
217 // flags = 0x2
218 pub(self) fn fn_in_module() -> ();
219 }
220 "##]],
221 );
222}
223
224#[test]
225fn macros() {
226 check(
227 r#"
228macro_rules! m {
229 () => {};
230}
231
232pub macro m2() {}
233
234m!();
235 "#,
236 expect![[r#"
237 macro_rules! m { ... }
238
239 pub macro m2 { ... }
240
241 m!(...);
242 "#]],
243 );
244}
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 3896be25d..014ea4de4 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -16,19 +16,20 @@ use hir_expand::{
16 FragmentKind, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, 16 FragmentKind, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
17}; 17};
18use hir_expand::{InFile, MacroCallLoc}; 18use hir_expand::{InFile, MacroCallLoc};
19use itertools::Itertools;
19use rustc_hash::{FxHashMap, FxHashSet}; 20use rustc_hash::{FxHashMap, FxHashSet};
20use syntax::ast; 21use syntax::ast;
21 22
22use crate::{ 23use crate::{
23 attr::{AttrId, Attrs}, 24 attr::{Attr, AttrId, AttrInput, Attrs},
24 builtin_attr, 25 builtin_attr,
25 db::DefDatabase, 26 db::DefDatabase,
26 derive_macro_as_call_id, 27 derive_macro_as_call_id,
27 intern::Interned, 28 intern::Interned,
28 item_scope::{ImportType, PerNsGlobImports}, 29 item_scope::{ImportType, PerNsGlobImports},
29 item_tree::{ 30 item_tree::{
30 self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroDef, MacroRules, Mod, ModItem, 31 self, Fields, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroDef, MacroRules, Mod,
31 ModKind, StructDefKind, 32 ModItem, ModKind,
32 }, 33 },
33 macro_call_as_call_id, 34 macro_call_as_call_id,
34 nameres::{ 35 nameres::{
@@ -94,14 +95,16 @@ pub(super) fn collect_defs(
94 unresolved_imports: Vec::new(), 95 unresolved_imports: Vec::new(),
95 resolved_imports: Vec::new(), 96 resolved_imports: Vec::new(),
96 97
97 unexpanded_macros: Vec::new(), 98 unresolved_macros: Vec::new(),
98 mod_dirs: FxHashMap::default(), 99 mod_dirs: FxHashMap::default(),
99 cfg_options, 100 cfg_options,
100 proc_macros, 101 proc_macros,
101 exports_proc_macros: false, 102 exports_proc_macros: false,
102 from_glob_import: Default::default(), 103 from_glob_import: Default::default(),
103 ignore_attrs_on: FxHashSet::default(), 104 skip_attrs: Default::default(),
104 derive_helpers_in_scope: FxHashMap::default(), 105 derive_helpers_in_scope: Default::default(),
106 registered_attrs: Default::default(),
107 registered_tools: Default::default(),
105 }; 108 };
106 match block { 109 match block {
107 Some(block) => { 110 Some(block) => {
@@ -237,7 +240,7 @@ struct DefCollector<'a> {
237 glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility)>>, 240 glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility)>>,
238 unresolved_imports: Vec<ImportDirective>, 241 unresolved_imports: Vec<ImportDirective>,
239 resolved_imports: Vec<ImportDirective>, 242 resolved_imports: Vec<ImportDirective>,
240 unexpanded_macros: Vec<MacroDirective>, 243 unresolved_macros: Vec<MacroDirective>,
241 mod_dirs: FxHashMap<LocalModuleId, ModDir>, 244 mod_dirs: FxHashMap<LocalModuleId, ModDir>,
242 cfg_options: &'a CfgOptions, 245 cfg_options: &'a CfgOptions,
243 /// List of procedural macros defined by this crate. This is read from the dynamic library 246 /// List of procedural macros defined by this crate. This is read from the dynamic library
@@ -247,10 +250,20 @@ struct DefCollector<'a> {
247 proc_macros: Vec<(Name, ProcMacroExpander)>, 250 proc_macros: Vec<(Name, ProcMacroExpander)>,
248 exports_proc_macros: bool, 251 exports_proc_macros: bool,
249 from_glob_import: PerNsGlobImports, 252 from_glob_import: PerNsGlobImports,
250 ignore_attrs_on: FxHashSet<InFile<ModItem>>, 253 /// If we fail to resolve an attribute on a `ModItem`, we fall back to ignoring the attribute.
254 /// This map is used to skip all attributes up to and including the one that failed to resolve,
255 /// in order to not expand them twice.
256 ///
257 /// This also stores the attributes to skip when we resolve derive helpers and non-macro
258 /// non-builtin attributes in general.
259 skip_attrs: FxHashMap<InFile<ModItem>, AttrId>,
251 /// Tracks which custom derives are in scope for an item, to allow resolution of derive helper 260 /// Tracks which custom derives are in scope for an item, to allow resolution of derive helper
252 /// attributes. 261 /// attributes.
253 derive_helpers_in_scope: FxHashMap<AstId<ast::Item>, Vec<Name>>, 262 derive_helpers_in_scope: FxHashMap<AstId<ast::Item>, Vec<Name>>,
263 /// Custom attributes registered with `#![register_attr]`.
264 registered_attrs: Vec<String>,
265 /// Custom tool modules registered with `#![register_tool]`.
266 registered_tools: Vec<String>,
254} 267}
255 268
256impl DefCollector<'_> { 269impl DefCollector<'_> {
@@ -259,11 +272,39 @@ impl DefCollector<'_> {
259 let item_tree = self.db.file_item_tree(file_id.into()); 272 let item_tree = self.db.file_item_tree(file_id.into());
260 let module_id = self.def_map.root; 273 let module_id = self.def_map.root;
261 self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id }; 274 self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id };
262 if item_tree 275
263 .top_level_attrs(self.db, self.def_map.krate) 276 let attrs = item_tree.top_level_attrs(self.db, self.def_map.krate);
264 .cfg() 277 if attrs.cfg().map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false)) {
265 .map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false)) 278 // Process other crate-level attributes.
266 { 279 for attr in &*attrs {
280 let attr_name = match attr.path.as_ident() {
281 Some(name) => name,
282 None => continue,
283 };
284
285 let registered_name = if *attr_name == hir_expand::name![register_attr]
286 || *attr_name == hir_expand::name![register_tool]
287 {
288 match &attr.input {
289 Some(AttrInput::TokenTree(subtree)) => match &*subtree.token_trees {
290 [tt::TokenTree::Leaf(tt::Leaf::Ident(name))] => name.as_name(),
291 _ => continue,
292 },
293 _ => continue,
294 }
295 } else {
296 continue;
297 };
298
299 if *attr_name == hir_expand::name![register_attr] {
300 self.registered_attrs.push(registered_name.to_string());
301 cov_mark::hit!(register_attr);
302 } else {
303 self.registered_tools.push(registered_name.to_string());
304 cov_mark::hit!(register_tool);
305 }
306 }
307
267 ModCollector { 308 ModCollector {
268 def_collector: &mut *self, 309 def_collector: &mut *self,
269 macro_depth: 0, 310 macro_depth: 0,
@@ -319,7 +360,7 @@ impl DefCollector<'_> {
319 } 360 }
320 } 361 }
321 362
322 if self.reseed_with_unresolved_attributes() == ReachedFixedPoint::Yes { 363 if self.reseed_with_unresolved_attribute() == ReachedFixedPoint::Yes {
323 break; 364 break;
324 } 365 }
325 } 366 }
@@ -362,27 +403,23 @@ impl DefCollector<'_> {
362 } 403 }
363 404
364 /// When the fixed-point loop reaches a stable state, we might still have some unresolved 405 /// When the fixed-point loop reaches a stable state, we might still have some unresolved
365 /// attributes (or unexpanded attribute proc macros) left over. This takes them, and feeds the 406 /// attributes (or unexpanded attribute proc macros) left over. This takes one of them, and
366 /// item they're applied to back into name resolution. 407 /// feeds the item it's applied to back into name resolution.
367 /// 408 ///
368 /// This effectively ignores the fact that the macro is there and just treats the items as 409 /// This effectively ignores the fact that the macro is there and just treats the items as
369 /// normal code. 410 /// normal code.
370 /// 411 ///
371 /// This improves UX when proc macros are turned off or don't work, and replicates the behavior 412 /// This improves UX when proc macros are turned off or don't work, and replicates the behavior
372 /// before we supported proc. attribute macros. 413 /// before we supported proc. attribute macros.
373 fn reseed_with_unresolved_attributes(&mut self) -> ReachedFixedPoint { 414 fn reseed_with_unresolved_attribute(&mut self) -> ReachedFixedPoint {
374 cov_mark::hit!(unresolved_attribute_fallback); 415 cov_mark::hit!(unresolved_attribute_fallback);
375 416
376 let mut added_items = false; 417 let mut unresolved_macros = std::mem::replace(&mut self.unresolved_macros, Vec::new());
377 let unexpanded_macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new()); 418 let pos = unresolved_macros.iter().position(|directive| {
378 for directive in &unexpanded_macros { 419 if let MacroDirectiveKind::Attr { ast_id, mod_item, attr } = &directive.kind {
379 if let MacroDirectiveKind::Attr { ast_id, mod_item, .. } = &directive.kind { 420 self.skip_attrs.insert(ast_id.ast_id.with_value(*mod_item), *attr);
380 // Make sure to only add such items once.
381 if !self.ignore_attrs_on.insert(ast_id.ast_id.with_value(*mod_item)) {
382 continue;
383 }
384 421
385 let file_id = self.def_map[directive.module_id].definition_source(self.db).file_id; 422 let file_id = ast_id.ast_id.file_id;
386 let item_tree = self.db.file_item_tree(file_id); 423 let item_tree = self.db.file_item_tree(file_id);
387 let mod_dir = self.mod_dirs[&directive.module_id].clone(); 424 let mod_dir = self.mod_dirs[&directive.module_id].clone();
388 ModCollector { 425 ModCollector {
@@ -394,14 +431,20 @@ impl DefCollector<'_> {
394 mod_dir, 431 mod_dir,
395 } 432 }
396 .collect(&[*mod_item]); 433 .collect(&[*mod_item]);
397 added_items = true; 434 true
435 } else {
436 false
398 } 437 }
438 });
439
440 if let Some(pos) = pos {
441 unresolved_macros.remove(pos);
399 } 442 }
400 443
401 // The collection above might add new unresolved macros (eg. derives), so merge the lists. 444 // The collection above might add new unresolved macros (eg. derives), so merge the lists.
402 self.unexpanded_macros.extend(unexpanded_macros); 445 self.unresolved_macros.extend(unresolved_macros);
403 446
404 if added_items { 447 if pos.is_some() {
405 // Continue name resolution with the new data. 448 // Continue name resolution with the new data.
406 ReachedFixedPoint::No 449 ReachedFixedPoint::No
407 } else { 450 } else {
@@ -873,7 +916,7 @@ impl DefCollector<'_> {
873 } 916 }
874 917
875 fn resolve_macros(&mut self) -> ReachedFixedPoint { 918 fn resolve_macros(&mut self) -> ReachedFixedPoint {
876 let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new()); 919 let mut macros = std::mem::replace(&mut self.unresolved_macros, Vec::new());
877 let mut resolved = Vec::new(); 920 let mut resolved = Vec::new();
878 let mut res = ReachedFixedPoint::Yes; 921 let mut res = ReachedFixedPoint::Yes;
879 macros.retain(|directive| { 922 macros.retain(|directive| {
@@ -922,14 +965,43 @@ impl DefCollector<'_> {
922 Err(UnresolvedMacro { .. }) => (), 965 Err(UnresolvedMacro { .. }) => (),
923 } 966 }
924 } 967 }
925 MacroDirectiveKind::Attr { .. } => { 968 MacroDirectiveKind::Attr { ast_id, mod_item, attr } => {
926 // not yet :) 969 if let Some(ident) = ast_id.path.as_ident() {
970 if let Some(helpers) = self.derive_helpers_in_scope.get(&ast_id.ast_id) {
971 if helpers.contains(ident) {
972 cov_mark::hit!(resolved_derive_helper);
973
974 // Resolved to derive helper. Collect the item's attributes again,
975 // starting after the derive helper.
976 let file_id = ast_id.ast_id.file_id;
977 let item_tree = self.db.file_item_tree(file_id);
978 let mod_dir = self.mod_dirs[&directive.module_id].clone();
979 self.skip_attrs.insert(InFile::new(file_id, *mod_item), *attr);
980 ModCollector {
981 def_collector: &mut *self,
982 macro_depth: directive.depth,
983 module_id: directive.module_id,
984 file_id,
985 item_tree: &item_tree,
986 mod_dir,
987 }
988 .collect(&[*mod_item]);
989
990 // Remove the original directive since we resolved it.
991 return false;
992 }
993 }
994 }
995
996 // Not resolved to a derive helper, so try to resolve as a macro.
997 // FIXME: not yet :)
927 } 998 }
928 } 999 }
929 1000
930 true 1001 true
931 }); 1002 });
932 self.unexpanded_macros = macros; 1003 // Attribute resolution can add unresolved macro invocations, so concatenate the lists.
1004 self.unresolved_macros.extend(macros);
933 1005
934 for (module_id, macro_call_id, depth) in resolved { 1006 for (module_id, macro_call_id, depth) in resolved {
935 self.collect_macro_expansion(module_id, macro_call_id, depth); 1007 self.collect_macro_expansion(module_id, macro_call_id, depth);
@@ -1000,7 +1072,7 @@ impl DefCollector<'_> {
1000 fn finish(mut self) -> DefMap { 1072 fn finish(mut self) -> DefMap {
1001 // Emit diagnostics for all remaining unexpanded macros. 1073 // Emit diagnostics for all remaining unexpanded macros.
1002 1074
1003 for directive in &self.unexpanded_macros { 1075 for directive in &self.unresolved_macros {
1004 match &directive.kind { 1076 match &directive.kind {
1005 MacroDirectiveKind::FnLike { ast_id, fragment } => match macro_call_as_call_id( 1077 MacroDirectiveKind::FnLike { ast_id, fragment } => match macro_call_as_call_id(
1006 ast_id, 1078 ast_id,
@@ -1102,7 +1174,7 @@ impl ModCollector<'_, '_> {
1102 1174
1103 // Prelude module is always considered to be `#[macro_use]`. 1175 // Prelude module is always considered to be `#[macro_use]`.
1104 if let Some(prelude_module) = self.def_collector.def_map.prelude { 1176 if let Some(prelude_module) = self.def_collector.def_map.prelude {
1105 if prelude_module.krate != self.def_collector.def_map.krate { 1177 if prelude_module.krate != krate {
1106 cov_mark::hit!(prelude_is_macro_use); 1178 cov_mark::hit!(prelude_is_macro_use);
1107 self.def_collector.import_all_macros_exported(self.module_id, prelude_module.krate); 1179 self.def_collector.import_all_macros_exported(self.module_id, prelude_module.krate);
1108 } 1180 }
@@ -1172,6 +1244,7 @@ impl ModCollector<'_, '_> {
1172 status: PartialResolvedImport::Unresolved, 1244 status: PartialResolvedImport::Unresolved,
1173 }) 1245 })
1174 } 1246 }
1247 ModItem::ExternBlock(block) => self.collect(&self.item_tree[block].children),
1175 ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]), 1248 ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]),
1176 ModItem::MacroRules(id) => self.collect_macro_rules(id), 1249 ModItem::MacroRules(id) => self.collect_macro_rules(id),
1177 ModItem::MacroDef(id) => self.collect_macro_def(id), 1250 ModItem::MacroDef(id) => self.collect_macro_def(id),
@@ -1203,28 +1276,18 @@ impl ModCollector<'_, '_> {
1203 ModItem::Struct(id) => { 1276 ModItem::Struct(id) => {
1204 let it = &self.item_tree[id]; 1277 let it = &self.item_tree[id];
1205 1278
1206 // FIXME: check attrs to see if this is an attribute macro invocation;
1207 // in which case we don't add the invocation, just a single attribute
1208 // macro invocation
1209 self.collect_derives(&attrs, it.ast_id.upcast());
1210
1211 def = Some(DefData { 1279 def = Some(DefData {
1212 id: StructLoc { container: module, id: ItemTreeId::new(self.file_id, id) } 1280 id: StructLoc { container: module, id: ItemTreeId::new(self.file_id, id) }
1213 .intern(self.def_collector.db) 1281 .intern(self.def_collector.db)
1214 .into(), 1282 .into(),
1215 name: &it.name, 1283 name: &it.name,
1216 visibility: &self.item_tree[it.visibility], 1284 visibility: &self.item_tree[it.visibility],
1217 has_constructor: it.kind != StructDefKind::Record, 1285 has_constructor: !matches!(it.fields, Fields::Record(_)),
1218 }); 1286 });
1219 } 1287 }
1220 ModItem::Union(id) => { 1288 ModItem::Union(id) => {
1221 let it = &self.item_tree[id]; 1289 let it = &self.item_tree[id];
1222 1290
1223 // FIXME: check attrs to see if this is an attribute macro invocation;
1224 // in which case we don't add the invocation, just a single attribute
1225 // macro invocation
1226 self.collect_derives(&attrs, it.ast_id.upcast());
1227
1228 def = Some(DefData { 1291 def = Some(DefData {
1229 id: UnionLoc { container: module, id: ItemTreeId::new(self.file_id, id) } 1292 id: UnionLoc { container: module, id: ItemTreeId::new(self.file_id, id) }
1230 .intern(self.def_collector.db) 1293 .intern(self.def_collector.db)
@@ -1237,11 +1300,6 @@ impl ModCollector<'_, '_> {
1237 ModItem::Enum(id) => { 1300 ModItem::Enum(id) => {
1238 let it = &self.item_tree[id]; 1301 let it = &self.item_tree[id];
1239 1302
1240 // FIXME: check attrs to see if this is an attribute macro invocation;
1241 // in which case we don't add the invocation, just a single attribute
1242 // macro invocation
1243 self.collect_derives(&attrs, it.ast_id.upcast());
1244
1245 def = Some(DefData { 1303 def = Some(DefData {
1246 id: EnumLoc { container: module, id: ItemTreeId::new(self.file_id, id) } 1304 id: EnumLoc { container: module, id: ItemTreeId::new(self.file_id, id) }
1247 .intern(self.def_collector.db) 1305 .intern(self.def_collector.db)
@@ -1453,76 +1511,116 @@ impl ModCollector<'_, '_> {
1453 /// 1511 ///
1454 /// Returns `Err` when some attributes could not be resolved to builtins and have been 1512 /// Returns `Err` when some attributes could not be resolved to builtins and have been
1455 /// registered as unresolved. 1513 /// registered as unresolved.
1514 ///
1515 /// If `ignore_up_to` is `Some`, attributes precending and including that attribute will be
1516 /// assumed to be resolved already.
1456 fn resolve_attributes(&mut self, attrs: &Attrs, mod_item: ModItem) -> Result<(), ()> { 1517 fn resolve_attributes(&mut self, attrs: &Attrs, mod_item: ModItem) -> Result<(), ()> {
1457 fn is_builtin_attr(path: &ModPath) -> bool { 1518 let mut ignore_up_to =
1458 if path.kind == PathKind::Plain { 1519 self.def_collector.skip_attrs.get(&InFile::new(self.file_id, mod_item)).copied();
1459 if let Some(tool_module) = path.segments().first() { 1520 let iter = attrs
1460 let tool_module = tool_module.to_string(); 1521 .iter()
1461 if builtin_attr::TOOL_MODULES.iter().any(|m| tool_module == *m) { 1522 .dedup_by(|a, b| {
1462 return true; 1523 // FIXME: this should not be required, all attributes on an item should have a
1463 } 1524 // unique ID!
1464 } 1525 // Still, this occurs because `#[cfg_attr]` can "expand" to multiple attributes:
1465 1526 // #[cfg_attr(not(off), unresolved, unresolved)]
1466 if let Some(name) = path.as_ident() { 1527 // struct S;
1467 let name = name.to_string(); 1528 // We should come up with a different way to ID attributes.
1468 if builtin_attr::INERT_ATTRIBUTES 1529 a.id == b.id
1469 .iter() 1530 })
1470 .chain(builtin_attr::EXTRA_ATTRIBUTES) 1531 .skip_while(|attr| match ignore_up_to {
1471 .any(|attr| name == *attr) 1532 Some(id) if attr.id == id => {
1472 { 1533 ignore_up_to = None;
1473 return true; 1534 true
1474 }
1475 } 1535 }
1476 } 1536 Some(_) => true,
1477 1537 None => false,
1478 false 1538 });
1479 } 1539
1480 1540 for attr in iter {
1481 // We failed to resolve an attribute on this item earlier, and are falling back to treating 1541 if attr.path.as_ident() == Some(&hir_expand::name![derive]) {
1482 // the item as-is. 1542 self.collect_derive(attr, mod_item);
1483 if self.def_collector.ignore_attrs_on.contains(&InFile::new(self.file_id, mod_item)) { 1543 } else if self.is_builtin_or_registered_attr(&attr.path) {
1484 return Ok(()); 1544 continue;
1485 } 1545 } else {
1486 1546 log::debug!("non-builtin attribute {}", attr.path);
1487 match attrs.iter().find(|attr| !is_builtin_attr(&attr.path)) {
1488 Some(non_builtin_attr) => {
1489 log::debug!("non-builtin attribute {}", non_builtin_attr.path);
1490 1547
1491 let ast_id = AstIdWithPath::new( 1548 let ast_id = AstIdWithPath::new(
1492 self.file_id, 1549 self.file_id,
1493 mod_item.ast_id(self.item_tree), 1550 mod_item.ast_id(self.item_tree),
1494 non_builtin_attr.path.as_ref().clone(), 1551 attr.path.as_ref().clone(),
1495 ); 1552 );
1496 self.def_collector.unexpanded_macros.push(MacroDirective { 1553 self.def_collector.unresolved_macros.push(MacroDirective {
1497 module_id: self.module_id, 1554 module_id: self.module_id,
1498 depth: self.macro_depth + 1, 1555 depth: self.macro_depth + 1,
1499 kind: MacroDirectiveKind::Attr { ast_id, attr: non_builtin_attr.id, mod_item }, 1556 kind: MacroDirectiveKind::Attr { ast_id, attr: attr.id, mod_item },
1500 }); 1557 });
1501 1558
1502 Err(()) 1559 return Err(());
1503 } 1560 }
1504 None => Ok(()),
1505 } 1561 }
1562
1563 Ok(())
1506 } 1564 }
1507 1565
1508 fn collect_derives(&mut self, attrs: &Attrs, ast_id: FileAstId<ast::Item>) { 1566 fn is_builtin_or_registered_attr(&self, path: &ModPath) -> bool {
1509 for derive in attrs.by_key("derive").attrs() { 1567 if path.kind == PathKind::Plain {
1510 match derive.parse_derive() { 1568 if let Some(tool_module) = path.segments().first() {
1511 Some(derive_macros) => { 1569 let tool_module = tool_module.to_string();
1512 for path in derive_macros { 1570 if builtin_attr::TOOL_MODULES
1513 let ast_id = AstIdWithPath::new(self.file_id, ast_id, path); 1571 .iter()
1514 self.def_collector.unexpanded_macros.push(MacroDirective { 1572 .copied()
1515 module_id: self.module_id, 1573 .chain(self.def_collector.registered_tools.iter().map(|s| &**s))
1516 depth: self.macro_depth + 1, 1574 .any(|m| tool_module == *m)
1517 kind: MacroDirectiveKind::Derive { ast_id, derive_attr: derive.id }, 1575 {
1518 }); 1576 return true;
1519 }
1520 } 1577 }
1521 None => { 1578 }
1522 // FIXME: diagnose 1579
1523 log::debug!("malformed derive: {:?}", derive); 1580 if let Some(name) = path.as_ident() {
1581 let name = name.to_string();
1582 if builtin_attr::INERT_ATTRIBUTES
1583 .iter()
1584 .chain(builtin_attr::EXTRA_ATTRIBUTES)
1585 .copied()
1586 .chain(self.def_collector.registered_attrs.iter().map(|s| &**s))
1587 .any(|attr| name == *attr)
1588 {
1589 return true;
1590 }
1591 }
1592 }
1593
1594 false
1595 }
1596
1597 fn collect_derive(&mut self, attr: &Attr, mod_item: ModItem) {
1598 let ast_id: FileAstId<ast::Item> = match mod_item {
1599 ModItem::Struct(it) => self.item_tree[it].ast_id.upcast(),
1600 ModItem::Union(it) => self.item_tree[it].ast_id.upcast(),
1601 ModItem::Enum(it) => self.item_tree[it].ast_id.upcast(),
1602 _ => {
1603 // Cannot use derive on this item.
1604 // FIXME: diagnose
1605 return;
1606 }
1607 };
1608
1609 match attr.parse_derive() {
1610 Some(derive_macros) => {
1611 for path in derive_macros {
1612 let ast_id = AstIdWithPath::new(self.file_id, ast_id, path);
1613 self.def_collector.unresolved_macros.push(MacroDirective {
1614 module_id: self.module_id,
1615 depth: self.macro_depth + 1,
1616 kind: MacroDirectiveKind::Derive { ast_id, derive_attr: attr.id },
1617 });
1524 } 1618 }
1525 } 1619 }
1620 None => {
1621 // FIXME: diagnose
1622 log::debug!("malformed derive: {:?}", attr);
1623 }
1526 } 1624 }
1527 } 1625 }
1528 1626
@@ -1686,7 +1784,7 @@ impl ModCollector<'_, '_> {
1686 ast_id.path.kind = PathKind::Super(0); 1784 ast_id.path.kind = PathKind::Super(0);
1687 } 1785 }
1688 1786
1689 self.def_collector.unexpanded_macros.push(MacroDirective { 1787 self.def_collector.unresolved_macros.push(MacroDirective {
1690 module_id: self.module_id, 1788 module_id: self.module_id,
1691 depth: self.macro_depth + 1, 1789 depth: self.macro_depth + 1,
1692 kind: MacroDirectiveKind::FnLike { ast_id, fragment: mac.fragment }, 1790 kind: MacroDirectiveKind::FnLike { ast_id, fragment: mac.fragment },
@@ -1731,14 +1829,16 @@ mod tests {
1731 glob_imports: FxHashMap::default(), 1829 glob_imports: FxHashMap::default(),
1732 unresolved_imports: Vec::new(), 1830 unresolved_imports: Vec::new(),
1733 resolved_imports: Vec::new(), 1831 resolved_imports: Vec::new(),
1734 unexpanded_macros: Vec::new(), 1832 unresolved_macros: Vec::new(),
1735 mod_dirs: FxHashMap::default(), 1833 mod_dirs: FxHashMap::default(),
1736 cfg_options: &CfgOptions::default(), 1834 cfg_options: &CfgOptions::default(),
1737 proc_macros: Default::default(), 1835 proc_macros: Default::default(),
1738 exports_proc_macros: false, 1836 exports_proc_macros: false,
1739 from_glob_import: Default::default(), 1837 from_glob_import: Default::default(),
1740 ignore_attrs_on: FxHashSet::default(), 1838 skip_attrs: Default::default(),
1741 derive_helpers_in_scope: FxHashMap::default(), 1839 derive_helpers_in_scope: Default::default(),
1840 registered_attrs: Default::default(),
1841 registered_tools: Default::default(),
1742 }; 1842 };
1743 collector.seed_with_top_level(); 1843 collector.seed_with_top_level();
1744 collector.collect(); 1844 collector.collect();
diff --git a/crates/hir_def/src/nameres/tests/diagnostics.rs b/crates/hir_def/src/nameres/tests/diagnostics.rs
index 543975e07..75147d973 100644
--- a/crates/hir_def/src/nameres/tests/diagnostics.rs
+++ b/crates/hir_def/src/nameres/tests/diagnostics.rs
@@ -237,3 +237,20 @@ fn good_out_dir_diagnostic() {
237 "#, 237 "#,
238 ); 238 );
239} 239}
240
241#[test]
242fn register_attr_and_tool() {
243 cov_mark::check!(register_attr);
244 cov_mark::check!(register_tool);
245 check_no_diagnostics(
246 r#"
247#![register_tool(tool)]
248#![register_attr(attr)]
249
250#[tool::path]
251#[attr]
252struct S;
253 "#,
254 );
255 // NB: we don't currently emit diagnostics here
256}
diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs
index 6eb5f97be..3065efd65 100644
--- a/crates/hir_def/src/nameres/tests/macros.rs
+++ b/crates/hir_def/src/nameres/tests/macros.rs
@@ -736,6 +736,80 @@ fn unresolved_attributes_fall_back_track_per_file_moditems() {
736} 736}
737 737
738#[test] 738#[test]
739fn unresolved_attrs_extern_block_hang() {
740 // Regression test for https://github.com/rust-analyzer/rust-analyzer/issues/8905
741 check(
742 r#"
743#[unresolved]
744extern "C" {
745 #[unresolved]
746 fn f();
747}
748 "#,
749 expect![[r#"
750 crate
751 f: v
752 "#]],
753 );
754}
755
756#[test]
757fn macros_in_extern_block() {
758 check(
759 r#"
760macro_rules! m {
761 () => { static S: u8; };
762}
763
764extern {
765 m!();
766}
767 "#,
768 expect![[r#"
769 crate
770 S: v
771 "#]],
772 );
773}
774
775#[test]
776fn resolves_derive_helper() {
777 cov_mark::check!(resolved_derive_helper);
778 check(
779 r#"
780//- /main.rs crate:main deps:proc
781#[derive(proc::Derive)]
782#[helper]
783#[unresolved]
784struct S;
785
786//- /proc.rs crate:proc
787#[proc_macro_derive(Derive, attributes(helper))]
788fn derive() {}
789 "#,
790 expect![[r#"
791 crate
792 S: t v
793 "#]],
794 );
795}
796
797#[test]
798fn unresolved_attr_with_cfg_attr_hang() {
799 // Another regression test for https://github.com/rust-analyzer/rust-analyzer/issues/8905
800 check(
801 r#"
802#[cfg_attr(not(off), unresolved, unresolved)]
803struct S;
804 "#,
805 expect![[r#"
806 crate
807 S: t v
808 "#]],
809 );
810}
811
812#[test]
739fn macro_expansion_overflow() { 813fn macro_expansion_overflow() {
740 cov_mark::check!(macro_expansion_overflow); 814 cov_mark::check!(macro_expansion_overflow);
741 check( 815 check(
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs
index a43441b1c..9b8873fd2 100644
--- a/crates/hir_def/src/path.rs
+++ b/crates/hir_def/src/path.rs
@@ -46,6 +46,15 @@ pub enum ImportAlias {
46 Alias(Name), 46 Alias(Name),
47} 47}
48 48
49impl Display for ImportAlias {
50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51 match self {
52 ImportAlias::Underscore => f.write_str("_"),
53 ImportAlias::Alias(name) => f.write_str(&name.to_string()),
54 }
55 }
56}
57
49impl ModPath { 58impl ModPath {
50 pub fn from_src(db: &dyn DefDatabase, path: ast::Path, hygiene: &Hygiene) -> Option<ModPath> { 59 pub fn from_src(db: &dyn DefDatabase, path: ast::Path, hygiene: &Hygiene) -> Option<ModPath> {
51 let ctx = LowerCtx::with_hygiene(db, hygiene); 60 let ctx = LowerCtx::with_hygiene(db, hygiene);
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs
index 5a5dc9afd..ef67ea2e9 100644
--- a/crates/hir_expand/src/name.rs
+++ b/crates/hir_expand/src/name.rs
@@ -164,6 +164,8 @@ pub mod known {
164 doc, 164 doc,
165 cfg, 165 cfg,
166 cfg_attr, 166 cfg_attr,
167 register_attr,
168 register_tool,
167 // Components of known path (value or mod name) 169 // Components of known path (value or mod name)
168 std, 170 std,
169 core, 171 core,
diff --git a/crates/hir_ty/src/builder.rs b/crates/hir_ty/src/builder.rs
index e25ef866d..893e727c2 100644
--- a/crates/hir_ty/src/builder.rs
+++ b/crates/hir_ty/src/builder.rs
@@ -6,15 +6,15 @@ use chalk_ir::{
6 cast::{Cast, CastTo, Caster}, 6 cast::{Cast, CastTo, Caster},
7 fold::Fold, 7 fold::Fold,
8 interner::HasInterner, 8 interner::HasInterner,
9 AdtId, BoundVar, DebruijnIndex, Safety, Scalar, 9 AdtId, BoundVar, DebruijnIndex, Scalar,
10}; 10};
11use hir_def::{builtin_type::BuiltinType, GenericDefId, TraitId, TypeAliasId}; 11use hir_def::{builtin_type::BuiltinType, GenericDefId, TraitId, TypeAliasId};
12use smallvec::SmallVec; 12use smallvec::SmallVec;
13 13
14use crate::{ 14use crate::{
15 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,
16 CallableSig, FnPointer, FnSig, FnSubst, GenericArg, Interner, ProjectionTy, Substitution, 16 CallableSig, GenericArg, Interner, ProjectionTy, Substitution, TraitRef, Ty, TyDefId, TyExt,
17 TraitRef, Ty, TyDefId, TyExt, TyKind, ValueTyDefId, 17 TyKind, ValueTyDefId,
18}; 18};
19 19
20/// 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`.
@@ -77,15 +77,7 @@ impl TyBuilder<()> {
77 } 77 }
78 78
79 pub fn fn_ptr(sig: CallableSig) -> Ty { 79 pub fn fn_ptr(sig: CallableSig) -> Ty {
80 TyKind::Function(FnPointer { 80 TyKind::Function(sig.to_fn_ptr()).intern(&Interner)
81 num_binders: 0,
82 sig: FnSig { abi: (), safety: Safety::Safe, variadic: sig.is_varargs },
83 substitution: FnSubst(Substitution::from_iter(
84 &Interner,
85 sig.params_and_return.iter().cloned(),
86 )),
87 })
88 .intern(&Interner)
89 } 81 }
90 82
91 pub fn builtin(builtin: BuiltinType) -> Ty { 83 pub fn builtin(builtin: BuiltinType) -> Ty {
diff --git a/crates/hir_ty/src/chalk_db.rs b/crates/hir_ty/src/chalk_db.rs
index 8f054d06b..b108fd559 100644
--- a/crates/hir_ty/src/chalk_db.rs
+++ b/crates/hir_ty/src/chalk_db.rs
@@ -344,20 +344,20 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
344 } 344 }
345 345
346 fn unification_database(&self) -> &dyn chalk_ir::UnificationDatabase<Interner> { 346 fn unification_database(&self) -> &dyn chalk_ir::UnificationDatabase<Interner> {
347 self 347 &self.db
348 } 348 }
349} 349}
350 350
351impl<'a> chalk_ir::UnificationDatabase<Interner> for ChalkContext<'a> { 351impl<'a> chalk_ir::UnificationDatabase<Interner> for &'a dyn HirDatabase {
352 fn fn_def_variance( 352 fn fn_def_variance(
353 &self, 353 &self,
354 fn_def_id: chalk_ir::FnDefId<Interner>, 354 fn_def_id: chalk_ir::FnDefId<Interner>,
355 ) -> chalk_ir::Variances<Interner> { 355 ) -> chalk_ir::Variances<Interner> {
356 self.db.fn_def_variance(self.krate, fn_def_id) 356 HirDatabase::fn_def_variance(*self, fn_def_id)
357 } 357 }
358 358
359 fn adt_variance(&self, adt_id: chalk_ir::AdtId<Interner>) -> chalk_ir::Variances<Interner> { 359 fn adt_variance(&self, adt_id: chalk_ir::AdtId<Interner>) -> chalk_ir::Variances<Interner> {
360 self.db.adt_variance(self.krate, adt_id) 360 HirDatabase::adt_variance(*self, adt_id)
361 } 361 }
362} 362}
363 363
@@ -651,11 +651,7 @@ pub(crate) fn fn_def_datum_query(
651 Arc::new(datum) 651 Arc::new(datum)
652} 652}
653 653
654pub(crate) fn fn_def_variance_query( 654pub(crate) fn fn_def_variance_query(db: &dyn HirDatabase, fn_def_id: FnDefId) -> Variances {
655 db: &dyn HirDatabase,
656 _krate: CrateId,
657 fn_def_id: FnDefId,
658) -> Variances {
659 let callable_def: CallableDefId = from_chalk(db, fn_def_id); 655 let callable_def: CallableDefId = from_chalk(db, fn_def_id);
660 let generic_params = generics(db.upcast(), callable_def.into()); 656 let generic_params = generics(db.upcast(), callable_def.into());
661 Variances::from_iter( 657 Variances::from_iter(
@@ -666,7 +662,6 @@ pub(crate) fn fn_def_variance_query(
666 662
667pub(crate) fn adt_variance_query( 663pub(crate) fn adt_variance_query(
668 db: &dyn HirDatabase, 664 db: &dyn HirDatabase,
669 _krate: CrateId,
670 chalk_ir::AdtId(adt_id): AdtId, 665 chalk_ir::AdtId(adt_id): AdtId,
671) -> Variances { 666) -> Variances {
672 let generic_params = generics(db.upcast(), adt_id.into()); 667 let generic_params = generics(db.upcast(), adt_id.into());
diff --git a/crates/hir_ty/src/chalk_ext.rs b/crates/hir_ty/src/chalk_ext.rs
index 5232a7d80..df340a6ca 100644
--- a/crates/hir_ty/src/chalk_ext.rs
+++ b/crates/hir_ty/src/chalk_ext.rs
@@ -18,6 +18,7 @@ pub trait TyExt {
18 fn is_unit(&self) -> bool; 18 fn is_unit(&self) -> bool;
19 fn is_never(&self) -> bool; 19 fn is_never(&self) -> bool;
20 fn is_unknown(&self) -> bool; 20 fn is_unknown(&self) -> bool;
21 fn is_ty_var(&self) -> bool;
21 22
22 fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)>; 23 fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)>;
23 fn as_builtin(&self) -> Option<BuiltinType>; 24 fn as_builtin(&self) -> Option<BuiltinType>;
@@ -55,6 +56,10 @@ impl TyExt for Ty {
55 matches!(self.kind(&Interner), TyKind::Error) 56 matches!(self.kind(&Interner), TyKind::Error)
56 } 57 }
57 58
59 fn is_ty_var(&self) -> bool {
60 matches!(self.kind(&Interner), TyKind::InferenceVar(_, _))
61 }
62
58 fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)> { 63 fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)> {
59 match self.kind(&Interner) { 64 match self.kind(&Interner) {
60 TyKind::Adt(AdtId(adt), parameters) => Some((*adt, parameters)), 65 TyKind::Adt(AdtId(adt), parameters) => Some((*adt, parameters)),
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs
index 9da0a02e3..be5b9110e 100644
--- a/crates/hir_ty/src/db.rs
+++ b/crates/hir_ty/src/db.rs
@@ -117,10 +117,10 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
117 fn fn_def_datum(&self, krate: CrateId, fn_def_id: FnDefId) -> Arc<chalk_db::FnDefDatum>; 117 fn fn_def_datum(&self, krate: CrateId, fn_def_id: FnDefId) -> Arc<chalk_db::FnDefDatum>;
118 118
119 #[salsa::invoke(chalk_db::fn_def_variance_query)] 119 #[salsa::invoke(chalk_db::fn_def_variance_query)]
120 fn fn_def_variance(&self, krate: CrateId, fn_def_id: FnDefId) -> chalk_db::Variances; 120 fn fn_def_variance(&self, fn_def_id: FnDefId) -> chalk_db::Variances;
121 121
122 #[salsa::invoke(chalk_db::adt_variance_query)] 122 #[salsa::invoke(chalk_db::adt_variance_query)]
123 fn adt_variance(&self, krate: CrateId, adt_id: chalk_db::AdtId) -> chalk_db::Variances; 123 fn adt_variance(&self, adt_id: chalk_db::AdtId) -> chalk_db::Variances;
124 124
125 #[salsa::invoke(chalk_db::associated_ty_value_query)] 125 #[salsa::invoke(chalk_db::associated_ty_value_query)]
126 fn associated_ty_value( 126 fn associated_ty_value(
@@ -134,14 +134,14 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
134 fn trait_solve( 134 fn trait_solve(
135 &self, 135 &self,
136 krate: CrateId, 136 krate: CrateId,
137 goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>, 137 goal: crate::Canonical<crate::InEnvironment<crate::Goal>>,
138 ) -> Option<crate::Solution>; 138 ) -> Option<crate::Solution>;
139 139
140 #[salsa::invoke(crate::traits::trait_solve_query)] 140 #[salsa::invoke(crate::traits::trait_solve_query)]
141 fn trait_solve_query( 141 fn trait_solve_query(
142 &self, 142 &self,
143 krate: CrateId, 143 krate: CrateId,
144 goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>, 144 goal: crate::Canonical<crate::InEnvironment<crate::Goal>>,
145 ) -> Option<crate::Solution>; 145 ) -> Option<crate::Solution>;
146 146
147 #[salsa::invoke(chalk_db::program_clauses_for_chalk_env_query)] 147 #[salsa::invoke(chalk_db::program_clauses_for_chalk_env_query)]
@@ -168,7 +168,7 @@ fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult>
168fn trait_solve_wait( 168fn trait_solve_wait(
169 db: &dyn HirDatabase, 169 db: &dyn HirDatabase,
170 krate: CrateId, 170 krate: CrateId,
171 goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>, 171 goal: crate::Canonical<crate::InEnvironment<crate::Goal>>,
172) -> Option<crate::Solution> { 172) -> Option<crate::Solution> {
173 let _p = profile::span("trait_solve::wait"); 173 let _p = profile::span("trait_solve::wait");
174 db.trait_solve_query(krate, goal) 174 db.trait_solve_query(krate, goal)
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index 0ee851a74..f1cebbdb9 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -13,8 +13,6 @@
13//! to certain types. To record this, we use the union-find implementation from 13//! to certain types. To record this, we use the union-find implementation from
14//! the `ena` crate, which is extracted from rustc. 14//! the `ena` crate, which is extracted from rustc.
15 15
16use std::borrow::Cow;
17use std::mem;
18use std::ops::Index; 16use std::ops::Index;
19use std::sync::Arc; 17use std::sync::Arc;
20 18
@@ -27,8 +25,8 @@ use hir_def::{
27 path::{path, Path}, 25 path::{path, Path},
28 resolver::{HasResolver, Resolver, TypeNs}, 26 resolver::{HasResolver, Resolver, TypeNs},
29 type_ref::TypeRef, 27 type_ref::TypeRef,
30 AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, Lookup, TraitId, 28 AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, HasModule, Lookup,
31 TypeAliasId, VariantId, 29 TraitId, TypeAliasId, VariantId,
32}; 30};
33use hir_expand::{diagnostics::DiagnosticSink, name::name}; 31use hir_expand::{diagnostics::DiagnosticSink, name::name};
34use la_arena::ArenaMap; 32use la_arena::ArenaMap;
@@ -36,13 +34,11 @@ use rustc_hash::FxHashMap;
36use stdx::impl_from; 34use stdx::impl_from;
37use syntax::SmolStr; 35use syntax::SmolStr;
38 36
39use super::{ 37use super::{DomainGoal, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty};
40 DomainGoal, Guidance, InEnvironment, ProjectionTy, Solution, TraitEnvironment, TraitRef, Ty,
41};
42use crate::{ 38use crate::{
43 db::HirDatabase, fold_tys, infer::diagnostics::InferenceDiagnostic, 39 db::HirDatabase, fold_tys, infer::diagnostics::InferenceDiagnostic,
44 lower::ImplTraitLoweringMode, to_assoc_type_id, AliasEq, AliasTy, Canonical, Interner, 40 lower::ImplTraitLoweringMode, to_assoc_type_id, AliasEq, AliasTy, Goal, Interner, TyBuilder,
45 TyBuilder, TyExt, TyKind, 41 TyExt, TyKind,
46}; 42};
47 43
48// This lint has a false positive here. See the link below for details. 44// This lint has a false positive here. See the link below for details.
@@ -106,6 +102,14 @@ impl Default for BindingMode {
106 } 102 }
107} 103}
108 104
105#[derive(Debug)]
106pub(crate) struct InferOk {
107 goals: Vec<InEnvironment<Goal>>,
108}
109#[derive(Debug)]
110pub(crate) struct TypeError;
111pub(crate) type InferResult = Result<InferOk, TypeError>;
112
109/// A mismatch between an expected and an inferred type. 113/// A mismatch between an expected and an inferred type.
110#[derive(Clone, PartialEq, Eq, Debug, Hash)] 114#[derive(Clone, PartialEq, Eq, Debug, Hash)]
111pub struct TypeMismatch { 115pub struct TypeMismatch {
@@ -217,10 +221,8 @@ struct InferenceContext<'a> {
217 owner: DefWithBodyId, 221 owner: DefWithBodyId,
218 body: Arc<Body>, 222 body: Arc<Body>,
219 resolver: Resolver, 223 resolver: Resolver,
220 table: unify::InferenceTable, 224 table: unify::InferenceTable<'a>,
221 trait_env: Arc<TraitEnvironment>, 225 trait_env: Arc<TraitEnvironment>,
222 obligations: Vec<DomainGoal>,
223 last_obligations_check: Option<u32>,
224 result: InferenceResult, 226 result: InferenceResult,
225 /// The return type of the function being inferred, or the closure if we're 227 /// The return type of the function being inferred, or the closure if we're
226 /// currently within one. 228 /// currently within one.
@@ -252,15 +254,15 @@ fn find_breakable<'c>(
252 254
253impl<'a> InferenceContext<'a> { 255impl<'a> InferenceContext<'a> {
254 fn new(db: &'a dyn HirDatabase, owner: DefWithBodyId, resolver: Resolver) -> Self { 256 fn new(db: &'a dyn HirDatabase, owner: DefWithBodyId, resolver: Resolver) -> Self {
257 let krate = owner.module(db.upcast()).krate();
258 let trait_env = owner
259 .as_generic_def_id()
260 .map_or_else(|| Arc::new(TraitEnvironment::empty(krate)), |d| db.trait_environment(d));
255 InferenceContext { 261 InferenceContext {
256 result: InferenceResult::default(), 262 result: InferenceResult::default(),
257 table: unify::InferenceTable::new(), 263 table: unify::InferenceTable::new(db, trait_env.clone()),
258 obligations: Vec::default(), 264 trait_env,
259 last_obligations_check: None,
260 return_ty: TyKind::Error.intern(&Interner), // set in collect_fn_signature 265 return_ty: TyKind::Error.intern(&Interner), // set in collect_fn_signature
261 trait_env: owner
262 .as_generic_def_id()
263 .map_or_else(Default::default, |d| db.trait_environment(d)),
264 db, 266 db,
265 owner, 267 owner,
266 body: db.body(owner), 268 body: db.body(owner),
@@ -271,19 +273,25 @@ impl<'a> InferenceContext<'a> {
271 } 273 }
272 274
273 fn err_ty(&self) -> Ty { 275 fn err_ty(&self) -> Ty {
274 TyKind::Error.intern(&Interner) 276 self.result.standard_types.unknown.clone()
275 } 277 }
276 278
277 fn resolve_all(mut self) -> InferenceResult { 279 fn resolve_all(mut self) -> InferenceResult {
278 // FIXME resolve obligations as well (use Guidance if necessary) 280 // FIXME resolve obligations as well (use Guidance if necessary)
281 self.table.resolve_obligations_as_possible();
282
283 // make sure diverging type variables are marked as such
284 self.table.propagate_diverging_flag();
279 let mut result = std::mem::take(&mut self.result); 285 let mut result = std::mem::take(&mut self.result);
280 for ty in result.type_of_expr.values_mut() { 286 for ty in result.type_of_expr.values_mut() {
281 let resolved = self.table.resolve_ty_completely(ty.clone()); 287 *ty = self.table.resolve_ty_completely(ty.clone());
282 *ty = resolved;
283 } 288 }
284 for ty in result.type_of_pat.values_mut() { 289 for ty in result.type_of_pat.values_mut() {
285 let resolved = self.table.resolve_ty_completely(ty.clone()); 290 *ty = self.table.resolve_ty_completely(ty.clone());
286 *ty = resolved; 291 }
292 for mismatch in result.type_mismatches.values_mut() {
293 mismatch.expected = self.table.resolve_ty_completely(mismatch.expected.clone());
294 mismatch.actual = self.table.resolve_ty_completely(mismatch.actual.clone());
287 } 295 }
288 result 296 result
289 } 297 }
@@ -337,6 +345,14 @@ impl<'a> InferenceContext<'a> {
337 fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { 345 fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
338 match ty.kind(&Interner) { 346 match ty.kind(&Interner) {
339 TyKind::Error => self.table.new_type_var(), 347 TyKind::Error => self.table.new_type_var(),
348 TyKind::InferenceVar(..) => {
349 let ty_resolved = self.resolve_ty_shallow(&ty);
350 if ty_resolved.is_unknown() {
351 self.table.new_type_var()
352 } else {
353 ty
354 }
355 }
340 _ => ty, 356 _ => ty,
341 } 357 }
342 } 358 }
@@ -346,66 +362,19 @@ impl<'a> InferenceContext<'a> {
346 } 362 }
347 363
348 fn resolve_obligations_as_possible(&mut self) { 364 fn resolve_obligations_as_possible(&mut self) {
349 if self.last_obligations_check == Some(self.table.revision) { 365 self.table.resolve_obligations_as_possible();
350 // no change
351 return;
352 }
353 let _span = profile::span("resolve_obligations_as_possible");
354
355 self.last_obligations_check = Some(self.table.revision);
356 let obligations = mem::replace(&mut self.obligations, Vec::new());
357 for obligation in obligations {
358 let in_env = InEnvironment::new(&self.trait_env.env, obligation.clone());
359 let canonicalized = self.canonicalizer().canonicalize_obligation(in_env);
360 let solution =
361 self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone());
362
363 match solution {
364 Some(Solution::Unique(canonical_subst)) => {
365 canonicalized.apply_solution(
366 self,
367 Canonical {
368 binders: canonical_subst.binders,
369 // FIXME: handle constraints
370 value: canonical_subst.value.subst,
371 },
372 );
373 }
374 Some(Solution::Ambig(Guidance::Definite(substs))) => {
375 canonicalized.apply_solution(self, substs);
376 self.obligations.push(obligation);
377 }
378 Some(_) => {
379 // FIXME use this when trying to resolve everything at the end
380 self.obligations.push(obligation);
381 }
382 None => {
383 // FIXME obligation cannot be fulfilled => diagnostic
384 }
385 };
386 }
387 } 366 }
388 367
389 fn push_obligation(&mut self, o: DomainGoal) { 368 fn push_obligation(&mut self, o: DomainGoal) {
390 self.obligations.push(o); 369 self.table.register_obligation(o.cast(&Interner));
391 self.last_obligations_check = None;
392 } 370 }
393 371
394 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { 372 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
395 self.table.unify(ty1, ty2) 373 self.table.unify(ty1, ty2)
396 } 374 }
397 375
398 /// Resolves the type as far as currently possible, replacing type variables 376 fn resolve_ty_shallow(&mut self, ty: &Ty) -> Ty {
399 /// by their known types. All types returned by the infer_* functions should
400 /// be resolved as far as possible, i.e. contain no type variables with
401 /// known type.
402 fn resolve_ty_as_possible(&mut self, ty: Ty) -> Ty {
403 self.resolve_obligations_as_possible(); 377 self.resolve_obligations_as_possible();
404
405 self.table.resolve_ty_as_possible(ty)
406 }
407
408 fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> {
409 self.table.resolve_ty_shallow(ty) 378 self.table.resolve_ty_shallow(ty)
410 } 379 }
411 380
@@ -439,7 +408,7 @@ impl<'a> InferenceContext<'a> {
439 }; 408 };
440 self.push_obligation(trait_ref.cast(&Interner)); 409 self.push_obligation(trait_ref.cast(&Interner));
441 self.push_obligation(alias_eq.cast(&Interner)); 410 self.push_obligation(alias_eq.cast(&Interner));
442 self.resolve_ty_as_possible(ty) 411 ty
443 } 412 }
444 None => self.err_ty(), 413 None => self.err_ty(),
445 } 414 }
@@ -452,25 +421,7 @@ impl<'a> InferenceContext<'a> {
452 /// call). `make_ty` handles this already, but e.g. for field types we need 421 /// call). `make_ty` handles this already, but e.g. for field types we need
453 /// to do it as well. 422 /// to do it as well.
454 fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { 423 fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty {
455 let ty = self.resolve_ty_as_possible(ty); 424 self.table.normalize_associated_types_in(ty)
456 fold_tys(
457 ty,
458 |ty, _| match ty.kind(&Interner) {
459 TyKind::Alias(AliasTy::Projection(proj_ty)) => {
460 self.normalize_projection_ty(proj_ty.clone())
461 }
462 _ => ty,
463 },
464 DebruijnIndex::INNERMOST,
465 )
466 }
467
468 fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
469 let var = self.table.new_type_var();
470 let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() };
471 let obligation = alias_eq.cast(&Interner);
472 self.push_obligation(obligation);
473 var
474 } 425 }
475 426
476 fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantId>) { 427 fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantId>) {
@@ -720,17 +671,23 @@ impl<'a> InferenceContext<'a> {
720/// When inferring an expression, we propagate downward whatever type hint we 671/// When inferring an expression, we propagate downward whatever type hint we
721/// are able in the form of an `Expectation`. 672/// are able in the form of an `Expectation`.
722#[derive(Clone, PartialEq, Eq, Debug)] 673#[derive(Clone, PartialEq, Eq, Debug)]
723struct Expectation { 674enum Expectation {
724 ty: Ty, 675 None,
725 /// See the `rvalue_hint` method. 676 HasType(Ty),
726 rvalue_hint: bool, 677 // Castable(Ty), // rustc has this, we currently just don't propagate an expectation for casts
678 RValueLikeUnsized(Ty),
727} 679}
728 680
729impl Expectation { 681impl Expectation {
730 /// The expectation that the type of the expression needs to equal the given 682 /// The expectation that the type of the expression needs to equal the given
731 /// type. 683 /// type.
732 fn has_type(ty: Ty) -> Self { 684 fn has_type(ty: Ty) -> Self {
733 Expectation { ty, rvalue_hint: false } 685 if ty.is_unknown() {
686 // FIXME: get rid of this?
687 Expectation::None
688 } else {
689 Expectation::HasType(ty)
690 }
734 } 691 }
735 692
736 /// The following explanation is copied straight from rustc: 693 /// The following explanation is copied straight from rustc:
@@ -754,24 +711,41 @@ impl Expectation {
754 /// See the test case `test/ui/coerce-expect-unsized.rs` and #20169 711 /// See the test case `test/ui/coerce-expect-unsized.rs` and #20169
755 /// for examples of where this comes up,. 712 /// for examples of where this comes up,.
756 fn rvalue_hint(ty: Ty) -> Self { 713 fn rvalue_hint(ty: Ty) -> Self {
757 Expectation { ty, rvalue_hint: true } 714 match ty.strip_references().kind(&Interner) {
715 TyKind::Slice(_) | TyKind::Str | TyKind::Dyn(_) => Expectation::RValueLikeUnsized(ty),
716 _ => Expectation::has_type(ty),
717 }
758 } 718 }
759 719
760 /// This expresses no expectation on the type. 720 /// This expresses no expectation on the type.
761 fn none() -> Self { 721 fn none() -> Self {
762 Expectation { 722 Expectation::None
763 // FIXME 723 }
764 ty: TyKind::Error.intern(&Interner), 724
765 rvalue_hint: false, 725 fn resolve(&self, table: &mut unify::InferenceTable) -> Expectation {
726 match self {
727 Expectation::None => Expectation::None,
728 Expectation::HasType(t) => Expectation::HasType(table.resolve_ty_shallow(t)),
729 Expectation::RValueLikeUnsized(t) => {
730 Expectation::RValueLikeUnsized(table.resolve_ty_shallow(t))
731 }
766 } 732 }
767 } 733 }
768 734
769 fn coercion_target(&self) -> Ty { 735 fn to_option(&self, table: &mut unify::InferenceTable) -> Option<Ty> {
770 if self.rvalue_hint { 736 match self.resolve(table) {
771 // FIXME 737 Expectation::None => None,
772 TyKind::Error.intern(&Interner) 738 Expectation::HasType(t) |
773 } else { 739 // Expectation::Castable(t) |
774 self.ty.clone() 740 Expectation::RValueLikeUnsized(t) => Some(t),
741 }
742 }
743
744 fn only_has_type(&self, table: &mut unify::InferenceTable) -> Option<Ty> {
745 match self {
746 Expectation::HasType(t) => Some(table.resolve_ty_shallow(t)),
747 // Expectation::Castable(_) |
748 Expectation::RValueLikeUnsized(_) | Expectation::None => None,
775 } 749 }
776 } 750 }
777} 751}
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs
index 1f463a425..765a02b1c 100644
--- a/crates/hir_ty/src/infer/coerce.rs
+++ b/crates/hir_ty/src/infer/coerce.rs
@@ -2,156 +2,414 @@
2//! happen in certain places, e.g. weakening `&mut` to `&` or deref coercions 2//! happen in certain places, e.g. weakening `&mut` to `&` or deref coercions
3//! like going from `&Vec<T>` to `&[T]`. 3//! like going from `&Vec<T>` to `&[T]`.
4//! 4//!
5//! See: https://doc.rust-lang.org/nomicon/coercions.html 5//! See https://doc.rust-lang.org/nomicon/coercions.html and
6//! librustc_typeck/check/coercion.rs.
6 7
7use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; 8use chalk_ir::{cast::Cast, Mutability, TyVariableKind};
8use hir_def::lang_item::LangItemTarget; 9use hir_def::{expr::ExprId, lang_item::LangItemTarget};
9 10
10use crate::{autoderef, Canonical, Interner, Solution, Ty, TyBuilder, TyExt, TyKind}; 11use crate::{
12 autoderef, infer::TypeMismatch, static_lifetime, Canonical, DomainGoal, FnPointer, FnSig,
13 Interner, Solution, Substitution, Ty, TyBuilder, TyExt, TyKind,
14};
11 15
12use super::{InEnvironment, InferenceContext}; 16use super::{InEnvironment, InferOk, InferResult, InferenceContext, TypeError};
13 17
14impl<'a> InferenceContext<'a> { 18impl<'a> InferenceContext<'a> {
15 /// Unify two types, but may coerce the first one to the second one 19 /// Unify two types, but may coerce the first one to the second one
16 /// using "implicit coercion rules" if needed. 20 /// using "implicit coercion rules" if needed.
17 pub(super) fn coerce(&mut self, from_ty: &Ty, to_ty: &Ty) -> bool { 21 pub(super) fn coerce(&mut self, from_ty: &Ty, to_ty: &Ty) -> bool {
18 let from_ty = self.resolve_ty_shallow(from_ty).into_owned(); 22 let from_ty = self.resolve_ty_shallow(from_ty);
19 let to_ty = self.resolve_ty_shallow(to_ty); 23 let to_ty = self.resolve_ty_shallow(to_ty);
20 self.coerce_inner(from_ty, &to_ty) 24 match self.coerce_inner(from_ty, &to_ty) {
25 Ok(result) => {
26 self.table.register_infer_ok(result);
27 true
28 }
29 Err(_) => {
30 // FIXME deal with error
31 false
32 }
33 }
21 } 34 }
22 35
23 /// Merge two types from different branches, with possible coercion. 36 /// Merge two types from different branches, with possible coercion.
24 /// 37 ///
25 /// Mostly this means trying to coerce one to the other, but 38 /// Mostly this means trying to coerce one to the other, but
26 /// - if we have two function types for different functions, we need to 39 /// - if we have two function types for different functions or closures, we need to
27 /// coerce both to function pointers; 40 /// coerce both to function pointers;
28 /// - if we were concerned with lifetime subtyping, we'd need to look for a 41 /// - if we were concerned with lifetime subtyping, we'd need to look for a
29 /// least upper bound. 42 /// least upper bound.
30 pub(super) fn coerce_merge_branch(&mut self, ty1: &Ty, ty2: &Ty) -> Ty { 43 pub(super) fn coerce_merge_branch(&mut self, id: Option<ExprId>, ty1: &Ty, ty2: &Ty) -> Ty {
31 if self.coerce(ty1, ty2) { 44 let ty1 = self.resolve_ty_shallow(ty1);
32 ty2.clone() 45 let ty2 = self.resolve_ty_shallow(ty2);
33 } else if self.coerce(ty2, ty1) { 46 // Special case: two function types. Try to coerce both to
47 // pointers to have a chance at getting a match. See
48 // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916
49 let sig = match (ty1.kind(&Interner), ty2.kind(&Interner)) {
50 (TyKind::FnDef(..), TyKind::FnDef(..))
51 | (TyKind::Closure(..), TyKind::FnDef(..))
52 | (TyKind::FnDef(..), TyKind::Closure(..))
53 | (TyKind::Closure(..), TyKind::Closure(..)) => {
54 // FIXME: we're ignoring safety here. To be more correct, if we have one FnDef and one Closure,
55 // we should be coercing the closure to a fn pointer of the safety of the FnDef
56 cov_mark::hit!(coerce_fn_reification);
57 let sig = ty1.callable_sig(self.db).expect("FnDef without callable sig");
58 Some(sig)
59 }
60 _ => None,
61 };
62 if let Some(sig) = sig {
63 let target_ty = TyKind::Function(sig.to_fn_ptr()).intern(&Interner);
64 let result1 = self.coerce_inner(ty1.clone(), &target_ty);
65 let result2 = self.coerce_inner(ty2.clone(), &target_ty);
66 if let (Ok(result1), Ok(result2)) = (result1, result2) {
67 self.table.register_infer_ok(result1);
68 self.table.register_infer_ok(result2);
69 return target_ty;
70 }
71 }
72
73 // It might not seem like it, but order is important here: ty1 is our
74 // "previous" type, ty2 is the "new" one being added. If the previous
75 // type is a type variable and the new one is `!`, trying it the other
76 // way around first would mean we make the type variable `!`, instead of
77 // just marking it as possibly diverging.
78 if self.coerce(&ty2, &ty1) {
34 ty1.clone() 79 ty1.clone()
80 } else if self.coerce(&ty1, &ty2) {
81 ty2.clone()
35 } else { 82 } else {
36 if let (TyKind::FnDef(..), TyKind::FnDef(..)) = 83 if let Some(id) = id {
37 (ty1.kind(&Interner), ty2.kind(&Interner)) 84 self.result
38 { 85 .type_mismatches
39 cov_mark::hit!(coerce_fn_reification); 86 .insert(id.into(), TypeMismatch { expected: ty1.clone(), actual: ty2.clone() });
40 // Special case: two function types. Try to coerce both to
41 // pointers to have a chance at getting a match. See
42 // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916
43 let sig1 = ty1.callable_sig(self.db).expect("FnDef without callable sig");
44 let sig2 = ty2.callable_sig(self.db).expect("FnDef without callable sig");
45 let ptr_ty1 = TyBuilder::fn_ptr(sig1);
46 let ptr_ty2 = TyBuilder::fn_ptr(sig2);
47 self.coerce_merge_branch(&ptr_ty1, &ptr_ty2)
48 } else {
49 cov_mark::hit!(coerce_merge_fail_fallback);
50 ty1.clone()
51 } 87 }
88 cov_mark::hit!(coerce_merge_fail_fallback);
89 ty1.clone()
52 } 90 }
53 } 91 }
54 92
55 fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool { 93 fn coerce_inner(&mut self, from_ty: Ty, to_ty: &Ty) -> InferResult {
56 match (from_ty.kind(&Interner), to_ty.kind(&Interner)) { 94 if from_ty.is_never() {
57 // Never type will make type variable to fallback to Never Type instead of Unknown. 95 // Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound
58 (TyKind::Never, TyKind::InferenceVar(tv, TyVariableKind::General)) => { 96 // type variable, we want `?T` to fallback to `!` if not
59 self.table.type_variable_table.set_diverging(*tv, true); 97 // otherwise constrained. An example where this arises:
60 return true; 98 //
99 // let _: Option<?T> = Some({ return; });
100 //
101 // here, we would coerce from `!` to `?T`.
102 match to_ty.kind(&Interner) {
103 TyKind::InferenceVar(tv, TyVariableKind::General) => {
104 self.table.set_diverging(*tv, true);
105 }
106 _ => {}
61 } 107 }
62 (TyKind::Never, _) => return true, 108 return Ok(InferOk { goals: Vec::new() });
109 }
63 110
64 // Trivial cases, this should go after `never` check to 111 // Consider coercing the subtype to a DST
65 // avoid infer result type to be never 112 if let Ok(ret) = self.try_coerce_unsized(&from_ty, &to_ty) {
66 _ => { 113 return Ok(ret);
67 if self.table.unify_inner_trivial(&from_ty, &to_ty, 0) { 114 }
68 return true; 115
69 } 116 // Examine the supertype and consider auto-borrowing.
117 match to_ty.kind(&Interner) {
118 TyKind::Raw(mt, _) => {
119 return self.coerce_ptr(from_ty, to_ty, *mt);
70 } 120 }
121 TyKind::Ref(mt, _, _) => {
122 return self.coerce_ref(from_ty, to_ty, *mt);
123 }
124 _ => {}
71 } 125 }
72 126
73 // Pointer weakening and function to pointer 127 match from_ty.kind(&Interner) {
74 match (from_ty.kind(&Interner), to_ty.kind(&Interner)) { 128 TyKind::FnDef(..) => {
75 // `*mut T` -> `*const T` 129 // Function items are coercible to any closure
76 (TyKind::Raw(_, inner), TyKind::Raw(m2 @ Mutability::Not, ..)) => { 130 // type; function pointers are not (that would
77 from_ty = TyKind::Raw(*m2, inner.clone()).intern(&Interner); 131 // require double indirection).
132 // Additionally, we permit coercion of function
133 // items to drop the unsafe qualifier.
134 self.coerce_from_fn_item(from_ty, to_ty)
78 } 135 }
79 // `&mut T` -> `&T` 136 TyKind::Function(from_fn_ptr) => {
80 (TyKind::Ref(_, lt, inner), TyKind::Ref(m2 @ Mutability::Not, ..)) => { 137 // We permit coercion of fn pointers to drop the
81 from_ty = TyKind::Ref(*m2, lt.clone(), inner.clone()).intern(&Interner); 138 // unsafe qualifier.
139 self.coerce_from_fn_pointer(from_ty.clone(), from_fn_ptr, to_ty)
82 } 140 }
83 // `&T` -> `*const T` 141 TyKind::Closure(_, from_substs) => {
84 // `&mut T` -> `*mut T`/`*const T` 142 // Non-capturing closures are coercible to
85 (TyKind::Ref(.., substs), &TyKind::Raw(m2 @ Mutability::Not, ..)) 143 // function pointers or unsafe function pointers.
86 | (TyKind::Ref(Mutability::Mut, _, substs), &TyKind::Raw(m2, ..)) => { 144 // It cannot convert closures that require unsafe.
87 from_ty = TyKind::Raw(m2, substs.clone()).intern(&Interner); 145 self.coerce_closure_to_fn(from_ty.clone(), from_substs, to_ty)
88 } 146 }
147 _ => {
148 // Otherwise, just use unification rules.
149 self.table.try_unify(&from_ty, to_ty)
150 }
151 }
152 }
89 153
90 // Illegal mutability conversion 154 fn coerce_ptr(&mut self, from_ty: Ty, to_ty: &Ty, to_mt: Mutability) -> InferResult {
91 (TyKind::Raw(Mutability::Not, ..), TyKind::Raw(Mutability::Mut, ..)) 155 let (_is_ref, from_mt, from_inner) = match from_ty.kind(&Interner) {
92 | (TyKind::Ref(Mutability::Not, ..), TyKind::Ref(Mutability::Mut, ..)) => return false, 156 TyKind::Ref(mt, _, ty) => (true, mt, ty),
157 TyKind::Raw(mt, ty) => (false, mt, ty),
158 _ => return self.table.try_unify(&from_ty, to_ty),
159 };
93 160
94 // `{function_type}` -> `fn()` 161 coerce_mutabilities(*from_mt, to_mt)?;
95 (TyKind::FnDef(..), TyKind::Function { .. }) => match from_ty.callable_sig(self.db) { 162
96 None => return false, 163 // Check that the types which they point at are compatible.
97 Some(sig) => { 164 let from_raw = TyKind::Raw(to_mt, from_inner.clone()).intern(&Interner);
98 from_ty = TyBuilder::fn_ptr(sig); 165 // FIXME: behavior differs based on is_ref once we're computing adjustments
99 } 166 self.table.try_unify(&from_raw, to_ty)
167 }
168
169 /// Reborrows `&mut A` to `&mut B` and `&(mut) A` to `&B`.
170 /// To match `A` with `B`, autoderef will be performed,
171 /// calling `deref`/`deref_mut` where necessary.
172 fn coerce_ref(&mut self, from_ty: Ty, to_ty: &Ty, to_mt: Mutability) -> InferResult {
173 match from_ty.kind(&Interner) {
174 TyKind::Ref(mt, _, _) => {
175 coerce_mutabilities(*mt, to_mt)?;
176 }
177 _ => return self.table.try_unify(&from_ty, to_ty),
178 };
179
180 // NOTE: this code is mostly copied and adapted from rustc, and
181 // currently more complicated than necessary, carrying errors around
182 // etc.. This complication will become necessary when we actually track
183 // details of coercion errors though, so I think it's useful to leave
184 // the structure like it is.
185
186 let canonicalized = self.canonicalize(from_ty.clone());
187 let autoderef = autoderef::autoderef(
188 self.db,
189 self.resolver.krate(),
190 InEnvironment {
191 goal: canonicalized.value.clone(),
192 environment: self.trait_env.env.clone(),
100 }, 193 },
194 );
195 let mut first_error = None;
196 let mut found = None;
101 197
102 (TyKind::Closure(.., substs), TyKind::Function { .. }) => { 198 for (autoderefs, referent_ty) in autoderef.enumerate() {
103 from_ty = substs.at(&Interner, 0).assert_ty_ref(&Interner).clone(); 199 if autoderefs == 0 {
200 // Don't let this pass, otherwise it would cause
201 // &T to autoref to &&T.
202 continue;
104 } 203 }
105 204
106 _ => {} 205 let referent_ty = canonicalized.decanonicalize_ty(referent_ty.value);
206
207 // At this point, we have deref'd `a` to `referent_ty`. So
208 // imagine we are coercing from `&'a mut Vec<T>` to `&'b mut [T]`.
209 // In the autoderef loop for `&'a mut Vec<T>`, we would get
210 // three callbacks:
211 //
212 // - `&'a mut Vec<T>` -- 0 derefs, just ignore it
213 // - `Vec<T>` -- 1 deref
214 // - `[T]` -- 2 deref
215 //
216 // At each point after the first callback, we want to
217 // check to see whether this would match out target type
218 // (`&'b mut [T]`) if we autoref'd it. We can't just
219 // compare the referent types, though, because we still
220 // have to consider the mutability. E.g., in the case
221 // we've been considering, we have an `&mut` reference, so
222 // the `T` in `[T]` needs to be unified with equality.
223 //
224 // Therefore, we construct reference types reflecting what
225 // the types will be after we do the final auto-ref and
226 // compare those. Note that this means we use the target
227 // mutability [1], since it may be that we are coercing
228 // from `&mut T` to `&U`.
229 let lt = static_lifetime(); // FIXME: handle lifetimes correctly, see rustc
230 let derefd_from_ty = TyKind::Ref(to_mt, lt, referent_ty).intern(&Interner);
231 match self.table.try_unify(&derefd_from_ty, to_ty) {
232 Ok(result) => {
233 found = Some(result);
234 break;
235 }
236 Err(err) => {
237 if first_error.is_none() {
238 first_error = Some(err);
239 }
240 }
241 }
107 } 242 }
108 243
109 if let Some(ret) = self.try_coerce_unsized(&from_ty, &to_ty) { 244 // Extract type or return an error. We return the first error
110 return ret; 245 // we got, which should be from relating the "base" type
246 // (e.g., in example above, the failure from relating `Vec<T>`
247 // to the target type), since that should be the least
248 // confusing.
249 let result = match found {
250 Some(d) => d,
251 None => {
252 let err = first_error.expect("coerce_borrowed_pointer had no error");
253 return Err(err);
254 }
255 };
256
257 Ok(result)
258 }
259
260 /// Attempts to coerce from the type of a Rust function item into a function pointer.
261 fn coerce_from_fn_item(&mut self, from_ty: Ty, to_ty: &Ty) -> InferResult {
262 match to_ty.kind(&Interner) {
263 TyKind::Function(_) => {
264 let from_sig = from_ty.callable_sig(self.db).expect("FnDef had no sig");
265
266 // FIXME check ABI: Intrinsics are not coercible to function pointers
267 // FIXME Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396)
268
269 // FIXME rustc normalizes assoc types in the sig here, not sure if necessary
270
271 let from_sig = from_sig.to_fn_ptr();
272 let from_fn_pointer = TyKind::Function(from_sig.clone()).intern(&Interner);
273 let ok = self.coerce_from_safe_fn(from_fn_pointer, &from_sig, to_ty)?;
274
275 Ok(ok)
276 }
277 _ => self.table.try_unify(&from_ty, to_ty),
111 } 278 }
279 }
280
281 fn coerce_from_fn_pointer(
282 &mut self,
283 from_ty: Ty,
284 from_f: &FnPointer,
285 to_ty: &Ty,
286 ) -> InferResult {
287 self.coerce_from_safe_fn(from_ty, from_f, to_ty)
288 }
112 289
113 // Auto Deref if cannot coerce 290 fn coerce_from_safe_fn(
114 match (from_ty.kind(&Interner), to_ty.kind(&Interner)) { 291 &mut self,
115 // FIXME: DerefMut 292 from_ty: Ty,
116 (TyKind::Ref(.., st1), TyKind::Ref(.., st2)) => { 293 from_fn_ptr: &FnPointer,
117 self.unify_autoderef_behind_ref(st1, st2) 294 to_ty: &Ty,
295 ) -> InferResult {
296 if let TyKind::Function(to_fn_ptr) = to_ty.kind(&Interner) {
297 if let (chalk_ir::Safety::Safe, chalk_ir::Safety::Unsafe) =
298 (from_fn_ptr.sig.safety, to_fn_ptr.sig.safety)
299 {
300 let from_unsafe =
301 TyKind::Function(safe_to_unsafe_fn_ty(from_fn_ptr.clone())).intern(&Interner);
302 return self.table.try_unify(&from_unsafe, to_ty);
118 } 303 }
304 }
305 self.table.try_unify(&from_ty, to_ty)
306 }
119 307
120 // Otherwise, normal unify 308 /// Attempts to coerce from the type of a non-capturing closure into a
121 _ => self.unify(&from_ty, to_ty), 309 /// function pointer.
310 fn coerce_closure_to_fn(
311 &mut self,
312 from_ty: Ty,
313 from_substs: &Substitution,
314 to_ty: &Ty,
315 ) -> InferResult {
316 match to_ty.kind(&Interner) {
317 TyKind::Function(fn_ty) /* if from_substs is non-capturing (FIXME) */ => {
318 // We coerce the closure, which has fn type
319 // `extern "rust-call" fn((arg0,arg1,...)) -> _`
320 // to
321 // `fn(arg0,arg1,...) -> _`
322 // or
323 // `unsafe fn(arg0,arg1,...) -> _`
324 let safety = fn_ty.sig.safety;
325 let pointer_ty = coerce_closure_fn_ty(from_substs, safety);
326 self.table.try_unify(&pointer_ty, to_ty)
327 }
328 _ => self.table.try_unify(&from_ty, to_ty),
122 } 329 }
123 } 330 }
124 331
125 /// Coerce a type using `from_ty: CoerceUnsized<ty_ty>` 332 /// Coerce a type using `from_ty: CoerceUnsized<ty_ty>`
126 /// 333 ///
127 /// See: https://doc.rust-lang.org/nightly/std/marker/trait.CoerceUnsized.html 334 /// See: https://doc.rust-lang.org/nightly/std/marker/trait.CoerceUnsized.html
128 fn try_coerce_unsized(&mut self, from_ty: &Ty, to_ty: &Ty) -> Option<bool> { 335 fn try_coerce_unsized(&mut self, from_ty: &Ty, to_ty: &Ty) -> InferResult {
336 // These 'if' statements require some explanation.
337 // The `CoerceUnsized` trait is special - it is only
338 // possible to write `impl CoerceUnsized<B> for A` where
339 // A and B have 'matching' fields. This rules out the following
340 // two types of blanket impls:
341 //
342 // `impl<T> CoerceUnsized<T> for SomeType`
343 // `impl<T> CoerceUnsized<SomeType> for T`
344 //
345 // Both of these trigger a special `CoerceUnsized`-related error (E0376)
346 //
347 // We can take advantage of this fact to avoid performing unecessary work.
348 // If either `source` or `target` is a type variable, then any applicable impl
349 // would need to be generic over the self-type (`impl<T> CoerceUnsized<SomeType> for T`)
350 // or generic over the `CoerceUnsized` type parameter (`impl<T> CoerceUnsized<T> for
351 // SomeType`).
352 //
353 // However, these are exactly the kinds of impls which are forbidden by
354 // the compiler! Therefore, we can be sure that coercion will always fail
355 // when either the source or target type is a type variable. This allows us
356 // to skip performing any trait selection, and immediately bail out.
357 if from_ty.is_ty_var() {
358 return Err(TypeError);
359 }
360 if to_ty.is_ty_var() {
361 return Err(TypeError);
362 }
363
364 // Handle reborrows before trying to solve `Source: CoerceUnsized<Target>`.
365 let coerce_from = match (from_ty.kind(&Interner), to_ty.kind(&Interner)) {
366 (TyKind::Ref(from_mt, _, from_inner), TyKind::Ref(to_mt, _, _)) => {
367 coerce_mutabilities(*from_mt, *to_mt)?;
368
369 let lt = static_lifetime();
370 TyKind::Ref(*to_mt, lt, from_inner.clone()).intern(&Interner)
371 }
372 (TyKind::Ref(from_mt, _, from_inner), TyKind::Raw(to_mt, _)) => {
373 coerce_mutabilities(*from_mt, *to_mt)?;
374
375 TyKind::Raw(*to_mt, from_inner.clone()).intern(&Interner)
376 }
377 _ => from_ty.clone(),
378 };
379
129 let krate = self.resolver.krate().unwrap(); 380 let krate = self.resolver.krate().unwrap();
130 let coerce_unsized_trait = match self.db.lang_item(krate, "coerce_unsized".into()) { 381 let coerce_unsized_trait = match self.db.lang_item(krate, "coerce_unsized".into()) {
131 Some(LangItemTarget::TraitId(trait_)) => trait_, 382 Some(LangItemTarget::TraitId(trait_)) => trait_,
132 _ => return None, 383 _ => return Err(TypeError),
133 }; 384 };
134 385
135 let trait_ref = { 386 let trait_ref = {
136 let b = TyBuilder::trait_ref(self.db, coerce_unsized_trait); 387 let b = TyBuilder::trait_ref(self.db, coerce_unsized_trait);
137 if b.remaining() != 2 { 388 if b.remaining() != 2 {
138 // The CoerceUnsized trait should have two generic params: Self and T. 389 // The CoerceUnsized trait should have two generic params: Self and T.
139 return None; 390 return Err(TypeError);
140 } 391 }
141 b.push(from_ty.clone()).push(to_ty.clone()).build() 392 b.push(coerce_from.clone()).push(to_ty.clone()).build()
142 }; 393 };
143 394
144 let goal = InEnvironment::new(&self.trait_env.env, trait_ref.cast(&Interner)); 395 let goal: InEnvironment<DomainGoal> =
396 InEnvironment::new(&self.trait_env.env, trait_ref.cast(&Interner));
145 397
146 let canonicalizer = self.canonicalizer(); 398 let canonicalized = self.canonicalize(goal);
147 let canonicalized = canonicalizer.canonicalize_obligation(goal);
148 399
149 let solution = self.db.trait_solve(krate, canonicalized.value.clone())?; 400 // FIXME: rustc's coerce_unsized is more specialized -- it only tries to
401 // solve `CoerceUnsized` and `Unsize` goals at this point and leaves the
402 // rest for later. Also, there's some logic about sized type variables.
403 // Need to find out in what cases this is necessary
404 let solution = self
405 .db
406 .trait_solve(krate, canonicalized.value.clone().cast(&Interner))
407 .ok_or(TypeError)?;
150 408
151 match solution { 409 match solution {
152 Solution::Unique(v) => { 410 Solution::Unique(v) => {
153 canonicalized.apply_solution( 411 canonicalized.apply_solution(
154 self, 412 &mut self.table,
155 Canonical { 413 Canonical {
156 binders: v.binders, 414 binders: v.binders,
157 // FIXME handle constraints 415 // FIXME handle constraints
@@ -159,38 +417,40 @@ impl<'a> InferenceContext<'a> {
159 }, 417 },
160 ); 418 );
161 } 419 }
162 _ => return None, 420 // FIXME: should we accept ambiguous results here?
421 _ => return Err(TypeError),
163 }; 422 };
164 423
165 Some(true) 424 Ok(InferOk { goals: Vec::new() })
166 } 425 }
426}
167 427
168 /// Unify `from_ty` to `to_ty` with optional auto Deref 428fn coerce_closure_fn_ty(closure_substs: &Substitution, safety: chalk_ir::Safety) -> Ty {
169 /// 429 let closure_sig = closure_substs.at(&Interner, 0).assert_ty_ref(&Interner).clone();
170 /// Note that the parameters are already stripped the outer reference. 430 match closure_sig.kind(&Interner) {
171 fn unify_autoderef_behind_ref(&mut self, from_ty: &Ty, to_ty: &Ty) -> bool { 431 TyKind::Function(fn_ty) => TyKind::Function(FnPointer {
172 let canonicalized = self.canonicalizer().canonicalize_ty(from_ty.clone()); 432 num_binders: fn_ty.num_binders,
173 let to_ty = self.resolve_ty_shallow(&to_ty); 433 sig: FnSig { safety, ..fn_ty.sig },
174 // FIXME: Auto DerefMut 434 substitution: fn_ty.substitution.clone(),
175 for derefed_ty in autoderef::autoderef( 435 })
176 self.db, 436 .intern(&Interner),
177 self.resolver.krate(), 437 _ => TyKind::Error.intern(&Interner),
178 InEnvironment { 438 }
179 goal: canonicalized.value.clone(), 439}
180 environment: self.trait_env.env.clone(), 440
181 }, 441fn safe_to_unsafe_fn_ty(fn_ty: FnPointer) -> FnPointer {
182 ) { 442 FnPointer {
183 let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); 443 num_binders: fn_ty.num_binders,
184 let from_ty = self.resolve_ty_shallow(&derefed_ty); 444 sig: FnSig { safety: chalk_ir::Safety::Unsafe, ..fn_ty.sig },
185 // Stop when constructor matches. 445 substitution: fn_ty.substitution,
186 if from_ty.equals_ctor(&to_ty) { 446 }
187 // It will not recurse to `coerce`. 447}
188 return self.table.unify(&from_ty, &to_ty);
189 } else if self.table.unify_inner_trivial(&derefed_ty, &to_ty, 0) {
190 return true;
191 }
192 }
193 448
194 false 449fn coerce_mutabilities(from: Mutability, to: Mutability) -> Result<(), TypeError> {
450 match (from, to) {
451 (Mutability::Mut, Mutability::Mut)
452 | (Mutability::Mut, Mutability::Not)
453 | (Mutability::Not, Mutability::Not) => Ok(()),
454 (Mutability::Not, Mutability::Mut) => Err(TypeError),
195 } 455 }
196} 456}
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index 7278faeec..08c05c67c 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -35,39 +35,43 @@ use super::{
35impl<'a> InferenceContext<'a> { 35impl<'a> InferenceContext<'a> {
36 pub(super) fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { 36 pub(super) fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
37 let ty = self.infer_expr_inner(tgt_expr, expected); 37 let ty = self.infer_expr_inner(tgt_expr, expected);
38 if ty.is_never() { 38 if self.resolve_ty_shallow(&ty).is_never() {
39 // Any expression that produces a value of type `!` must have diverged 39 // Any expression that produces a value of type `!` must have diverged
40 self.diverges = Diverges::Always; 40 self.diverges = Diverges::Always;
41 } 41 }
42 let could_unify = self.unify(&ty, &expected.ty); 42 if let Some(expected_ty) = expected.only_has_type(&mut self.table) {
43 if !could_unify { 43 let could_unify = self.unify(&ty, &expected_ty);
44 self.result.type_mismatches.insert( 44 if !could_unify {
45 tgt_expr.into(), 45 self.result.type_mismatches.insert(
46 TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() }, 46 tgt_expr.into(),
47 ); 47 TypeMismatch { expected: expected_ty.clone(), actual: ty.clone() },
48 );
49 }
48 } 50 }
49 self.resolve_ty_as_possible(ty) 51 ty
50 } 52 }
51 53
52 /// Infer type of expression with possibly implicit coerce to the expected type. 54 /// Infer type of expression with possibly implicit coerce to the expected type.
53 /// Return the type after possible coercion. 55 /// Return the type after possible coercion.
54 pub(super) fn infer_expr_coerce(&mut self, expr: ExprId, expected: &Expectation) -> Ty { 56 pub(super) fn infer_expr_coerce(&mut self, expr: ExprId, expected: &Expectation) -> Ty {
55 let ty = self.infer_expr_inner(expr, &expected); 57 let ty = self.infer_expr_inner(expr, &expected);
56 let ty = if !self.coerce(&ty, &expected.coercion_target()) { 58 let ty = if let Some(target) = expected.only_has_type(&mut self.table) {
57 self.result.type_mismatches.insert( 59 if !self.coerce(&ty, &target) {
58 expr.into(), 60 self.result.type_mismatches.insert(
59 TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() }, 61 expr.into(),
60 ); 62 TypeMismatch { expected: target.clone(), actual: ty.clone() },
61 // Return actual type when type mismatch. 63 );
62 // This is needed for diagnostic when return type mismatch. 64 // Return actual type when type mismatch.
63 ty 65 // This is needed for diagnostic when return type mismatch.
64 } else if expected.coercion_target().is_unknown() { 66 ty
65 ty 67 } else {
68 target.clone()
69 }
66 } else { 70 } else {
67 expected.ty.clone() 71 ty
68 }; 72 };
69 73
70 self.resolve_ty_as_possible(ty) 74 ty
71 } 75 }
72 76
73 fn callable_sig_from_fn_trait(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> { 77 fn callable_sig_from_fn_trait(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> {
@@ -98,10 +102,10 @@ impl<'a> InferenceContext<'a> {
98 goal: projection.trait_ref(self.db).cast(&Interner), 102 goal: projection.trait_ref(self.db).cast(&Interner),
99 environment: trait_env, 103 environment: trait_env,
100 }; 104 };
101 let canonical = self.canonicalizer().canonicalize_obligation(obligation.clone()); 105 let canonical = self.canonicalize(obligation.clone());
102 if self.db.trait_solve(krate, canonical.value).is_some() { 106 if self.db.trait_solve(krate, canonical.value.cast(&Interner)).is_some() {
103 self.push_obligation(obligation.goal); 107 self.push_obligation(obligation.goal);
104 let return_ty = self.normalize_projection_ty(projection); 108 let return_ty = self.table.normalize_projection_ty(projection);
105 Some((arg_tys, return_ty)) 109 Some((arg_tys, return_ty))
106 } else { 110 } else {
107 None 111 None
@@ -131,17 +135,21 @@ impl<'a> InferenceContext<'a> {
131 let condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); 135 let condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
132 let mut both_arms_diverge = Diverges::Always; 136 let mut both_arms_diverge = Diverges::Always;
133 137
138 let mut result_ty = self.table.new_type_var();
134 let then_ty = self.infer_expr_inner(*then_branch, &expected); 139 let then_ty = self.infer_expr_inner(*then_branch, &expected);
135 both_arms_diverge &= mem::replace(&mut self.diverges, Diverges::Maybe); 140 both_arms_diverge &= mem::replace(&mut self.diverges, Diverges::Maybe);
141 result_ty = self.coerce_merge_branch(Some(*then_branch), &result_ty, &then_ty);
136 let else_ty = match else_branch { 142 let else_ty = match else_branch {
137 Some(else_branch) => self.infer_expr_inner(*else_branch, &expected), 143 Some(else_branch) => self.infer_expr_inner(*else_branch, &expected),
138 None => TyBuilder::unit(), 144 None => TyBuilder::unit(),
139 }; 145 };
140 both_arms_diverge &= self.diverges; 146 both_arms_diverge &= self.diverges;
147 // FIXME: create a synthetic `else {}` so we have something to refer to here instead of None?
148 result_ty = self.coerce_merge_branch(*else_branch, &result_ty, &else_ty);
141 149
142 self.diverges = condition_diverges | both_arms_diverge; 150 self.diverges = condition_diverges | both_arms_diverge;
143 151
144 self.coerce_merge_branch(&then_ty, &else_ty) 152 result_ty
145 } 153 }
146 Expr::Block { statements, tail, label, id: _ } => { 154 Expr::Block { statements, tail, label, id: _ } => {
147 let old_resolver = mem::replace( 155 let old_resolver = mem::replace(
@@ -277,12 +285,13 @@ impl<'a> InferenceContext<'a> {
277 // Eagerly try to relate the closure type with the expected 285 // Eagerly try to relate the closure type with the expected
278 // type, otherwise we often won't have enough information to 286 // type, otherwise we often won't have enough information to
279 // infer the body. 287 // infer the body.
280 self.coerce(&closure_ty, &expected.ty); 288 if let Some(t) = expected.only_has_type(&mut self.table) {
289 self.coerce(&closure_ty, &t);
290 }
281 291
282 // Now go through the argument patterns 292 // Now go through the argument patterns
283 for (arg_pat, arg_ty) in args.iter().zip(sig_tys) { 293 for (arg_pat, arg_ty) in args.iter().zip(sig_tys) {
284 let resolved = self.resolve_ty_as_possible(arg_ty); 294 self.infer_pat(*arg_pat, &arg_ty, BindingMode::default());
285 self.infer_pat(*arg_pat, &resolved, BindingMode::default());
286 } 295 }
287 296
288 let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); 297 let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
@@ -297,13 +306,13 @@ impl<'a> InferenceContext<'a> {
297 } 306 }
298 Expr::Call { callee, args } => { 307 Expr::Call { callee, args } => {
299 let callee_ty = self.infer_expr(*callee, &Expectation::none()); 308 let callee_ty = self.infer_expr(*callee, &Expectation::none());
300 let canonicalized = self.canonicalizer().canonicalize_ty(callee_ty.clone()); 309 let canonicalized = self.canonicalize(callee_ty.clone());
301 let mut derefs = autoderef( 310 let mut derefs = autoderef(
302 self.db, 311 self.db,
303 self.resolver.krate(), 312 self.resolver.krate(),
304 InEnvironment { 313 InEnvironment {
305 goal: canonicalized.value.clone(), 314 goal: canonicalized.value.clone(),
306 environment: self.trait_env.env.clone(), 315 environment: self.table.trait_env.env.clone(),
307 }, 316 },
308 ); 317 );
309 let (param_tys, ret_ty): (Vec<Ty>, Ty) = derefs 318 let (param_tys, ret_ty): (Vec<Ty>, Ty) = derefs
@@ -350,7 +359,7 @@ impl<'a> InferenceContext<'a> {
350 359
351 let arm_ty = self.infer_expr_inner(arm.expr, &expected); 360 let arm_ty = self.infer_expr_inner(arm.expr, &expected);
352 all_arms_diverge &= self.diverges; 361 all_arms_diverge &= self.diverges;
353 result_ty = self.coerce_merge_branch(&result_ty, &arm_ty); 362 result_ty = self.coerce_merge_branch(Some(arm.expr), &result_ty, &arm_ty);
354 } 363 }
355 364
356 self.diverges = matchee_diverges | all_arms_diverge; 365 self.diverges = matchee_diverges | all_arms_diverge;
@@ -364,12 +373,6 @@ impl<'a> InferenceContext<'a> {
364 } 373 }
365 Expr::Continue { .. } => TyKind::Never.intern(&Interner), 374 Expr::Continue { .. } => TyKind::Never.intern(&Interner),
366 Expr::Break { expr, label } => { 375 Expr::Break { expr, label } => {
367 let val_ty = if let Some(expr) = expr {
368 self.infer_expr(*expr, &Expectation::none())
369 } else {
370 TyBuilder::unit()
371 };
372
373 let last_ty = 376 let last_ty =
374 if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) { 377 if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) {
375 ctxt.break_ty.clone() 378 ctxt.break_ty.clone()
@@ -377,7 +380,14 @@ impl<'a> InferenceContext<'a> {
377 self.err_ty() 380 self.err_ty()
378 }; 381 };
379 382
380 let merged_type = self.coerce_merge_branch(&last_ty, &val_ty); 383 let val_ty = if let Some(expr) = expr {
384 self.infer_expr(*expr, &Expectation::none())
385 } else {
386 TyBuilder::unit()
387 };
388
389 // FIXME: create a synthetic `()` during lowering so we have something to refer to here?
390 let merged_type = self.coerce_merge_branch(*expr, &last_ty, &val_ty);
381 391
382 if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) { 392 if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) {
383 ctxt.break_ty = merged_type; 393 ctxt.break_ty = merged_type;
@@ -411,7 +421,9 @@ impl<'a> InferenceContext<'a> {
411 self.write_variant_resolution(tgt_expr.into(), variant); 421 self.write_variant_resolution(tgt_expr.into(), variant);
412 } 422 }
413 423
414 self.unify(&ty, &expected.ty); 424 if let Some(t) = expected.only_has_type(&mut self.table) {
425 self.unify(&ty, &t);
426 }
415 427
416 let substs = ty 428 let substs = ty
417 .as_adt() 429 .as_adt()
@@ -442,7 +454,7 @@ impl<'a> InferenceContext<'a> {
442 } 454 }
443 Expr::Field { expr, name } => { 455 Expr::Field { expr, name } => {
444 let receiver_ty = self.infer_expr_inner(*expr, &Expectation::none()); 456 let receiver_ty = self.infer_expr_inner(*expr, &Expectation::none());
445 let canonicalized = self.canonicalizer().canonicalize_ty(receiver_ty); 457 let canonicalized = self.canonicalize(receiver_ty);
446 let ty = autoderef::autoderef( 458 let ty = autoderef::autoderef(
447 self.db, 459 self.db,
448 self.resolver.krate(), 460 self.resolver.krate(),
@@ -514,6 +526,7 @@ impl<'a> InferenceContext<'a> {
514 self.resolve_associated_type(inner_ty, self.resolve_ops_try_ok()) 526 self.resolve_associated_type(inner_ty, self.resolve_ops_try_ok())
515 } 527 }
516 Expr::Cast { expr, type_ref } => { 528 Expr::Cast { expr, type_ref } => {
529 // FIXME: propagate the "castable to" expectation (and find a test case that shows this is necessary)
517 let _inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); 530 let _inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
518 let cast_ty = self.make_ty(type_ref); 531 let cast_ty = self.make_ty(type_ref);
519 // FIXME check the cast... 532 // FIXME check the cast...
@@ -521,15 +534,17 @@ impl<'a> InferenceContext<'a> {
521 } 534 }
522 Expr::Ref { expr, rawness, mutability } => { 535 Expr::Ref { expr, rawness, mutability } => {
523 let mutability = lower_to_chalk_mutability(*mutability); 536 let mutability = lower_to_chalk_mutability(*mutability);
524 let expectation = if let Some((exp_inner, exp_rawness, exp_mutability)) = 537 let expectation = if let Some((exp_inner, exp_rawness, exp_mutability)) = expected
525 &expected.ty.as_reference_or_ptr() 538 .only_has_type(&mut self.table)
539 .as_ref()
540 .and_then(|t| t.as_reference_or_ptr())
526 { 541 {
527 if *exp_mutability == Mutability::Mut && mutability == Mutability::Not { 542 if exp_mutability == Mutability::Mut && mutability == Mutability::Not {
528 // FIXME: throw type error - expected mut reference but found shared ref, 543 // FIXME: record type error - expected mut reference but found shared ref,
529 // which cannot be coerced 544 // which cannot be coerced
530 } 545 }
531 if *exp_rawness == Rawness::Ref && *rawness == Rawness::RawPtr { 546 if exp_rawness == Rawness::Ref && *rawness == Rawness::RawPtr {
532 // FIXME: throw type error - expected reference but found ptr, 547 // FIXME: record type error - expected reference but found ptr,
533 // which cannot be coerced 548 // which cannot be coerced
534 } 549 }
535 Expectation::rvalue_hint(Ty::clone(exp_inner)) 550 Expectation::rvalue_hint(Ty::clone(exp_inner))
@@ -556,10 +571,11 @@ impl<'a> InferenceContext<'a> {
556 } 571 }
557 Expr::UnaryOp { expr, op } => { 572 Expr::UnaryOp { expr, op } => {
558 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); 573 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
574 let inner_ty = self.resolve_ty_shallow(&inner_ty);
559 match op { 575 match op {
560 UnaryOp::Deref => match self.resolver.krate() { 576 UnaryOp::Deref => match self.resolver.krate() {
561 Some(krate) => { 577 Some(krate) => {
562 let canonicalized = self.canonicalizer().canonicalize_ty(inner_ty); 578 let canonicalized = self.canonicalize(inner_ty);
563 match autoderef::deref( 579 match autoderef::deref(
564 self.db, 580 self.db,
565 krate, 581 krate,
@@ -612,8 +628,10 @@ impl<'a> InferenceContext<'a> {
612 _ => Expectation::none(), 628 _ => Expectation::none(),
613 }; 629 };
614 let lhs_ty = self.infer_expr(*lhs, &lhs_expectation); 630 let lhs_ty = self.infer_expr(*lhs, &lhs_expectation);
631 let lhs_ty = self.resolve_ty_shallow(&lhs_ty);
615 let rhs_expectation = op::binary_op_rhs_expectation(*op, lhs_ty.clone()); 632 let rhs_expectation = op::binary_op_rhs_expectation(*op, lhs_ty.clone());
616 let rhs_ty = self.infer_expr(*rhs, &Expectation::has_type(rhs_expectation)); 633 let rhs_ty = self.infer_expr(*rhs, &Expectation::has_type(rhs_expectation));
634 let rhs_ty = self.resolve_ty_shallow(&rhs_ty);
617 635
618 let ret = op::binary_op_return_ty(*op, lhs_ty.clone(), rhs_ty.clone()); 636 let ret = op::binary_op_return_ty(*op, lhs_ty.clone(), rhs_ty.clone());
619 637
@@ -676,7 +694,7 @@ impl<'a> InferenceContext<'a> {
676 if let (Some(index_trait), Some(krate)) = 694 if let (Some(index_trait), Some(krate)) =
677 (self.resolve_ops_index(), self.resolver.krate()) 695 (self.resolve_ops_index(), self.resolver.krate())
678 { 696 {
679 let canonicalized = self.canonicalizer().canonicalize_ty(base_ty); 697 let canonicalized = self.canonicalize(base_ty);
680 let self_ty = method_resolution::resolve_indexing_op( 698 let self_ty = method_resolution::resolve_indexing_op(
681 self.db, 699 self.db,
682 &canonicalized.value, 700 &canonicalized.value,
@@ -696,8 +714,12 @@ impl<'a> InferenceContext<'a> {
696 } 714 }
697 } 715 }
698 Expr::Tuple { exprs } => { 716 Expr::Tuple { exprs } => {
699 let mut tys = match expected.ty.kind(&Interner) { 717 let mut tys = match expected
700 TyKind::Tuple(_, substs) => substs 718 .only_has_type(&mut self.table)
719 .as_ref()
720 .map(|t| t.kind(&Interner))
721 {
722 Some(TyKind::Tuple(_, substs)) => substs
701 .iter(&Interner) 723 .iter(&Interner)
702 .map(|a| a.assert_ty_ref(&Interner).clone()) 724 .map(|a| a.assert_ty_ref(&Interner).clone())
703 .chain(repeat_with(|| self.table.new_type_var())) 725 .chain(repeat_with(|| self.table.new_type_var()))
@@ -713,14 +735,16 @@ impl<'a> InferenceContext<'a> {
713 TyKind::Tuple(tys.len(), Substitution::from_iter(&Interner, tys)).intern(&Interner) 735 TyKind::Tuple(tys.len(), Substitution::from_iter(&Interner, tys)).intern(&Interner)
714 } 736 }
715 Expr::Array(array) => { 737 Expr::Array(array) => {
716 let elem_ty = match expected.ty.kind(&Interner) { 738 let elem_ty =
717 TyKind::Array(st, _) | TyKind::Slice(st) => st.clone(), 739 match expected.to_option(&mut self.table).as_ref().map(|t| t.kind(&Interner)) {
718 _ => self.table.new_type_var(), 740 Some(TyKind::Array(st, _)) | Some(TyKind::Slice(st)) => st.clone(),
719 }; 741 _ => self.table.new_type_var(),
742 };
720 743
721 let len = match array { 744 let len = match array {
722 Array::ElementList(items) => { 745 Array::ElementList(items) => {
723 for expr in items.iter() { 746 for expr in items.iter() {
747 // FIXME: use CoerceMany (coerce_merge_branch)
724 self.infer_expr_coerce(*expr, &Expectation::has_type(elem_ty.clone())); 748 self.infer_expr_coerce(*expr, &Expectation::has_type(elem_ty.clone()));
725 } 749 }
726 Some(items.len() as u64) 750 Some(items.len() as u64)
@@ -785,7 +809,6 @@ impl<'a> InferenceContext<'a> {
785 }; 809 };
786 // use a new type variable if we got unknown here 810 // use a new type variable if we got unknown here
787 let ty = self.insert_type_vars_shallow(ty); 811 let ty = self.insert_type_vars_shallow(ty);
788 let ty = self.resolve_ty_as_possible(ty);
789 self.write_expr_ty(tgt_expr, ty.clone()); 812 self.write_expr_ty(tgt_expr, ty.clone());
790 ty 813 ty
791 } 814 }
@@ -813,7 +836,6 @@ impl<'a> InferenceContext<'a> {
813 } 836 }
814 } 837 }
815 838
816 let ty = self.resolve_ty_as_possible(ty);
817 self.infer_pat(*pat, &ty, BindingMode::default()); 839 self.infer_pat(*pat, &ty, BindingMode::default());
818 } 840 }
819 Statement::Expr { expr, .. } => { 841 Statement::Expr { expr, .. } => {
@@ -836,7 +858,9 @@ impl<'a> InferenceContext<'a> {
836 // we don't even make an attempt at coercion 858 // we don't even make an attempt at coercion
837 self.table.new_maybe_never_var() 859 self.table.new_maybe_never_var()
838 } else { 860 } else {
839 self.coerce(&TyBuilder::unit(), &expected.coercion_target()); 861 if let Some(t) = expected.only_has_type(&mut self.table) {
862 self.coerce(&TyBuilder::unit(), &t);
863 }
840 TyBuilder::unit() 864 TyBuilder::unit()
841 } 865 }
842 }; 866 };
@@ -852,7 +876,7 @@ impl<'a> InferenceContext<'a> {
852 generic_args: Option<&GenericArgs>, 876 generic_args: Option<&GenericArgs>,
853 ) -> Ty { 877 ) -> Ty {
854 let receiver_ty = self.infer_expr(receiver, &Expectation::none()); 878 let receiver_ty = self.infer_expr(receiver, &Expectation::none());
855 let canonicalized_receiver = self.canonicalizer().canonicalize_ty(receiver_ty.clone()); 879 let canonicalized_receiver = self.canonicalize(receiver_ty.clone());
856 880
857 let traits_in_scope = self.resolver.traits_in_scope(self.db.upcast()); 881 let traits_in_scope = self.resolver.traits_in_scope(self.db.upcast());
858 882
@@ -891,7 +915,8 @@ impl<'a> InferenceContext<'a> {
891 }; 915 };
892 // Apply autoref so the below unification works correctly 916 // Apply autoref so the below unification works correctly
893 // FIXME: return correct autorefs from lookup_method 917 // FIXME: return correct autorefs from lookup_method
894 let actual_receiver_ty = match expected_receiver_ty.as_reference() { 918 let actual_receiver_ty = match self.resolve_ty_shallow(&expected_receiver_ty).as_reference()
919 {
895 Some((_, lifetime, mutability)) => { 920 Some((_, lifetime, mutability)) => {
896 TyKind::Ref(mutability, lifetime, derefed_receiver_ty).intern(&Interner) 921 TyKind::Ref(mutability, lifetime, derefed_receiver_ty).intern(&Interner)
897 } 922 }
@@ -971,6 +996,7 @@ impl<'a> InferenceContext<'a> {
971 } 996 }
972 997
973 fn register_obligations_for_call(&mut self, callable_ty: &Ty) { 998 fn register_obligations_for_call(&mut self, callable_ty: &Ty) {
999 let callable_ty = self.resolve_ty_shallow(&callable_ty);
974 if let TyKind::FnDef(fn_def, parameters) = callable_ty.kind(&Interner) { 1000 if let TyKind::FnDef(fn_def, parameters) = callable_ty.kind(&Interner) {
975 let def: CallableDefId = from_chalk(self.db, *fn_def); 1001 let def: CallableDefId = from_chalk(self.db, *fn_def);
976 let generic_predicates = self.db.generic_predicates(def.into()); 1002 let generic_predicates = self.db.generic_predicates(def.into());
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index b15f4977d..9c8e3b6ae 100644
--- a/crates/hir_ty/src/infer/pat.rs
+++ b/crates/hir_ty/src/infer/pat.rs
@@ -94,14 +94,15 @@ impl<'a> InferenceContext<'a> {
94 pub(super) fn infer_pat( 94 pub(super) fn infer_pat(
95 &mut self, 95 &mut self,
96 pat: PatId, 96 pat: PatId,
97 mut expected: &Ty, 97 expected: &Ty,
98 mut default_bm: BindingMode, 98 mut default_bm: BindingMode,
99 ) -> Ty { 99 ) -> Ty {
100 let body = Arc::clone(&self.body); // avoid borrow checker problem 100 let body = Arc::clone(&self.body); // avoid borrow checker problem
101 let mut expected = self.resolve_ty_shallow(expected);
101 102
102 if is_non_ref_pat(&body, pat) { 103 if is_non_ref_pat(&body, pat) {
103 while let Some((inner, _lifetime, mutability)) = expected.as_reference() { 104 while let Some((inner, _lifetime, mutability)) = expected.as_reference() {
104 expected = inner; 105 expected = self.resolve_ty_shallow(inner);
105 default_bm = match default_bm { 106 default_bm = match default_bm {
106 BindingMode::Move => BindingMode::Ref(mutability), 107 BindingMode::Move => BindingMode::Ref(mutability),
107 BindingMode::Ref(Mutability::Not) => BindingMode::Ref(Mutability::Not), 108 BindingMode::Ref(Mutability::Not) => BindingMode::Ref(Mutability::Not),
@@ -147,9 +148,9 @@ impl<'a> InferenceContext<'a> {
147 } 148 }
148 Pat::Or(ref pats) => { 149 Pat::Or(ref pats) => {
149 if let Some((first_pat, rest)) = pats.split_first() { 150 if let Some((first_pat, rest)) = pats.split_first() {
150 let ty = self.infer_pat(*first_pat, expected, default_bm); 151 let ty = self.infer_pat(*first_pat, &expected, default_bm);
151 for pat in rest { 152 for pat in rest {
152 self.infer_pat(*pat, expected, default_bm); 153 self.infer_pat(*pat, &expected, default_bm);
153 } 154 }
154 ty 155 ty
155 } else { 156 } else {
@@ -173,13 +174,13 @@ impl<'a> InferenceContext<'a> {
173 Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat( 174 Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat(
174 p.as_deref(), 175 p.as_deref(),
175 subpats, 176 subpats,
176 expected, 177 &expected,
177 default_bm, 178 default_bm,
178 pat, 179 pat,
179 *ellipsis, 180 *ellipsis,
180 ), 181 ),
181 Pat::Record { path: p, args: fields, ellipsis: _ } => { 182 Pat::Record { path: p, args: fields, ellipsis: _ } => {
182 self.infer_record_pat(p.as_deref(), fields, expected, default_bm, pat) 183 self.infer_record_pat(p.as_deref(), fields, &expected, default_bm, pat)
183 } 184 }
184 Pat::Path(path) => { 185 Pat::Path(path) => {
185 // FIXME use correct resolver for the surrounding expression 186 // FIXME use correct resolver for the surrounding expression
@@ -193,7 +194,7 @@ impl<'a> InferenceContext<'a> {
193 BindingMode::convert(*mode) 194 BindingMode::convert(*mode)
194 }; 195 };
195 let inner_ty = if let Some(subpat) = subpat { 196 let inner_ty = if let Some(subpat) = subpat {
196 self.infer_pat(*subpat, expected, default_bm) 197 self.infer_pat(*subpat, &expected, default_bm)
197 } else { 198 } else {
198 expected.clone() 199 expected.clone()
199 }; 200 };
@@ -206,7 +207,6 @@ impl<'a> InferenceContext<'a> {
206 } 207 }
207 BindingMode::Move => inner_ty.clone(), 208 BindingMode::Move => inner_ty.clone(),
208 }; 209 };
209 let bound_ty = self.resolve_ty_as_possible(bound_ty);
210 self.write_pat_ty(pat, bound_ty); 210 self.write_pat_ty(pat, bound_ty);
211 return inner_ty; 211 return inner_ty;
212 } 212 }
@@ -265,13 +265,12 @@ impl<'a> InferenceContext<'a> {
265 }; 265 };
266 // use a new type variable if we got error type here 266 // use a new type variable if we got error type here
267 let ty = self.insert_type_vars_shallow(ty); 267 let ty = self.insert_type_vars_shallow(ty);
268 if !self.unify(&ty, expected) { 268 if !self.unify(&ty, &expected) {
269 self.result.type_mismatches.insert( 269 self.result.type_mismatches.insert(
270 pat.into(), 270 pat.into(),
271 TypeMismatch { expected: expected.clone(), actual: ty.clone() }, 271 TypeMismatch { expected: expected.clone(), actual: ty.clone() },
272 ); 272 );
273 } 273 }
274 let ty = self.resolve_ty_as_possible(ty);
275 self.write_pat_ty(pat, ty.clone()); 274 self.write_pat_ty(pat, ty.clone());
276 ty 275 ty
277 } 276 }
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs
index 495282eba..14c99eafd 100644
--- a/crates/hir_ty/src/infer/path.rs
+++ b/crates/hir_ty/src/infer/path.rs
@@ -65,7 +65,6 @@ impl<'a> InferenceContext<'a> {
65 let typable: ValueTyDefId = match value { 65 let typable: ValueTyDefId = match value {
66 ValueNs::LocalBinding(pat) => { 66 ValueNs::LocalBinding(pat) => {
67 let ty = self.result.type_of_pat.get(pat)?.clone(); 67 let ty = self.result.type_of_pat.get(pat)?.clone();
68 let ty = self.resolve_ty_as_possible(ty);
69 return Some(ty); 68 return Some(ty);
70 } 69 }
71 ValueNs::FunctionId(it) => it.into(), 70 ValueNs::FunctionId(it) => it.into(),
@@ -218,14 +217,14 @@ impl<'a> InferenceContext<'a> {
218 return Some(result); 217 return Some(result);
219 } 218 }
220 219
221 let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone()); 220 let canonical_ty = self.canonicalize(ty.clone());
222 let krate = self.resolver.krate()?; 221 let krate = self.resolver.krate()?;
223 let traits_in_scope = self.resolver.traits_in_scope(self.db.upcast()); 222 let traits_in_scope = self.resolver.traits_in_scope(self.db.upcast());
224 223
225 method_resolution::iterate_method_candidates( 224 method_resolution::iterate_method_candidates(
226 &canonical_ty.value, 225 &canonical_ty.value,
227 self.db, 226 self.db,
228 self.trait_env.clone(), 227 self.table.trait_env.clone(),
229 krate, 228 krate,
230 &traits_in_scope, 229 &traits_in_scope,
231 None, 230 None,
@@ -275,6 +274,7 @@ impl<'a> InferenceContext<'a> {
275 name: &Name, 274 name: &Name,
276 id: ExprOrPatId, 275 id: ExprOrPatId,
277 ) -> Option<(ValueNs, Option<Substitution>)> { 276 ) -> Option<(ValueNs, Option<Substitution>)> {
277 let ty = self.resolve_ty_shallow(ty);
278 let (enum_id, subst) = match ty.as_adt() { 278 let (enum_id, subst) = match ty.as_adt() {
279 Some((AdtId::EnumId(e), subst)) => (e, subst), 279 Some((AdtId::EnumId(e), subst)) => (e, subst),
280 _ => return None, 280 _ => return None,
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs
index d8e0b4320..21d3fb54e 100644
--- a/crates/hir_ty/src/infer/unify.rs
+++ b/crates/hir_ty/src/infer/unify.rs
@@ -1,177 +1,95 @@
1//! Unification and canonicalization logic. 1//! Unification and canonicalization logic.
2 2
3use std::borrow::Cow; 3use std::{fmt, mem, sync::Arc};
4 4
5use chalk_ir::{ 5use chalk_ir::{
6 cast::Cast, fold::Fold, interner::HasInterner, FloatTy, IntTy, TyVariableKind, UniverseIndex, 6 cast::Cast, fold::Fold, interner::HasInterner, zip::Zip, FloatTy, IntTy, TyVariableKind,
7 VariableKind, 7 UniverseIndex,
8}; 8};
9use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; 9use chalk_solve::infer::ParameterEnaVariableExt;
10use ena::unify::UnifyKey;
10 11
11use super::{DomainGoal, InferenceContext}; 12use super::{InferOk, InferResult, InferenceContext, TypeError};
12use crate::{ 13use crate::{
13 fold_tys, static_lifetime, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, 14 db::HirDatabase, fold_tys, static_lifetime, AliasEq, AliasTy, BoundVar, Canonical,
14 DebruijnIndex, FnPointer, FnSubst, InEnvironment, InferenceVar, Interner, Scalar, Substitution, 15 DebruijnIndex, GenericArg, Goal, Guidance, InEnvironment, InferenceVar, Interner, ProjectionTy,
15 Ty, TyExt, TyKind, WhereClause, 16 Scalar, Solution, Substitution, TraitEnvironment, Ty, TyKind, VariableKind,
16}; 17};
17 18
18impl<'a> InferenceContext<'a> { 19impl<'a> InferenceContext<'a> {
19 pub(super) fn canonicalizer<'b>(&'b mut self) -> Canonicalizer<'a, 'b> 20 pub(super) fn canonicalize<T: Fold<Interner> + HasInterner<Interner = Interner>>(
21 &mut self,
22 t: T,
23 ) -> Canonicalized<T::Result>
20 where 24 where
21 'a: 'b, 25 T::Result: HasInterner<Interner = Interner>,
22 { 26 {
23 Canonicalizer { ctx: self, free_vars: Vec::new(), var_stack: Vec::new() } 27 // try to resolve obligations before canonicalizing, since this might
28 // result in new knowledge about variables
29 self.resolve_obligations_as_possible();
30 self.table.canonicalize(t)
24 } 31 }
25} 32}
26 33
27pub(super) struct Canonicalizer<'a, 'b> 34#[derive(Debug, Clone)]
28where
29 'a: 'b,
30{
31 ctx: &'b mut InferenceContext<'a>,
32 free_vars: Vec<(InferenceVar, TyVariableKind)>,
33 /// A stack of type variables that is used to detect recursive types (which
34 /// are an error, but we need to protect against them to avoid stack
35 /// overflows).
36 var_stack: Vec<TypeVarId>,
37}
38
39#[derive(Debug)]
40pub(super) struct Canonicalized<T> 35pub(super) struct Canonicalized<T>
41where 36where
42 T: HasInterner<Interner = Interner>, 37 T: HasInterner<Interner = Interner>,
43{ 38{
44 pub(super) value: Canonical<T>, 39 pub(super) value: Canonical<T>,
45 free_vars: Vec<(InferenceVar, TyVariableKind)>, 40 free_vars: Vec<GenericArg>,
46}
47
48impl<'a, 'b> Canonicalizer<'a, 'b> {
49 fn add(&mut self, free_var: InferenceVar, kind: TyVariableKind) -> usize {
50 self.free_vars.iter().position(|&(v, _)| v == free_var).unwrap_or_else(|| {
51 let next_index = self.free_vars.len();
52 self.free_vars.push((free_var, kind));
53 next_index
54 })
55 }
56
57 fn do_canonicalize<T: Fold<Interner, Result = T> + HasInterner<Interner = Interner>>(
58 &mut self,
59 t: T,
60 binders: DebruijnIndex,
61 ) -> T {
62 fold_tys(
63 t,
64 |ty, binders| match ty.kind(&Interner) {
65 &TyKind::InferenceVar(var, kind) => {
66 let inner = from_inference_var(var);
67 if self.var_stack.contains(&inner) {
68 // recursive type
69 return self.ctx.table.type_variable_table.fallback_value(var, kind);
70 }
71 if let Some(known_ty) =
72 self.ctx.table.var_unification_table.inlined_probe_value(inner).known()
73 {
74 self.var_stack.push(inner);
75 let result = self.do_canonicalize(known_ty.clone(), binders);
76 self.var_stack.pop();
77 result
78 } else {
79 let root = self.ctx.table.var_unification_table.find(inner);
80 let position = self.add(to_inference_var(root), kind);
81 TyKind::BoundVar(BoundVar::new(binders, position)).intern(&Interner)
82 }
83 }
84 _ => ty,
85 },
86 binders,
87 )
88 }
89
90 fn into_canonicalized<T: HasInterner<Interner = Interner>>(
91 self,
92 result: T,
93 ) -> Canonicalized<T> {
94 let kinds = self
95 .free_vars
96 .iter()
97 .map(|&(_, k)| chalk_ir::WithKind::new(VariableKind::Ty(k), UniverseIndex::ROOT));
98 Canonicalized {
99 value: Canonical {
100 value: result,
101 binders: CanonicalVarKinds::from_iter(&Interner, kinds),
102 },
103 free_vars: self.free_vars,
104 }
105 }
106
107 pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> {
108 let result = self.do_canonicalize(ty, DebruijnIndex::INNERMOST);
109 self.into_canonicalized(result)
110 }
111
112 pub(crate) fn canonicalize_obligation(
113 mut self,
114 obligation: InEnvironment<DomainGoal>,
115 ) -> Canonicalized<InEnvironment<DomainGoal>> {
116 let result = match obligation.goal {
117 DomainGoal::Holds(wc) => {
118 DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST))
119 }
120 _ => unimplemented!(),
121 };
122 self.into_canonicalized(InEnvironment { goal: result, environment: obligation.environment })
123 }
124} 41}
125 42
126impl<T: HasInterner<Interner = Interner>> Canonicalized<T> { 43impl<T: HasInterner<Interner = Interner>> Canonicalized<T> {
127 pub(super) fn decanonicalize_ty(&self, ty: Ty) -> Ty { 44 pub(super) fn decanonicalize_ty(&self, ty: Ty) -> Ty {
128 crate::fold_free_vars(ty, |bound, _binders| { 45 chalk_ir::Substitute::apply(&self.free_vars, ty, &Interner)
129 let (v, k) = self.free_vars[bound.index];
130 TyKind::InferenceVar(v, k).intern(&Interner)
131 })
132 } 46 }
133 47
134 pub(super) fn apply_solution( 48 pub(super) fn apply_solution(
135 &self, 49 &self,
136 ctx: &mut InferenceContext<'_>, 50 ctx: &mut InferenceTable,
137 solution: Canonical<Substitution>, 51 solution: Canonical<Substitution>,
138 ) { 52 ) {
139 // the solution may contain new variables, which we need to convert to new inference vars 53 // the solution may contain new variables, which we need to convert to new inference vars
140 let new_vars = Substitution::from_iter( 54 let new_vars = Substitution::from_iter(
141 &Interner, 55 &Interner,
142 solution.binders.iter(&Interner).map(|k| match k.kind { 56 solution.binders.iter(&Interner).map(|k| match k.kind {
143 VariableKind::Ty(TyVariableKind::General) => { 57 VariableKind::Ty(TyVariableKind::General) => ctx.new_type_var().cast(&Interner),
144 ctx.table.new_type_var().cast(&Interner) 58 VariableKind::Ty(TyVariableKind::Integer) => ctx.new_integer_var().cast(&Interner),
145 } 59 VariableKind::Ty(TyVariableKind::Float) => ctx.new_float_var().cast(&Interner),
146 VariableKind::Ty(TyVariableKind::Integer) => {
147 ctx.table.new_integer_var().cast(&Interner)
148 }
149 VariableKind::Ty(TyVariableKind::Float) => {
150 ctx.table.new_float_var().cast(&Interner)
151 }
152 // Chalk can sometimes return new lifetime variables. We just use the static lifetime everywhere 60 // Chalk can sometimes return new lifetime variables. We just use the static lifetime everywhere
153 VariableKind::Lifetime => static_lifetime().cast(&Interner), 61 VariableKind::Lifetime => static_lifetime().cast(&Interner),
154 _ => panic!("const variable in solution"), 62 _ => panic!("const variable in solution"),
155 }), 63 }),
156 ); 64 );
157 for (i, ty) in solution.value.iter(&Interner).enumerate() { 65 for (i, v) in solution.value.iter(&Interner).enumerate() {
158 let (v, k) = self.free_vars[i]; 66 let var = self.free_vars[i].clone();
159 // eagerly replace projections in the type; we may be getting types 67 if let Some(ty) = v.ty(&Interner) {
160 // e.g. from where clauses where this hasn't happened yet 68 // eagerly replace projections in the type; we may be getting types
161 let ty = ctx.normalize_associated_types_in( 69 // e.g. from where clauses where this hasn't happened yet
162 new_vars.apply(ty.assert_ty_ref(&Interner).clone(), &Interner), 70 let ty = ctx.normalize_associated_types_in(new_vars.apply(ty.clone(), &Interner));
163 ); 71 ctx.unify(var.assert_ty_ref(&Interner), &ty);
164 ctx.table.unify(&TyKind::InferenceVar(v, k).intern(&Interner), &ty); 72 } else {
73 let _ = ctx.try_unify(&var, &new_vars.apply(v.clone(), &Interner));
74 }
165 } 75 }
166 } 76 }
167} 77}
168 78
169pub fn could_unify(t1: &Ty, t2: &Ty) -> bool { 79pub fn could_unify(
170 InferenceTable::new().unify(t1, t2) 80 db: &dyn HirDatabase,
81 env: Arc<TraitEnvironment>,
82 tys: &Canonical<(Ty, Ty)>,
83) -> bool {
84 unify(db, env, tys).is_some()
171} 85}
172 86
173pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { 87pub(crate) fn unify(
174 let mut table = InferenceTable::new(); 88 db: &dyn HirDatabase,
89 env: Arc<TraitEnvironment>,
90 tys: &Canonical<(Ty, Ty)>,
91) -> Option<Substitution> {
92 let mut table = InferenceTable::new(db, env);
175 let vars = Substitution::from_iter( 93 let vars = Substitution::from_iter(
176 &Interner, 94 &Interner,
177 tys.binders 95 tys.binders
@@ -187,77 +105,151 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> {
187 } 105 }
188 // default any type vars that weren't unified back to their original bound vars 106 // default any type vars that weren't unified back to their original bound vars
189 // (kind of hacky) 107 // (kind of hacky)
190 for (i, var) in vars.iter(&Interner).enumerate() { 108 let find_var = |iv| {
191 let var = var.assert_ty_ref(&Interner); 109 vars.iter(&Interner).position(|v| match v.interned() {
192 if &*table.resolve_ty_shallow(var) == var { 110 chalk_ir::GenericArgData::Ty(ty) => ty.inference_var(&Interner),
193 table.unify( 111 chalk_ir::GenericArgData::Lifetime(lt) => lt.inference_var(&Interner),
194 var, 112 chalk_ir::GenericArgData::Const(c) => c.inference_var(&Interner),
195 &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i)).intern(&Interner), 113 } == Some(iv))
196 ); 114 };
197 } 115 let fallback = |iv, kind, default, binder| match kind {
198 } 116 chalk_ir::VariableKind::Ty(_ty_kind) => find_var(iv)
117 .map_or(default, |i| BoundVar::new(binder, i).to_ty(&Interner).cast(&Interner)),
118 chalk_ir::VariableKind::Lifetime => find_var(iv)
119 .map_or(default, |i| BoundVar::new(binder, i).to_lifetime(&Interner).cast(&Interner)),
120 chalk_ir::VariableKind::Const(ty) => find_var(iv)
121 .map_or(default, |i| BoundVar::new(binder, i).to_const(&Interner, ty).cast(&Interner)),
122 };
199 Some(Substitution::from_iter( 123 Some(Substitution::from_iter(
200 &Interner, 124 &Interner,
201 vars.iter(&Interner) 125 vars.iter(&Interner)
202 .map(|v| table.resolve_ty_completely(v.assert_ty_ref(&Interner).clone())), 126 .map(|v| table.resolve_with_fallback(v.assert_ty_ref(&Interner).clone(), fallback)),
203 )) 127 ))
204} 128}
205 129
206#[derive(Clone, Debug)] 130#[derive(Copy, Clone, Debug)]
207pub(super) struct TypeVariableTable { 131pub(crate) struct TypeVariableData {
208 inner: Vec<TypeVariableData>, 132 diverging: bool,
209} 133}
210 134
211impl TypeVariableTable { 135type ChalkInferenceTable = chalk_solve::infer::InferenceTable<Interner>;
212 fn push(&mut self, data: TypeVariableData) { 136
213 self.inner.push(data); 137#[derive(Clone)]
138pub(crate) struct InferenceTable<'a> {
139 pub(crate) db: &'a dyn HirDatabase,
140 pub(crate) trait_env: Arc<TraitEnvironment>,
141 var_unification_table: ChalkInferenceTable,
142 type_variable_table: Vec<TypeVariableData>,
143 pending_obligations: Vec<Canonicalized<InEnvironment<Goal>>>,
144}
145
146impl<'a> InferenceTable<'a> {
147 pub(crate) fn new(db: &'a dyn HirDatabase, trait_env: Arc<TraitEnvironment>) -> Self {
148 InferenceTable {
149 db,
150 trait_env,
151 var_unification_table: ChalkInferenceTable::new(),
152 type_variable_table: Vec::new(),
153 pending_obligations: Vec::new(),
154 }
214 } 155 }
215 156
216 pub(super) fn set_diverging(&mut self, iv: InferenceVar, diverging: bool) { 157 /// Chalk doesn't know about the `diverging` flag, so when it unifies two
217 self.inner[from_inference_var(iv).0 as usize].diverging = diverging; 158 /// type variables of which one is diverging, the chosen root might not be
159 /// diverging and we have no way of marking it as such at that time. This
160 /// function goes through all type variables and make sure their root is
161 /// marked as diverging if necessary, so that resolving them gives the right
162 /// result.
163 pub(super) fn propagate_diverging_flag(&mut self) {
164 for i in 0..self.type_variable_table.len() {
165 if !self.type_variable_table[i].diverging {
166 continue;
167 }
168 let v = InferenceVar::from(i as u32);
169 let root = self.var_unification_table.inference_var_root(v);
170 if let Some(data) = self.type_variable_table.get_mut(root.index() as usize) {
171 data.diverging = true;
172 }
173 }
218 } 174 }
219 175
220 fn is_diverging(&mut self, iv: InferenceVar) -> bool { 176 pub(super) fn set_diverging(&mut self, iv: InferenceVar, diverging: bool) {
221 self.inner[from_inference_var(iv).0 as usize].diverging 177 self.type_variable_table[iv.index() as usize].diverging = diverging;
222 } 178 }
223 179
224 fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty { 180 fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty {
225 match kind { 181 match kind {
226 _ if self.inner[from_inference_var(iv).0 as usize].diverging => TyKind::Never, 182 _ if self
183 .type_variable_table
184 .get(iv.index() as usize)
185 .map_or(false, |data| data.diverging) =>
186 {
187 TyKind::Never
188 }
227 TyVariableKind::General => TyKind::Error, 189 TyVariableKind::General => TyKind::Error,
228 TyVariableKind::Integer => TyKind::Scalar(Scalar::Int(IntTy::I32)), 190 TyVariableKind::Integer => TyKind::Scalar(Scalar::Int(IntTy::I32)),
229 TyVariableKind::Float => TyKind::Scalar(Scalar::Float(FloatTy::F64)), 191 TyVariableKind::Float => TyKind::Scalar(Scalar::Float(FloatTy::F64)),
230 } 192 }
231 .intern(&Interner) 193 .intern(&Interner)
232 } 194 }
233}
234 195
235#[derive(Copy, Clone, Debug)] 196 pub(super) fn canonicalize<T: Fold<Interner> + HasInterner<Interner = Interner>>(
236pub(crate) struct TypeVariableData { 197 &mut self,
237 diverging: bool, 198 t: T,
238} 199 ) -> Canonicalized<T::Result>
200 where
201 T::Result: HasInterner<Interner = Interner>,
202 {
203 let result = self.var_unification_table.canonicalize(&Interner, t);
204 let free_vars = result
205 .free_vars
206 .into_iter()
207 .map(|free_var| free_var.to_generic_arg(&Interner))
208 .collect();
209 Canonicalized { value: result.quantified, free_vars }
210 }
211
212 /// Recurses through the given type, normalizing associated types mentioned
213 /// in it by replacing them by type variables and registering obligations to
214 /// resolve later. This should be done once for every type we get from some
215 /// type annotation (e.g. from a let type annotation, field type or function
216 /// call). `make_ty` handles this already, but e.g. for field types we need
217 /// to do it as well.
218 pub(super) fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty {
219 fold_tys(
220 ty,
221 |ty, _| match ty.kind(&Interner) {
222 TyKind::Alias(AliasTy::Projection(proj_ty)) => {
223 self.normalize_projection_ty(proj_ty.clone())
224 }
225 _ => ty,
226 },
227 DebruijnIndex::INNERMOST,
228 )
229 }
239 230
240#[derive(Clone, Debug)] 231 pub(super) fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
241pub(crate) struct InferenceTable { 232 let var = self.new_type_var();
242 pub(super) var_unification_table: InPlaceUnificationTable<TypeVarId>, 233 let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() };
243 pub(super) type_variable_table: TypeVariableTable, 234 let obligation = alias_eq.cast(&Interner);
244 pub(super) revision: u32, 235 self.register_obligation(obligation);
245} 236 var
237 }
246 238
247impl InferenceTable { 239 fn extend_type_variable_table(&mut self, to_index: usize) {
248 pub(crate) fn new() -> Self { 240 self.type_variable_table.extend(
249 InferenceTable { 241 (0..1 + to_index - self.type_variable_table.len())
250 var_unification_table: InPlaceUnificationTable::new(), 242 .map(|_| TypeVariableData { diverging: false }),
251 type_variable_table: TypeVariableTable { inner: Vec::new() }, 243 );
252 revision: 0,
253 }
254 } 244 }
255 245
256 fn new_var(&mut self, kind: TyVariableKind, diverging: bool) -> Ty { 246 fn new_var(&mut self, kind: TyVariableKind, diverging: bool) -> Ty {
257 self.type_variable_table.push(TypeVariableData { diverging }); 247 let var = self.var_unification_table.new_variable(UniverseIndex::ROOT);
258 let key = self.var_unification_table.new_key(TypeVarValue::Unknown); 248 // Chalk might have created some type variables for its own purposes that we don't know about...
259 assert_eq!(key.0 as usize, self.type_variable_table.inner.len() - 1); 249 self.extend_type_variable_table(var.index() as usize);
260 TyKind::InferenceVar(to_inference_var(key), kind).intern(&Interner) 250 assert_eq!(var.index() as usize, self.type_variable_table.len() - 1);
251 self.type_variable_table[var.index() as usize].diverging = diverging;
252 var.to_ty_with_kind(&Interner, kind)
261 } 253 }
262 254
263 pub(crate) fn new_type_var(&mut self) -> Ty { 255 pub(crate) fn new_type_var(&mut self) -> Ty {
@@ -276,350 +268,261 @@ impl InferenceTable {
276 self.new_var(TyVariableKind::General, true) 268 self.new_var(TyVariableKind::General, true)
277 } 269 }
278 270
279 pub(crate) fn resolve_ty_completely(&mut self, ty: Ty) -> Ty { 271 pub(crate) fn resolve_with_fallback<T>(
280 self.resolve_ty_completely_inner(&mut Vec::new(), ty) 272 &mut self,
273 t: T,
274 fallback: impl Fn(InferenceVar, VariableKind, GenericArg, DebruijnIndex) -> GenericArg,
275 ) -> T::Result
276 where
277 T: HasInterner<Interner = Interner> + Fold<Interner>,
278 {
279 self.resolve_with_fallback_inner(&mut Vec::new(), t, &fallback)
281 } 280 }
282 281
283 pub(crate) fn resolve_ty_as_possible(&mut self, ty: Ty) -> Ty { 282 fn resolve_with_fallback_inner<T>(
284 self.resolve_ty_as_possible_inner(&mut Vec::new(), ty) 283 &mut self,
284 var_stack: &mut Vec<InferenceVar>,
285 t: T,
286 fallback: &impl Fn(InferenceVar, VariableKind, GenericArg, DebruijnIndex) -> GenericArg,
287 ) -> T::Result
288 where
289 T: HasInterner<Interner = Interner> + Fold<Interner>,
290 {
291 t.fold_with(
292 &mut resolve::Resolver { table: self, var_stack, fallback },
293 DebruijnIndex::INNERMOST,
294 )
295 .expect("fold failed unexpectedly")
285 } 296 }
286 297
287 pub(crate) fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { 298 pub(crate) fn resolve_ty_completely(&mut self, ty: Ty) -> Ty {
288 self.unify_inner(ty1, ty2, 0) 299 self.resolve_with_fallback(ty, |_, _, d, _| d)
289 } 300 }
290 301
291 pub(crate) fn unify_substs( 302 /// Unify two types and register new trait goals that arise from that.
292 &mut self, 303 pub(crate) fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
293 substs1: &Substitution, 304 let result = if let Ok(r) = self.try_unify(ty1, ty2) {
294 substs2: &Substitution, 305 r
295 depth: usize, 306 } else {
296 ) -> bool { 307 return false;
297 substs1.iter(&Interner).zip(substs2.iter(&Interner)).all(|(t1, t2)| { 308 };
298 self.unify_inner(t1.assert_ty_ref(&Interner), t2.assert_ty_ref(&Interner), depth) 309 self.register_infer_ok(result);
299 }) 310 true
300 } 311 }
301 312
302 fn unify_inner(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool { 313 /// Unify two types and return new trait goals arising from it, so the
303 if depth > 1000 { 314 /// caller needs to deal with them.
304 // prevent stackoverflows 315 pub(crate) fn try_unify<T: Zip<Interner>>(&mut self, t1: &T, t2: &T) -> InferResult {
305 panic!("infinite recursion in unification"); 316 match self.var_unification_table.relate(
306 } 317 &Interner,
307 if ty1 == ty2 { 318 &self.db,
308 return true; 319 &self.trait_env.env,
309 } 320 chalk_ir::Variance::Invariant,
310 // try to resolve type vars first 321 t1,
311 let ty1 = self.resolve_ty_shallow(ty1); 322 t2,
312 let ty2 = self.resolve_ty_shallow(ty2); 323 ) {
313 if ty1.equals_ctor(&ty2) { 324 Ok(result) => Ok(InferOk { goals: result.goals }),
314 match (ty1.kind(&Interner), ty2.kind(&Interner)) { 325 Err(chalk_ir::NoSolution) => Err(TypeError),
315 (TyKind::Adt(_, substs1), TyKind::Adt(_, substs2))
316 | (TyKind::FnDef(_, substs1), TyKind::FnDef(_, substs2))
317 | (
318 TyKind::Function(FnPointer { substitution: FnSubst(substs1), .. }),
319 TyKind::Function(FnPointer { substitution: FnSubst(substs2), .. }),
320 )
321 | (TyKind::Tuple(_, substs1), TyKind::Tuple(_, substs2))
322 | (TyKind::OpaqueType(_, substs1), TyKind::OpaqueType(_, substs2))
323 | (TyKind::AssociatedType(_, substs1), TyKind::AssociatedType(_, substs2))
324 | (TyKind::Closure(.., substs1), TyKind::Closure(.., substs2)) => {
325 self.unify_substs(substs1, substs2, depth + 1)
326 }
327 (TyKind::Array(ty1, c1), TyKind::Array(ty2, c2)) if c1 == c2 => {
328 self.unify_inner(ty1, ty2, depth + 1)
329 }
330 (TyKind::Ref(_, _, ty1), TyKind::Ref(_, _, ty2))
331 | (TyKind::Raw(_, ty1), TyKind::Raw(_, ty2))
332 | (TyKind::Slice(ty1), TyKind::Slice(ty2)) => self.unify_inner(ty1, ty2, depth + 1),
333 _ => true, /* we checked equals_ctor already */
334 }
335 } else if let (TyKind::Closure(.., substs1), TyKind::Closure(.., substs2)) =
336 (ty1.kind(&Interner), ty2.kind(&Interner))
337 {
338 self.unify_substs(substs1, substs2, depth + 1)
339 } else {
340 self.unify_inner_trivial(&ty1, &ty2, depth)
341 } 326 }
342 } 327 }
343 328
344 pub(super) fn unify_inner_trivial(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool { 329 /// If `ty` is a type variable with known type, returns that type;
345 match (ty1.kind(&Interner), ty2.kind(&Interner)) { 330 /// otherwise, return ty.
346 (TyKind::Error, _) | (_, TyKind::Error) => true, 331 pub(crate) fn resolve_ty_shallow(&mut self, ty: &Ty) -> Ty {
332 self.var_unification_table.normalize_ty_shallow(&Interner, ty).unwrap_or_else(|| ty.clone())
333 }
347 334
348 (TyKind::Placeholder(p1), TyKind::Placeholder(p2)) if *p1 == *p2 => true, 335 pub(crate) fn register_obligation(&mut self, goal: Goal) {
336 let in_env = InEnvironment::new(&self.trait_env.env, goal);
337 self.register_obligation_in_env(in_env)
338 }
349 339
350 (TyKind::Dyn(dyn1), TyKind::Dyn(dyn2)) 340 fn register_obligation_in_env(&mut self, goal: InEnvironment<Goal>) {
351 if dyn1.bounds.skip_binders().interned().len() 341 let canonicalized = self.canonicalize(goal);
352 == dyn2.bounds.skip_binders().interned().len() => 342 if !self.try_resolve_obligation(&canonicalized) {
353 { 343 self.pending_obligations.push(canonicalized);
354 for (pred1, pred2) in dyn1 344 }
355 .bounds 345 }
356 .skip_binders()
357 .interned()
358 .iter()
359 .zip(dyn2.bounds.skip_binders().interned().iter())
360 {
361 if !self.unify_preds(pred1.skip_binders(), pred2.skip_binders(), depth + 1) {
362 return false;
363 }
364 }
365 true
366 }
367 346
368 ( 347 pub(crate) fn register_infer_ok(&mut self, infer_ok: InferOk) {
369 TyKind::InferenceVar(tv1, TyVariableKind::General), 348 infer_ok.goals.into_iter().for_each(|goal| self.register_obligation_in_env(goal));
370 TyKind::InferenceVar(tv2, TyVariableKind::General), 349 }
371 )
372 | (
373 TyKind::InferenceVar(tv1, TyVariableKind::Integer),
374 TyKind::InferenceVar(tv2, TyVariableKind::Integer),
375 )
376 | (
377 TyKind::InferenceVar(tv1, TyVariableKind::Float),
378 TyKind::InferenceVar(tv2, TyVariableKind::Float),
379 ) if self.type_variable_table.is_diverging(*tv1)
380 == self.type_variable_table.is_diverging(*tv2) =>
381 {
382 // both type vars are unknown since we tried to resolve them
383 if !self
384 .var_unification_table
385 .unioned(from_inference_var(*tv1), from_inference_var(*tv2))
386 {
387 self.var_unification_table
388 .union(from_inference_var(*tv1), from_inference_var(*tv2));
389 self.revision += 1;
390 }
391 true
392 }
393 350
394 // The order of MaybeNeverTypeVar matters here. 351 pub(crate) fn resolve_obligations_as_possible(&mut self) {
395 // Unifying MaybeNeverTypeVar and TypeVar will let the latter become MaybeNeverTypeVar. 352 let _span = profile::span("resolve_obligations_as_possible");
396 // Unifying MaybeNeverTypeVar and other concrete type will let the former become it. 353 let mut changed = true;
397 (TyKind::InferenceVar(tv, TyVariableKind::General), other) 354 let mut obligations = Vec::new();
398 | (other, TyKind::InferenceVar(tv, TyVariableKind::General)) 355 while changed {
399 | ( 356 changed = false;
400 TyKind::InferenceVar(tv, TyVariableKind::Integer), 357 mem::swap(&mut self.pending_obligations, &mut obligations);
401 other @ TyKind::Scalar(Scalar::Int(_)), 358 for canonicalized in obligations.drain(..) {
402 ) 359 if !self.check_changed(&canonicalized) {
403 | ( 360 self.pending_obligations.push(canonicalized);
404 other @ TyKind::Scalar(Scalar::Int(_)), 361 continue;
405 TyKind::InferenceVar(tv, TyVariableKind::Integer), 362 }
406 ) 363 changed = true;
407 | ( 364 let uncanonical = chalk_ir::Substitute::apply(
408 TyKind::InferenceVar(tv, TyVariableKind::Integer), 365 &canonicalized.free_vars,
409 other @ TyKind::Scalar(Scalar::Uint(_)), 366 canonicalized.value.value,
410 ) 367 &Interner,
411 | (
412 other @ TyKind::Scalar(Scalar::Uint(_)),
413 TyKind::InferenceVar(tv, TyVariableKind::Integer),
414 )
415 | (
416 TyKind::InferenceVar(tv, TyVariableKind::Float),
417 other @ TyKind::Scalar(Scalar::Float(_)),
418 )
419 | (
420 other @ TyKind::Scalar(Scalar::Float(_)),
421 TyKind::InferenceVar(tv, TyVariableKind::Float),
422 ) => {
423 // the type var is unknown since we tried to resolve it
424 self.var_unification_table.union_value(
425 from_inference_var(*tv),
426 TypeVarValue::Known(other.clone().intern(&Interner)),
427 ); 368 );
428 self.revision += 1; 369 self.register_obligation_in_env(uncanonical);
429 true
430 } 370 }
431
432 _ => false,
433 } 371 }
434 } 372 }
435 373
436 fn unify_preds(&mut self, pred1: &WhereClause, pred2: &WhereClause, depth: usize) -> bool { 374 /// This checks whether any of the free variables in the `canonicalized`
437 match (pred1, pred2) { 375 /// have changed (either been unified with another variable, or with a
438 (WhereClause::Implemented(tr1), WhereClause::Implemented(tr2)) 376 /// value). If this is not the case, we don't need to try to solve the goal
439 if tr1.trait_id == tr2.trait_id => 377 /// again -- it'll give the same result as last time.
440 { 378 fn check_changed(&mut self, canonicalized: &Canonicalized<InEnvironment<Goal>>) -> bool {
441 self.unify_substs(&tr1.substitution, &tr2.substitution, depth + 1) 379 canonicalized.free_vars.iter().any(|var| {
380 let iv = match var.data(&Interner) {
381 chalk_ir::GenericArgData::Ty(ty) => ty.inference_var(&Interner),
382 chalk_ir::GenericArgData::Lifetime(lt) => lt.inference_var(&Interner),
383 chalk_ir::GenericArgData::Const(c) => c.inference_var(&Interner),
442 } 384 }
443 ( 385 .expect("free var is not inference var");
444 WhereClause::AliasEq(AliasEq { alias: alias1, ty: ty1 }), 386 if self.var_unification_table.probe_var(iv).is_some() {
445 WhereClause::AliasEq(AliasEq { alias: alias2, ty: ty2 }), 387 return true;
446 ) => {
447 let (substitution1, substitution2) = match (alias1, alias2) {
448 (AliasTy::Projection(projection_ty1), AliasTy::Projection(projection_ty2))
449 if projection_ty1.associated_ty_id == projection_ty2.associated_ty_id =>
450 {
451 (&projection_ty1.substitution, &projection_ty2.substitution)
452 }
453 (AliasTy::Opaque(opaque1), AliasTy::Opaque(opaque2))
454 if opaque1.opaque_ty_id == opaque2.opaque_ty_id =>
455 {
456 (&opaque1.substitution, &opaque2.substitution)
457 }
458 _ => return false,
459 };
460 self.unify_substs(&substitution1, &substitution2, depth + 1)
461 && self.unify_inner(&ty1, &ty2, depth + 1)
462 } 388 }
463 _ => false, 389 let root = self.var_unification_table.inference_var_root(iv);
464 } 390 iv != root
391 })
465 } 392 }
466 393
467 /// If `ty` is a type variable with known type, returns that type; 394 fn try_resolve_obligation(
468 /// otherwise, return ty. 395 &mut self,
469 pub(crate) fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> { 396 canonicalized: &Canonicalized<InEnvironment<Goal>>,
470 let mut ty = Cow::Borrowed(ty); 397 ) -> bool {
471 // The type variable could resolve to a int/float variable. Hence try 398 let solution = self.db.trait_solve(self.trait_env.krate, canonicalized.value.clone());
472 // resolving up to three times; each type of variable shouldn't occur 399
473 // more than once 400 match solution {
474 for i in 0..3 { 401 Some(Solution::Unique(canonical_subst)) => {
475 if i > 0 { 402 canonicalized.apply_solution(
476 cov_mark::hit!(type_var_resolves_to_int_var); 403 self,
404 Canonical {
405 binders: canonical_subst.binders,
406 // FIXME: handle constraints
407 value: canonical_subst.value.subst,
408 },