aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/code_model.rs4
-rw-r--r--crates/ra_hir/src/diagnostics.rs38
-rw-r--r--crates/ra_hir/src/expr.rs103
-rw-r--r--crates/ra_hir/src/marks.rs1
-rw-r--r--crates/ra_hir/src/nameres/collector.rs67
-rw-r--r--crates/ra_hir/src/nameres/raw.rs17
-rw-r--r--crates/ra_hir/src/nameres/tests/mods.rs14
-rw-r--r--crates/ra_hir/src/path.rs38
-rw-r--r--crates/ra_hir/src/source_binder.rs35
-rw-r--r--crates/ra_hir/src/ty.rs100
-rw-r--r--crates/ra_hir/src/ty/infer.rs47
-rw-r--r--crates/ra_hir/src/ty/lower.rs83
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs14
-rw-r--r--crates/ra_hir/src/ty/tests.rs121
-rw-r--r--crates/ra_hir/src/ty/traits.rs8
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs51
16 files changed, 606 insertions, 135 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 779764590..89fc1d1a1 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -838,6 +838,10 @@ impl TypeAlias {
838 self.id.module(db) 838 self.id.module(db)
839 } 839 }
840 840
841 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
842 self.module(db).krate(db)
843 }
844
841 /// The containing impl block, if this is a method. 845 /// The containing impl block, if this is a method.
842 pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> { 846 pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> {
843 let module_impls = db.impls_in_module(self.module(db)); 847 let module_impls = db.impls_in_module(self.module(db));
diff --git a/crates/ra_hir/src/diagnostics.rs b/crates/ra_hir/src/diagnostics.rs
index 0290483b3..f6240830f 100644
--- a/crates/ra_hir/src/diagnostics.rs
+++ b/crates/ra_hir/src/diagnostics.rs
@@ -3,7 +3,7 @@ use std::{any::Any, fmt};
3use ra_syntax::{ast, AstNode, AstPtr, SyntaxNode, SyntaxNodePtr, TextRange}; 3use ra_syntax::{ast, AstNode, AstPtr, SyntaxNode, SyntaxNodePtr, TextRange};
4use relative_path::RelativePathBuf; 4use relative_path::RelativePathBuf;
5 5
6use crate::{HirDatabase, HirFileId, Name}; 6use crate::{HirDatabase, HirFileId, Name, Source};
7 7
8/// Diagnostic defines hir API for errors and warnings. 8/// Diagnostic defines hir API for errors and warnings.
9/// 9///
@@ -19,10 +19,9 @@ use crate::{HirDatabase, HirFileId, Name};
19/// instance of `Diagnostic` on demand. 19/// instance of `Diagnostic` on demand.
20pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static { 20pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static {
21 fn message(&self) -> String; 21 fn message(&self) -> String;
22 fn file(&self) -> HirFileId; 22 fn source(&self) -> Source<SyntaxNodePtr>;
23 fn syntax_node_ptr(&self) -> SyntaxNodePtr;
24 fn highlight_range(&self) -> TextRange { 23 fn highlight_range(&self) -> TextRange {
25 self.syntax_node_ptr().range() 24 self.source().ast.range()
26 } 25 }
27 fn as_any(&self) -> &(dyn Any + Send + 'static); 26 fn as_any(&self) -> &(dyn Any + Send + 'static);
28} 27}
@@ -34,8 +33,8 @@ pub trait AstDiagnostic {
34 33
35impl dyn Diagnostic { 34impl dyn Diagnostic {
36 pub fn syntax_node(&self, db: &impl HirDatabase) -> SyntaxNode { 35 pub fn syntax_node(&self, db: &impl HirDatabase) -> SyntaxNode {
37 let node = db.parse_or_expand(self.file()).unwrap(); 36 let node = db.parse_or_expand(self.source().file_id).unwrap();
38 self.syntax_node_ptr().to_node(&node) 37 self.source().ast.to_node(&node)
39 } 38 }
40 39
41 pub fn downcast_ref<D: Diagnostic>(&self) -> Option<&D> { 40 pub fn downcast_ref<D: Diagnostic>(&self) -> Option<&D> {
@@ -87,12 +86,11 @@ impl Diagnostic for NoSuchField {
87 fn message(&self) -> String { 86 fn message(&self) -> String {
88 "no such field".to_string() 87 "no such field".to_string()
89 } 88 }
90 fn file(&self) -> HirFileId { 89
91 self.file 90 fn source(&self) -> Source<SyntaxNodePtr> {
92 } 91 Source { file_id: self.file, ast: self.field.into() }
93 fn syntax_node_ptr(&self) -> SyntaxNodePtr {
94 self.field.into()
95 } 92 }
93
96 fn as_any(&self) -> &(dyn Any + Send + 'static) { 94 fn as_any(&self) -> &(dyn Any + Send + 'static) {
97 self 95 self
98 } 96 }
@@ -109,11 +107,8 @@ impl Diagnostic for UnresolvedModule {
109 fn message(&self) -> String { 107 fn message(&self) -> String {
110 "unresolved module".to_string() 108 "unresolved module".to_string()
111 } 109 }
112 fn file(&self) -> HirFileId { 110 fn source(&self) -> Source<SyntaxNodePtr> {
113 self.file 111 Source { file_id: self.file, ast: self.decl.into() }
114 }
115 fn syntax_node_ptr(&self) -> SyntaxNodePtr {
116 self.decl.into()
117 } 112 }
118 fn as_any(&self) -> &(dyn Any + Send + 'static) { 113 fn as_any(&self) -> &(dyn Any + Send + 'static) {
119 self 114 self
@@ -131,11 +126,8 @@ impl Diagnostic for MissingFields {
131 fn message(&self) -> String { 126 fn message(&self) -> String {
132 "fill structure fields".to_string() 127 "fill structure fields".to_string()
133 } 128 }
134 fn file(&self) -> HirFileId { 129 fn source(&self) -> Source<SyntaxNodePtr> {
135 self.file 130 Source { file_id: self.file, ast: self.field_list.into() }
136 }
137 fn syntax_node_ptr(&self) -> SyntaxNodePtr {
138 self.field_list.into()
139 } 131 }
140 fn as_any(&self) -> &(dyn Any + Send + 'static) { 132 fn as_any(&self) -> &(dyn Any + Send + 'static) {
141 self 133 self
@@ -146,8 +138,8 @@ impl AstDiagnostic for MissingFields {
146 type AST = ast::NamedFieldList; 138 type AST = ast::NamedFieldList;
147 139
148 fn ast(&self, db: &impl HirDatabase) -> Self::AST { 140 fn ast(&self, db: &impl HirDatabase) -> Self::AST {
149 let root = db.parse_or_expand(self.file()).unwrap(); 141 let root = db.parse_or_expand(self.source().file_id).unwrap();
150 let node = self.syntax_node_ptr().to_node(&root); 142 let node = self.source().ast.to_node(&root);
151 ast::NamedFieldList::cast(node).unwrap() 143 ast::NamedFieldList::cast(node).unwrap()
152 } 144 }
153} 145}
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 4dcea19a9..f33676655 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -11,17 +11,16 @@ use ra_syntax::{
11 }, 11 },
12 AstNode, AstPtr, SyntaxNodePtr, 12 AstNode, AstPtr, SyntaxNodePtr,
13}; 13};
14use test_utils::tested_by;
14 15
15use crate::{ 16use crate::{
16 name::{AsName, SELF_PARAM}, 17 name::{AsName, SELF_PARAM},
18 path::GenericArgs,
19 ty::primitive::{FloatTy, IntTy, UncertainFloatTy, UncertainIntTy},
17 type_ref::{Mutability, TypeRef}, 20 type_ref::{Mutability, TypeRef},
18 DefWithBody, Either, HasSource, HirDatabase, HirFileId, MacroCallLoc, MacroFileKind, Name, 21 DefWithBody, Either, HasSource, HirDatabase, HirFileId, MacroCallLoc, MacroFileKind, Name,
19 Path, Resolver, 22 Path, Resolver,
20}; 23};
21use crate::{
22 path::GenericArgs,
23 ty::primitive::{FloatTy, IntTy, UncertainFloatTy, UncertainIntTy},
24};
25 24
26pub use self::scope::ExprScopes; 25pub use self::scope::ExprScopes;
27 26
@@ -558,37 +557,40 @@ where
558 let syntax_ptr = SyntaxNodePtr::new(expr.syntax()); 557 let syntax_ptr = SyntaxNodePtr::new(expr.syntax());
559 match expr.kind() { 558 match expr.kind() {
560 ast::ExprKind::IfExpr(e) => { 559 ast::ExprKind::IfExpr(e) => {
561 if let Some(pat) = e.condition().and_then(|c| c.pat()) { 560 let then_branch = self.collect_block_opt(e.then_branch());
562 // if let -- desugar to match 561
563 let pat = self.collect_pat(pat); 562 let else_branch = e.else_branch().map(|b| match b {
564 let match_expr = 563 ast::ElseBranch::Block(it) => self.collect_block(it),
565 self.collect_expr_opt(e.condition().expect("checked above").expr()); 564 ast::ElseBranch::IfExpr(elif) => {
566 let then_branch = self.collect_block_opt(e.then_branch()); 565 let expr: ast::Expr = ast::Expr::cast(elif.syntax().clone()).unwrap();
567 let else_branch = e 566 self.collect_expr(expr)
568 .else_branch() 567 }
569 .map(|b| match b { 568 });
570 ast::ElseBranch::Block(it) => self.collect_block(it), 569
571 ast::ElseBranch::IfExpr(elif) => self.collect_expr(elif.into()), 570 let condition = match e.condition() {
572 }) 571 None => self.exprs.alloc(Expr::Missing),
573 .unwrap_or_else(|| self.empty_block()); 572 Some(condition) => match condition.pat() {
574 let placeholder_pat = self.pats.alloc(Pat::Missing); 573 None => self.collect_expr_opt(condition.expr()),
575 let arms = vec![ 574 // if let -- desugar to match
576 MatchArm { pats: vec![pat], expr: then_branch, guard: None }, 575 Some(pat) => {
577 MatchArm { pats: vec![placeholder_pat], expr: else_branch, guard: None }, 576 let pat = self.collect_pat(pat);
578 ]; 577 let match_expr = self.collect_expr_opt(condition.expr());
579 self.alloc_expr(Expr::Match { expr: match_expr, arms }, syntax_ptr) 578 let placeholder_pat = self.pats.alloc(Pat::Missing);
580 } else { 579 let arms = vec![
581 let condition = self.collect_expr_opt(e.condition().and_then(|c| c.expr())); 580 MatchArm { pats: vec![pat], expr: then_branch, guard: None },
582 let then_branch = self.collect_block_opt(e.then_branch()); 581 MatchArm {
583 let else_branch = e.else_branch().map(|b| match b { 582 pats: vec![placeholder_pat],
584 ast::ElseBranch::Block(it) => self.collect_block(it), 583 expr: else_branch.unwrap_or_else(|| self.empty_block()),
585 ast::ElseBranch::IfExpr(elif) => { 584 guard: None,
586 let expr: ast::Expr = ast::Expr::cast(elif.syntax().clone()).unwrap(); 585 },
587 self.collect_expr(expr) 586 ];
587 return self
588 .alloc_expr(Expr::Match { expr: match_expr, arms }, syntax_ptr);
588 } 589 }
589 }); 590 },
590 self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr) 591 };
591 } 592
593 self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
592 } 594 }
593 ast::ExprKind::TryBlockExpr(e) => { 595 ast::ExprKind::TryBlockExpr(e) => {
594 let body = self.collect_block_opt(e.try_body()); 596 let body = self.collect_block_opt(e.try_body());
@@ -600,17 +602,30 @@ where
600 self.alloc_expr(Expr::Loop { body }, syntax_ptr) 602 self.alloc_expr(Expr::Loop { body }, syntax_ptr)
601 } 603 }
602 ast::ExprKind::WhileExpr(e) => { 604 ast::ExprKind::WhileExpr(e) => {
603 let condition = if let Some(condition) = e.condition() {
604 if condition.pat().is_none() {
605 self.collect_expr_opt(condition.expr())
606 } else {
607 // FIXME handle while let
608 return self.alloc_expr(Expr::Missing, syntax_ptr);
609 }
610 } else {
611 self.exprs.alloc(Expr::Missing)
612 };
613 let body = self.collect_block_opt(e.loop_body()); 605 let body = self.collect_block_opt(e.loop_body());
606
607 let condition = match e.condition() {
608 None => self.exprs.alloc(Expr::Missing),
609 Some(condition) => match condition.pat() {
610 None => self.collect_expr_opt(condition.expr()),
611 // if let -- desugar to match
612 Some(pat) => {
613 tested_by!(infer_while_let);
614 let pat = self.collect_pat(pat);
615 let match_expr = self.collect_expr_opt(condition.expr());
616 let placeholder_pat = self.pats.alloc(Pat::Missing);
617 let break_ = self.exprs.alloc(Expr::Break { expr: None });
618 let arms = vec![
619 MatchArm { pats: vec![pat], expr: body, guard: None },
620 MatchArm { pats: vec![placeholder_pat], expr: break_, guard: None },
621 ];
622 let match_expr =
623 self.exprs.alloc(Expr::Match { expr: match_expr, arms });
624 return self.alloc_expr(Expr::Loop { body: match_expr }, syntax_ptr);
625 }
626 },
627 };
628
614 self.alloc_expr(Expr::While { condition, body }, syntax_ptr) 629 self.alloc_expr(Expr::While { condition, body }, syntax_ptr)
615 } 630 }
616 ast::ExprKind::ForExpr(e) => { 631 ast::ExprKind::ForExpr(e) => {
diff --git a/crates/ra_hir/src/marks.rs b/crates/ra_hir/src/marks.rs
index 2d831f0d8..5b15eee90 100644
--- a/crates/ra_hir/src/marks.rs
+++ b/crates/ra_hir/src/marks.rs
@@ -10,4 +10,5 @@ test_utils::marks!(
10 std_prelude 10 std_prelude
11 match_ergonomics_ref 11 match_ergonomics_ref
12 trait_resolution_on_fn_type 12 trait_resolution_on_fn_type
13 infer_while_let
13); 14);
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs
index 06b732215..7da2dcdff 100644
--- a/crates/ra_hir/src/nameres/collector.rs
+++ b/crates/ra_hir/src/nameres/collector.rs
@@ -483,7 +483,7 @@ struct ModCollector<'a, D> {
483 module_id: CrateModuleId, 483 module_id: CrateModuleId,
484 file_id: HirFileId, 484 file_id: HirFileId,
485 raw_items: &'a raw::RawItems, 485 raw_items: &'a raw::RawItems,
486 parent_module: Option<&'a Name>, 486 parent_module: Option<ParentModule<'a>>,
487} 487}
488 488
489impl<DB> ModCollector<'_, &'_ mut DefCollector<&'_ DB>> 489impl<DB> ModCollector<'_, &'_ mut DefCollector<&'_ DB>>
@@ -508,15 +508,16 @@ where
508 fn collect_module(&mut self, module: &raw::ModuleData) { 508 fn collect_module(&mut self, module: &raw::ModuleData) {
509 match module { 509 match module {
510 // inline module, just recurse 510 // inline module, just recurse
511 raw::ModuleData::Definition { name, items, ast_id } => { 511 raw::ModuleData::Definition { name, items, ast_id, attr_path } => {
512 let module_id = 512 let module_id =
513 self.push_child_module(name.clone(), ast_id.with_file_id(self.file_id), None); 513 self.push_child_module(name.clone(), ast_id.with_file_id(self.file_id), None);
514 let parent_module = ParentModule { name, attr_path: attr_path.as_ref() };
514 ModCollector { 515 ModCollector {
515 def_collector: &mut *self.def_collector, 516 def_collector: &mut *self.def_collector,
516 module_id, 517 module_id,
517 file_id: self.file_id, 518 file_id: self.file_id,
518 raw_items: self.raw_items, 519 raw_items: self.raw_items,
519 parent_module: Some(name), 520 parent_module: Some(parent_module),
520 } 521 }
521 .collect(&*items); 522 .collect(&*items);
522 } 523 }
@@ -530,7 +531,7 @@ where
530 name, 531 name,
531 is_root, 532 is_root,
532 attr_path.as_ref(), 533 attr_path.as_ref(),
533 self.parent_module, 534 self.parent_module.as_ref(),
534 ) { 535 ) {
535 Ok(file_id) => { 536 Ok(file_id) => {
536 let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id)); 537 let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id));
@@ -647,7 +648,7 @@ fn resolve_submodule(
647 name: &Name, 648 name: &Name,
648 is_root: bool, 649 is_root: bool,
649 attr_path: Option<&SmolStr>, 650 attr_path: Option<&SmolStr>,
650 parent_module: Option<&Name>, 651 parent_module: Option<&ParentModule>,
651) -> Result<FileId, RelativePathBuf> { 652) -> Result<FileId, RelativePathBuf> {
652 let file_id = file_id.original_file(db); 653 let file_id = file_id.original_file(db);
653 let source_root_id = db.file_source_root(file_id); 654 let source_root_id = db.file_source_root(file_id);
@@ -657,20 +658,49 @@ fn resolve_submodule(
657 let mod_name = path.file_stem().unwrap_or("unknown"); 658 let mod_name = path.file_stem().unwrap_or("unknown");
658 659
659 let resolve_mode = match (attr_path.filter(|p| !p.is_empty()), parent_module) { 660 let resolve_mode = match (attr_path.filter(|p| !p.is_empty()), parent_module) {
660 (Some(file_path), Some(parent_name)) => { 661 (Some(file_path), Some(parent_module)) => {
661 let file_path = normalize_attribute_path(file_path); 662 let file_path = normalize_attribute_path(file_path);
662 let path = dir_path.join(format!("{}/{}", parent_name, file_path)).normalize(); 663 match parent_module.attribute_path() {
663 ResolutionMode::InsideInlineModule(InsideInlineModuleMode::WithAttributePath(path)) 664 Some(parent_module_attr_path) => {
665 let path = dir_path
666 .join(format!(
667 "{}/{}",
668 normalize_attribute_path(parent_module_attr_path),
669 file_path
670 ))
671 .normalize();
672 ResolutionMode::InlineModuleWithAttributePath(
673 InsideInlineModuleMode::WithAttributePath(path),
674 )
675 }
676 None => {
677 let path =
678 dir_path.join(format!("{}/{}", parent_module.name, file_path)).normalize();
679 ResolutionMode::InsideInlineModule(InsideInlineModuleMode::WithAttributePath(
680 path,
681 ))
682 }
683 }
664 } 684 }
685 (None, Some(parent_module)) => match parent_module.attribute_path() {
686 Some(parent_module_attr_path) => {
687 let path = dir_path.join(format!(
688 "{}/{}.rs",
689 normalize_attribute_path(parent_module_attr_path),
690 name
691 ));
692 ResolutionMode::InlineModuleWithAttributePath(InsideInlineModuleMode::File(path))
693 }
694 None => {
695 let path = dir_path.join(format!("{}/{}.rs", parent_module.name, name));
696 ResolutionMode::InsideInlineModule(InsideInlineModuleMode::File(path))
697 }
698 },
665 (Some(file_path), None) => { 699 (Some(file_path), None) => {
666 let file_path = normalize_attribute_path(file_path); 700 let file_path = normalize_attribute_path(file_path);
667 let path = dir_path.join(file_path.as_ref()).normalize(); 701 let path = dir_path.join(file_path.as_ref()).normalize();
668 ResolutionMode::OutOfLine(OutOfLineMode::WithAttributePath(path)) 702 ResolutionMode::OutOfLine(OutOfLineMode::WithAttributePath(path))
669 } 703 }
670 (None, Some(parent_name)) => {
671 let path = dir_path.join(format!("{}/{}.rs", parent_name, name));
672 ResolutionMode::InsideInlineModule(InsideInlineModuleMode::File(path))
673 }
674 _ => { 704 _ => {
675 let is_dir_owner = is_root || mod_name == "mod"; 705 let is_dir_owner = is_root || mod_name == "mod";
676 if is_dir_owner { 706 if is_dir_owner {
@@ -743,6 +773,7 @@ impl InsideInlineModuleMode {
743enum ResolutionMode { 773enum ResolutionMode {
744 OutOfLine(OutOfLineMode), 774 OutOfLine(OutOfLineMode),
745 InsideInlineModule(InsideInlineModuleMode), 775 InsideInlineModule(InsideInlineModuleMode),
776 InlineModuleWithAttributePath(InsideInlineModuleMode),
746} 777}
747 778
748impl ResolutionMode { 779impl ResolutionMode {
@@ -752,6 +783,7 @@ impl ResolutionMode {
752 match self { 783 match self {
753 OutOfLine(mode) => mode.resolve(source_root), 784 OutOfLine(mode) => mode.resolve(source_root),
754 InsideInlineModule(mode) => mode.resolve(source_root), 785 InsideInlineModule(mode) => mode.resolve(source_root),
786 InlineModuleWithAttributePath(mode) => mode.resolve(source_root),
755 } 787 }
756 } 788 }
757} 789}
@@ -773,6 +805,17 @@ fn resolve_find_result(
773 } 805 }
774} 806}
775 807
808struct ParentModule<'a> {
809 name: &'a Name,
810 attr_path: Option<&'a SmolStr>,
811}
812
813impl<'a> ParentModule<'a> {
814 pub fn attribute_path(&self) -> Option<&SmolStr> {
815 self.attr_path.filter(|p| !p.is_empty())
816 }
817}
818
776#[cfg(test)] 819#[cfg(test)]
777mod tests { 820mod tests {
778 use ra_db::SourceDatabase; 821 use ra_db::SourceDatabase;
diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs
index 8517f3c43..584e15e29 100644
--- a/crates/ra_hir/src/nameres/raw.rs
+++ b/crates/ra_hir/src/nameres/raw.rs
@@ -130,8 +130,17 @@ impl_arena_id!(Module);
130 130
131#[derive(Debug, PartialEq, Eq)] 131#[derive(Debug, PartialEq, Eq)]
132pub(super) enum ModuleData { 132pub(super) enum ModuleData {
133 Declaration { name: Name, ast_id: FileAstId<ast::Module>, attr_path: Option<SmolStr> }, 133 Declaration {
134 Definition { name: Name, ast_id: FileAstId<ast::Module>, items: Vec<RawItem> }, 134 name: Name,
135 ast_id: FileAstId<ast::Module>,
136 attr_path: Option<SmolStr>,
137 },
138 Definition {
139 name: Name,
140 ast_id: FileAstId<ast::Module>,
141 items: Vec<RawItem>,
142 attr_path: Option<SmolStr>,
143 },
135} 144}
136 145
137#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 146#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -256,9 +265,9 @@ impl RawItemsCollector {
256 None => return, 265 None => return,
257 }; 266 };
258 267
259 let attr_path = extract_mod_path_attribute(&module);
260 let ast_id = self.source_ast_id_map.ast_id(&module); 268 let ast_id = self.source_ast_id_map.ast_id(&module);
261 if module.has_semi() { 269 if module.has_semi() {
270 let attr_path = extract_mod_path_attribute(&module);
262 let item = 271 let item =
263 self.raw_items.modules.alloc(ModuleData::Declaration { name, ast_id, attr_path }); 272 self.raw_items.modules.alloc(ModuleData::Declaration { name, ast_id, attr_path });
264 self.push_item(current_module, RawItem::Module(item)); 273 self.push_item(current_module, RawItem::Module(item));
@@ -266,10 +275,12 @@ impl RawItemsCollector {
266 } 275 }
267 276
268 if let Some(item_list) = module.item_list() { 277 if let Some(item_list) = module.item_list() {
278 let attr_path = extract_mod_path_attribute(&module);
269 let item = self.raw_items.modules.alloc(ModuleData::Definition { 279 let item = self.raw_items.modules.alloc(ModuleData::Definition {
270 name, 280 name,
271 ast_id, 281 ast_id,
272 items: Vec::new(), 282 items: Vec::new(),
283 attr_path,
273 }); 284 });
274 self.process_module(Some(item), item_list); 285 self.process_module(Some(item), item_list);
275 self.push_item(current_module, RawItem::Module(item)); 286 self.push_item(current_module, RawItem::Module(item));
diff --git a/crates/ra_hir/src/nameres/tests/mods.rs b/crates/ra_hir/src/nameres/tests/mods.rs
index 382728149..6dd18df1a 100644
--- a/crates/ra_hir/src/nameres/tests/mods.rs
+++ b/crates/ra_hir/src/nameres/tests/mods.rs
@@ -336,9 +336,7 @@ fn module_resolution_explicit_path_mod_rs_with_win_separator() {
336 "###); 336 "###);
337} 337}
338 338
339// FIXME: issue #1529. not support out-of-line modules inside inline.
340#[test] 339#[test]
341#[ignore]
342fn module_resolution_decl_inside_inline_module_with_path_attribute() { 340fn module_resolution_decl_inside_inline_module_with_path_attribute() {
343 let map = def_map_with_crate_graph( 341 let map = def_map_with_crate_graph(
344 r###" 342 r###"
@@ -397,9 +395,7 @@ fn module_resolution_decl_inside_inline_module() {
397 "###); 395 "###);
398} 396}
399 397
400// FIXME: issue #1529. not support out-of-line modules inside inline.
401#[test] 398#[test]
402#[ignore]
403fn module_resolution_decl_inside_inline_module_2_with_path_attribute() { 399fn module_resolution_decl_inside_inline_module_2_with_path_attribute() {
404 let map = def_map_with_crate_graph( 400 let map = def_map_with_crate_graph(
405 r###" 401 r###"
@@ -429,9 +425,7 @@ fn module_resolution_decl_inside_inline_module_2_with_path_attribute() {
429 "###); 425 "###);
430} 426}
431 427
432// FIXME: issue #1529. not support out-of-line modules inside inline.
433#[test] 428#[test]
434#[ignore]
435fn module_resolution_decl_inside_inline_module_3() { 429fn module_resolution_decl_inside_inline_module_3() {
436 let map = def_map_with_crate_graph( 430 let map = def_map_with_crate_graph(
437 r###" 431 r###"
@@ -462,9 +456,7 @@ fn module_resolution_decl_inside_inline_module_3() {
462 "###); 456 "###);
463} 457}
464 458
465// FIXME: issue #1529. not support out-of-line modules inside inline.
466#[test] 459#[test]
467#[ignore]
468fn module_resolution_decl_inside_inline_module_empty_path() { 460fn module_resolution_decl_inside_inline_module_empty_path() {
469 let map = def_map_with_crate_graph( 461 let map = def_map_with_crate_graph(
470 r###" 462 r###"
@@ -475,7 +467,7 @@ fn module_resolution_decl_inside_inline_module_empty_path() {
475 mod bar; 467 mod bar;
476 } 468 }
477 469
478 //- /users.rs 470 //- /foo/users.rs
479 pub struct Baz; 471 pub struct Baz;
480 "###, 472 "###,
481 crate_graph! { 473 crate_graph! {
@@ -520,9 +512,7 @@ fn module_resolution_decl_empty_path() {
520 "###); 512 "###);
521} 513}
522 514
523// FIXME: issue #1529. not support out-of-line modules inside inline.
524#[test] 515#[test]
525#[ignore]
526fn module_resolution_decl_inside_inline_module_relative_path() { 516fn module_resolution_decl_inside_inline_module_relative_path() {
527 let map = def_map_with_crate_graph( 517 let map = def_map_with_crate_graph(
528 r###" 518 r###"
@@ -660,9 +650,7 @@ fn module_resolution_decl_inside_inline_module_in_non_crate_root() {
660 "###); 650 "###);
661} 651}
662 652
663// FIXME: issue #1529. not support out-of-line modules inside inline.
664#[test] 653#[test]
665#[ignore]
666fn module_resolution_decl_inside_inline_module_in_non_crate_root_2() { 654fn module_resolution_decl_inside_inline_module_in_non_crate_root_2() {
667 let map = def_map_with_crate_graph( 655 let map = def_map_with_crate_graph(
668 r###" 656 r###"
diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs
index 882db7681..5ee71e421 100644
--- a/crates/ra_hir/src/path.rs
+++ b/crates/ra_hir/src/path.rs
@@ -25,6 +25,12 @@ pub struct PathSegment {
25#[derive(Debug, Clone, PartialEq, Eq, Hash)] 25#[derive(Debug, Clone, PartialEq, Eq, Hash)]
26pub struct GenericArgs { 26pub struct GenericArgs {
27 pub args: Vec<GenericArg>, 27 pub args: Vec<GenericArg>,
28 /// This specifies whether the args contain a Self type as the first
29 /// element. This is the case for path segments like `<T as Trait>`, where
30 /// `T` is actually a type parameter for the path `Trait` specifying the
31 /// Self type. Otherwise, when we have a path `Trait<X, Y>`, the Self type
32 /// is left out.
33 pub has_self_type: bool,
28 // someday also bindings 34 // someday also bindings
29} 35}
30 36
@@ -74,6 +80,28 @@ impl Path {
74 let segment = PathSegment { name: name.as_name(), args_and_bindings: args }; 80 let segment = PathSegment { name: name.as_name(), args_and_bindings: args };
75 segments.push(segment); 81 segments.push(segment);
76 } 82 }
83 ast::PathSegmentKind::Type { type_ref, trait_ref } => {
84 assert!(path.qualifier().is_none()); // this can only occur at the first segment
85
86 // FIXME: handle <T> syntax (type segments without trait)
87
88 // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
89 let path = Path::from_ast(trait_ref?.path()?)?;
90 kind = path.kind;
91 let mut prefix_segments = path.segments;
92 prefix_segments.reverse();
93 segments.extend(prefix_segments);
94 // Insert the type reference (T in the above example) as Self parameter for the trait
95 let self_type = TypeRef::from_ast(type_ref?);
96 let mut last_segment = segments.last_mut()?;
97 if last_segment.args_and_bindings.is_none() {
98 last_segment.args_and_bindings = Some(Arc::new(GenericArgs::empty()));
99 };
100 let args = last_segment.args_and_bindings.as_mut().unwrap();
101 let mut args_inner = Arc::make_mut(args);
102 args_inner.has_self_type = true;
103 args_inner.args.insert(0, GenericArg::Type(self_type));
104 }
77 ast::PathSegmentKind::CrateKw => { 105 ast::PathSegmentKind::CrateKw => {
78 kind = PathKind::Crate; 106 kind = PathKind::Crate;
79 break; 107 break;
@@ -144,11 +172,15 @@ impl GenericArgs {
144 } 172 }
145 // lifetimes and assoc type args ignored for now 173 // lifetimes and assoc type args ignored for now
146 if !args.is_empty() { 174 if !args.is_empty() {
147 Some(GenericArgs { args }) 175 Some(GenericArgs { args, has_self_type: false })
148 } else { 176 } else {
149 None 177 None
150 } 178 }
151 } 179 }
180
181 pub(crate) fn empty() -> GenericArgs {
182 GenericArgs { args: Vec::new(), has_self_type: false }
183 }
152} 184}
153 185
154impl From<Name> for Path { 186impl From<Name> for Path {
@@ -236,6 +268,10 @@ fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> {
236 } 268 }
237 Path { kind: PathKind::Super, segments: Vec::new() } 269 Path { kind: PathKind::Super, segments: Vec::new() }
238 } 270 }
271 ast::PathSegmentKind::Type { .. } => {
272 // not allowed in imports
273 return None;
274 }
239 }; 275 };
240 Some(res) 276 Some(res)
241} 277}
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index c2c6921cb..e86716d74 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -18,14 +18,18 @@ use ra_syntax::{
18use rustc_hash::{FxHashMap, FxHashSet}; 18use rustc_hash::{FxHashMap, FxHashSet};
19 19
20use crate::{ 20use crate::{
21 expr,
22 expr::{ 21 expr::{
22 self,
23 scope::{ExprScopes, ScopeId}, 23 scope::{ExprScopes, ScopeId},
24 BodySourceMap, 24 BodySourceMap,
25 }, 25 },
26 ids::LocationCtx, 26 ids::LocationCtx,
27 name,
28 path::{PathKind, PathSegment},
29 ty::method_resolution::implements_trait,
27 AsName, AstId, Const, Crate, DefWithBody, Either, Enum, Function, HirDatabase, HirFileId, 30 AsName, AstId, Const, Crate, DefWithBody, Either, Enum, Function, HirDatabase, HirFileId,
28 MacroDef, Module, Name, Path, PerNs, Resolver, Static, Struct, Trait, Ty, 31 MacroDef, Module, ModuleDef, Name, Path, PerNs, Resolution, Resolver, Static, Struct, Trait,
32 Ty,
29}; 33};
30 34
31/// Locates the module by `FileId`. Picks topmost module in the file. 35/// Locates the module by `FileId`. Picks topmost module in the file.
@@ -409,6 +413,33 @@ impl SourceAnalyzer {
409 crate::ty::autoderef(db, &self.resolver, canonical).map(|canonical| canonical.value) 413 crate::ty::autoderef(db, &self.resolver, canonical).map(|canonical| canonical.value)
410 } 414 }
411 415
416 /// Checks that particular type `ty` implements `std::future::Future`.
417 /// This function is used in `.await` syntax completion.
418 pub fn impls_future(&self, db: &impl HirDatabase, ty: Ty) -> bool {
419 let std_future_path = Path {
420 kind: PathKind::Abs,
421 segments: vec![
422 PathSegment { name: name::STD, args_and_bindings: None },
423 PathSegment { name: name::FUTURE_MOD, args_and_bindings: None },
424 PathSegment { name: name::FUTURE_TYPE, args_and_bindings: None },
425 ],
426 };
427
428 let std_future_trait =
429 match self.resolver.resolve_path_segments(db, &std_future_path).into_fully_resolved() {
430 PerNs { types: Some(Resolution::Def(ModuleDef::Trait(trait_))), .. } => trait_,
431 _ => return false,
432 };
433
434 let krate = match self.resolver.krate() {
435 Some(krate) => krate,
436 _ => return false,
437 };
438
439 let canonical_ty = crate::ty::Canonical { value: ty, num_vars: 0 };
440 implements_trait(&canonical_ty, db, &self.resolver, krate, std_future_trait)
441 }
442
412 #[cfg(test)] 443 #[cfg(test)]
413 pub(crate) fn body_source_map(&self) -> Arc<BodySourceMap> { 444 pub(crate) fn body_source_map(&self) -> Arc<BodySourceMap> {
414 self.body_source_map.clone().unwrap() 445 self.body_source_map.clone().unwrap()
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 82589e504..642dd02cb 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -94,6 +94,12 @@ pub enum TypeCtor {
94 94
95 /// A tuple type. For example, `(i32, bool)`. 95 /// A tuple type. For example, `(i32, bool)`.
96 Tuple { cardinality: u16 }, 96 Tuple { cardinality: u16 },
97
98 /// Represents an associated item like `Iterator::Item`. This is used
99 /// when we have tried to normalize a projection like `T::Item` but
100 /// couldn't find a better representation. In that case, we generate
101 /// an **application type** like `(Iterator::Item)<T>`.
102 AssociatedType(TypeAlias),
97} 103}
98 104
99/// A nominal type with (maybe 0) type parameters. This might be a primitive 105/// A nominal type with (maybe 0) type parameters. This might be a primitive
@@ -114,6 +120,12 @@ pub struct ProjectionTy {
114 pub parameters: Substs, 120 pub parameters: Substs,
115} 121}
116 122
123#[derive(Clone, PartialEq, Eq, Debug, Hash)]
124pub struct UnselectedProjectionTy {
125 pub type_name: Name,
126 pub parameters: Substs,
127}
128
117/// A type. 129/// A type.
118/// 130///
119/// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents 131/// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents
@@ -127,6 +139,18 @@ pub enum Ty {
127 /// several other things. 139 /// several other things.
128 Apply(ApplicationTy), 140 Apply(ApplicationTy),
129 141
142 /// A "projection" type corresponds to an (unnormalized)
143 /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the
144 /// trait and all its parameters are fully known.
145 Projection(ProjectionTy),
146
147 /// This is a variant of a projection in which the trait is
148 /// **not** known. It corresponds to a case where people write
149 /// `T::Item` without specifying the trait. We would then try to
150 /// figure out the trait by looking at all the traits that are in
151 /// scope.
152 UnselectedProjection(UnselectedProjectionTy),
153
130 /// A type parameter; for example, `T` in `fn f<T>(x: T) {} 154 /// A type parameter; for example, `T` in `fn f<T>(x: T) {}
131 Param { 155 Param {
132 /// The index of the parameter (starting with parameters from the 156 /// The index of the parameter (starting with parameters from the
@@ -352,6 +376,16 @@ impl Ty {
352 t.walk(f); 376 t.walk(f);
353 } 377 }
354 } 378 }
379 Ty::Projection(p_ty) => {
380 for t in p_ty.parameters.iter() {
381 t.walk(f);
382 }
383 }
384 Ty::UnselectedProjection(p_ty) => {
385 for t in p_ty.parameters.iter() {
386 t.walk(f);
387 }
388 }
355 Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} 389 Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
356 } 390 }
357 f(self); 391 f(self);
@@ -362,6 +396,12 @@ impl Ty {
362 Ty::Apply(a_ty) => { 396 Ty::Apply(a_ty) => {
363 a_ty.parameters.walk_mut(f); 397 a_ty.parameters.walk_mut(f);
364 } 398 }
399 Ty::Projection(p_ty) => {
400 p_ty.parameters.walk_mut(f);
401 }
402 Ty::UnselectedProjection(p_ty) => {
403 p_ty.parameters.walk_mut(f);
404 }
365 Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} 405 Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
366 } 406 }
367 f(self); 407 f(self);
@@ -572,15 +612,61 @@ impl HirDisplay for ApplicationTy {
572 write!(f, ">")?; 612 write!(f, ">")?;
573 } 613 }
574 } 614 }
615 TypeCtor::AssociatedType(type_alias) => {
616 let trait_name = type_alias
617 .parent_trait(f.db)
618 .and_then(|t| t.name(f.db))
619 .unwrap_or_else(Name::missing);
620 let name = type_alias.name(f.db);
621 write!(f, "{}::{}", trait_name, name)?;
622 if self.parameters.len() > 0 {
623 write!(f, "<")?;
624 f.write_joined(&*self.parameters.0, ", ")?;
625 write!(f, ">")?;
626 }
627 }
575 } 628 }
576 Ok(()) 629 Ok(())
577 } 630 }
578} 631}
579 632
633impl HirDisplay for ProjectionTy {
634 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
635 let trait_name = self
636 .associated_ty
637 .parent_trait(f.db)
638 .and_then(|t| t.name(f.db))
639 .unwrap_or_else(Name::missing);
640 write!(f, "<{} as {}", self.parameters[0].display(f.db), trait_name,)?;
641 if self.parameters.len() > 1 {
642 write!(f, "<")?;
643 f.write_joined(&self.parameters[1..], ", ")?;
644 write!(f, ">")?;
645 }
646 write!(f, ">::{}", self.associated_ty.name(f.db))?;
647 Ok(())
648 }
649}
650
651impl HirDisplay for UnselectedProjectionTy {
652 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
653 write!(f, "{}", self.parameters[0].display(f.db))?;
654 if self.parameters.len() > 1 {
655 write!(f, "<")?;
656 f.write_joined(&self.parameters[1..], ", ")?;
657 write!(f, ">")?;
658 }
659 write!(f, "::{}", self.type_name)?;
660 Ok(())
661 }
662}
663
580impl HirDisplay for Ty { 664impl HirDisplay for Ty {
581 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { 665 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
582 match self { 666 match self {
583 Ty::Apply(a_ty) => a_ty.hir_fmt(f)?, 667 Ty::Apply(a_ty) => a_ty.hir_fmt(f)?,
668 Ty::Projection(p_ty) => p_ty.hir_fmt(f)?,
669 Ty::UnselectedProjection(p_ty) => p_ty.hir_fmt(f)?,
584 Ty::Param { name, .. } => write!(f, "{}", name)?, 670 Ty::Param { name, .. } => write!(f, "{}", name)?,
585 Ty::Bound(idx) => write!(f, "?{}", idx)?, 671 Ty::Bound(idx) => write!(f, "?{}", idx)?,
586 Ty::Unknown => write!(f, "{{unknown}}")?, 672 Ty::Unknown => write!(f, "{{unknown}}")?,
@@ -606,3 +692,17 @@ impl HirDisplay for TraitRef {
606 Ok(()) 692 Ok(())
607 } 693 }
608} 694}
695
696impl HirDisplay for Obligation {
697 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
698 match self {
699 Obligation::Trait(tr) => write!(f, "Implements({})", tr.display(f.db)),
700 Obligation::Projection(proj) => write!(
701 f,
702 "Normalize({} => {})",
703 proj.projection_ty.display(f.db),
704 proj.ty.display(f.db)
705 ),
706 }
707 }
708}
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 594c5bc79..675df4a22 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -245,7 +245,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
245 &self.resolver, 245 &self.resolver,
246 type_ref, 246 type_ref,
247 ); 247 );
248 self.insert_type_vars(ty) 248 let ty = self.insert_type_vars(ty);
249 self.normalize_associated_types_in(ty)
249 } 250 }
250 251
251 fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs, depth: usize) -> bool { 252 fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs, depth: usize) -> bool {
@@ -411,6 +412,32 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
411 ty 412 ty
412 } 413 }
413 414
415 /// Recurses through the given type, normalizing associated types mentioned
416 /// in it by replacing them by type variables and registering obligations to
417 /// resolve later. This should be done once for every type we get from some
418 /// type annotation (e.g. from a let type annotation, field type or function
419 /// call). `make_ty` handles this already, but e.g. for field types we need
420 /// to do it as well.
421 fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty {
422 let ty = self.resolve_ty_as_possible(&mut vec![], ty);
423 ty.fold(&mut |ty| match ty {
424 Ty::Projection(proj_ty) => self.normalize_projection_ty(proj_ty),
425 Ty::UnselectedProjection(proj_ty) => {
426 // FIXME use Chalk's unselected projection support
427 Ty::UnselectedProjection(proj_ty)
428 }
429 _ => ty,
430 })
431 }
432
433 fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
434 let var = self.new_type_var();
435 let predicate = ProjectionPredicate { projection_ty: proj_ty.clone(), ty: var.clone() };
436 let obligation = Obligation::Projection(predicate);
437 self.obligations.push(obligation);
438 var
439 }
440
414 /// Resolves the type completely; type variables without known type are 441 /// Resolves the type completely; type variables without known type are
415 /// replaced by Ty::Unknown. 442 /// replaced by Ty::Unknown.
416 fn resolve_ty_completely(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { 443 fn resolve_ty_completely(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
@@ -549,6 +576,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
549 let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); 576 let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable);
550 let ty = ty.subst(&substs); 577 let ty = ty.subst(&substs);
551 let ty = self.insert_type_vars(ty); 578 let ty = self.insert_type_vars(ty);
579 let ty = self.normalize_associated_types_in(ty);
552 Some(ty) 580 Some(ty)
553 } 581 }
554 Resolution::LocalBinding(pat) => { 582 Resolution::LocalBinding(pat) => {
@@ -670,6 +698,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
670 .and_then(|d| d.field(self.db, &Name::tuple_field_name(i))) 698 .and_then(|d| d.field(self.db, &Name::tuple_field_name(i)))
671 .map_or(Ty::Unknown, |field| field.ty(self.db)) 699 .map_or(Ty::Unknown, |field| field.ty(self.db))
672 .subst(&substs); 700 .subst(&substs);
701 let expected_ty = self.normalize_associated_types_in(expected_ty);
673 self.infer_pat(subpat, &expected_ty, default_bm); 702 self.infer_pat(subpat, &expected_ty, default_bm);
674 } 703 }
675 704
@@ -697,6 +726,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
697 let matching_field = def.and_then(|it| it.field(self.db, &subpat.name)); 726 let matching_field = def.and_then(|it| it.field(self.db, &subpat.name));
698 let expected_ty = 727 let expected_ty =
699 matching_field.map_or(Ty::Unknown, |field| field.ty(self.db)).subst(&substs); 728 matching_field.map_or(Ty::Unknown, |field| field.ty(self.db)).subst(&substs);
729 let expected_ty = self.normalize_associated_types_in(expected_ty);
700 self.infer_pat(subpat.pat, &expected_ty, default_bm); 730 self.infer_pat(subpat.pat, &expected_ty, default_bm);
701 } 731 }
702 732
@@ -927,9 +957,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
927 self.unify(&expected_receiver_ty, &actual_receiver_ty); 957 self.unify(&expected_receiver_ty, &actual_receiver_ty);
928 958
929 let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); 959 let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown));
930 for (arg, param) in args.iter().zip(param_iter) { 960 for (arg, param_ty) in args.iter().zip(param_iter) {
931 self.infer_expr(*arg, &Expectation::has_type(param)); 961 let param_ty = self.normalize_associated_types_in(param_ty);
962 self.infer_expr(*arg, &Expectation::has_type(param_ty));
932 } 963 }
964 let ret_ty = self.normalize_associated_types_in(ret_ty);
933 ret_ty 965 ret_ty
934 } 966 }
935 967
@@ -1020,9 +1052,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1020 }; 1052 };
1021 self.register_obligations_for_call(&callee_ty); 1053 self.register_obligations_for_call(&callee_ty);
1022 let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); 1054 let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown));
1023 for (arg, param) in args.iter().zip(param_iter) { 1055 for (arg, param_ty) in args.iter().zip(param_iter) {
1024 self.infer_expr(*arg, &Expectation::has_type(param)); 1056 let param_ty = self.normalize_associated_types_in(param_ty);
1057 self.infer_expr(*arg, &Expectation::has_type(param_ty));
1025 } 1058 }
1059 let ret_ty = self.normalize_associated_types_in(ret_ty);
1026 ret_ty 1060 ret_ty
1027 } 1061 }
1028 Expr::MethodCall { receiver, args, method_name, generic_args } => self 1062 Expr::MethodCall { receiver, args, method_name, generic_args } => self
@@ -1120,7 +1154,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1120 _ => None, 1154 _ => None,
1121 }) 1155 })
1122 .unwrap_or(Ty::Unknown); 1156 .unwrap_or(Ty::Unknown);
1123 self.insert_type_vars(ty) 1157 let ty = self.insert_type_vars(ty);
1158 self.normalize_associated_types_in(ty)
1124 } 1159 }
1125 Expr::Await { expr } => { 1160 Expr::Await { expr } => {
1126 let inner_ty = self.infer_expr(*expr, &Expectation::none()); 1161 let inner_ty = self.infer_expr(*expr, &Expectation::none());
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 894ba0695..debedcbb8 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -8,7 +8,7 @@
8use std::iter; 8use std::iter;
9use std::sync::Arc; 9use std::sync::Arc;
10 10
11use super::{FnSig, GenericPredicate, Substs, TraitRef, Ty, TypeCtor}; 11use super::{FnSig, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor};
12use crate::{ 12use crate::{
13 adt::VariantDef, 13 adt::VariantDef,
14 generics::HasGenericParams, 14 generics::HasGenericParams,
@@ -64,7 +64,8 @@ impl Ty {
64 64
65 pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Self { 65 pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Self {
66 // Resolve the path (in type namespace) 66 // Resolve the path (in type namespace)
67 let resolution = resolver.resolve_path_without_assoc_items(db, path).take_types(); 67 let (resolution, remaining_index) = resolver.resolve_path_segments(db, path).into_inner();
68 let resolution = resolution.take_types();
68 69
69 let def = match resolution { 70 let def = match resolution {
70 Some(Resolution::Def(def)) => def, 71 Some(Resolution::Def(def)) => def,
@@ -73,6 +74,10 @@ impl Ty {
73 panic!("path resolved to local binding in type ns"); 74 panic!("path resolved to local binding in type ns");
74 } 75 }
75 Some(Resolution::GenericParam(idx)) => { 76 Some(Resolution::GenericParam(idx)) => {
77 if remaining_index.is_some() {
78 // e.g. T::Item
79 return Ty::Unknown;
80 }
76 return Ty::Param { 81 return Ty::Param {
77 idx, 82 idx,
78 // FIXME: maybe return name in resolution? 83 // FIXME: maybe return name in resolution?
@@ -83,18 +88,54 @@ impl Ty {
83 }; 88 };
84 } 89 }
85 Some(Resolution::SelfType(impl_block)) => { 90 Some(Resolution::SelfType(impl_block)) => {
91 if remaining_index.is_some() {
92 // e.g. Self::Item
93 return Ty::Unknown;
94 }
86 return impl_block.target_ty(db); 95 return impl_block.target_ty(db);
87 } 96 }
88 None => return Ty::Unknown, 97 None => {
98 // path did not resolve
99 return Ty::Unknown;
100 }
89 }; 101 };
90 102
91 let typable: TypableDef = match def.into() { 103 if let ModuleDef::Trait(trait_) = def {
92 None => return Ty::Unknown, 104 let segment = match remaining_index {
93 Some(it) => it, 105 None => path.segments.last().expect("resolved path has at least one element"),
94 }; 106 Some(i) => &path.segments[i - 1],
95 let ty = db.type_for_def(typable, Namespace::Types); 107 };
96 let substs = Ty::substs_from_path(db, resolver, path, typable); 108 let trait_ref = TraitRef::from_resolved_path(db, resolver, trait_, segment, None);
97 ty.subst(&substs) 109 if let Some(remaining_index) = remaining_index {
110 if remaining_index == path.segments.len() - 1 {
111 let segment = &path.segments[remaining_index];
112 let associated_ty =
113 match trait_ref.trait_.associated_type_by_name(db, segment.name.clone()) {
114 Some(t) => t,
115 None => {
116 // associated type not found
117 return Ty::Unknown;
118 }
119 };
120 // FIXME handle type parameters on the segment
121 Ty::Projection(ProjectionTy { associated_ty, parameters: trait_ref.substs })
122 } else {
123 // FIXME more than one segment remaining, is this possible?
124 Ty::Unknown
125 }
126 } else {
127 // FIXME dyn Trait without the dyn
128 Ty::Unknown
129 }
130 } else {
131 let typable: TypableDef = match def.into() {
132 None => return Ty::Unknown,
133 Some(it) => it,
134 };
135 let ty = db.type_for_def(typable, Namespace::Types);
136 let substs = Ty::substs_from_path(db, resolver, path, typable);
137 ty.subst(&substs)
138 }
98 } 139 }
99 140
100 pub(super) fn substs_from_path_segment( 141 pub(super) fn substs_from_path_segment(
@@ -219,14 +260,25 @@ impl TraitRef {
219 Resolution::Def(ModuleDef::Trait(tr)) => tr, 260 Resolution::Def(ModuleDef::Trait(tr)) => tr,
220 _ => return None, 261 _ => return None,
221 }; 262 };
222 let mut substs = Self::substs_from_path(db, resolver, path, resolved); 263 let segment = path.segments.last().expect("path should have at least one segment");
264 Some(TraitRef::from_resolved_path(db, resolver, resolved, segment, explicit_self_ty))
265 }
266
267 fn from_resolved_path(
268 db: &impl HirDatabase,
269 resolver: &Resolver,
270 resolved: Trait,
271 segment: &PathSegment,
272 explicit_self_ty: Option<Ty>,
273 ) -> Self {
274 let mut substs = TraitRef::substs_from_path(db, resolver, segment, resolved);
223 if let Some(self_ty) = explicit_self_ty { 275 if let Some(self_ty) = explicit_self_ty {
224 // FIXME this could be nicer 276 // FIXME this could be nicer
225 let mut substs_vec = substs.0.to_vec(); 277 let mut substs_vec = substs.0.to_vec();
226 substs_vec[0] = self_ty; 278 substs_vec[0] = self_ty;
227 substs.0 = substs_vec.into(); 279 substs.0 = substs_vec.into();
228 } 280 }
229 Some(TraitRef { trait_: resolved, substs }) 281 TraitRef { trait_: resolved, substs }
230 } 282 }
231 283
232 pub(crate) fn from_hir( 284 pub(crate) fn from_hir(
@@ -245,11 +297,12 @@ impl TraitRef {
245 fn substs_from_path( 297 fn substs_from_path(
246 db: &impl HirDatabase, 298 db: &impl HirDatabase,
247 resolver: &Resolver, 299 resolver: &Resolver,
248 path: &Path, 300 segment: &PathSegment,
249 resolved: Trait, 301 resolved: Trait,
250 ) -> Substs { 302 ) -> Substs {
251 let segment = path.segments.last().expect("path should have at least one segment"); 303 let has_self_param =
252 substs_from_path_segment(db, resolver, segment, Some(resolved.into()), true) 304 segment.args_and_bindings.as_ref().map(|a| a.has_self_type).unwrap_or(false);
305 substs_from_path_segment(db, resolver, segment, Some(resolved.into()), !has_self_param)
253 } 306 }
254 307
255 pub(crate) fn for_trait(db: &impl HirDatabase, trait_: Trait) -> TraitRef { 308 pub(crate) fn for_trait(db: &impl HirDatabase, trait_: Trait) -> TraitRef {
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index d421bf9ef..88d012a74 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -255,6 +255,20 @@ fn iterate_inherent_methods<T>(
255 None 255 None
256} 256}
257 257
258pub(crate) fn implements_trait(
259 ty: &Canonical<Ty>,
260 db: &impl HirDatabase,
261 resolver: &Resolver,
262 krate: Crate,
263 trait_: Trait,
264) -> bool {
265 let env = lower::trait_env(db, resolver);
266 let goal = generic_implements_goal(db, env.clone(), trait_, ty.clone());
267 let solution = db.trait_solve(krate, goal);
268
269 solution.is_some()
270}
271
258impl Ty { 272impl Ty {
259 // This would be nicer if it just returned an iterator, but that runs into 273 // This would be nicer if it just returned an iterator, but that runs into
260 // lifetime problems, because we need to borrow temp `CrateImplBlocks`. 274 // lifetime problems, because we need to borrow temp `CrateImplBlocks`.
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 36dea17a3..28727bb18 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -145,6 +145,26 @@ mod collections {
145} 145}
146 146
147#[test] 147#[test]
148fn infer_while_let() {
149 covers!(infer_while_let);
150 let (db, pos) = MockDatabase::with_position(
151 r#"
152//- /main.rs
153enum Option<T> { Some(T), None }
154
155fn test() {
156 let foo: Option<f32> = None;
157 while let Option::Some(x) = foo {
158 <|>x
159 }
160}
161
162"#,
163 );
164 assert_eq!("f32", type_at_pos(&db, pos));
165}
166
167#[test]
148fn infer_basics() { 168fn infer_basics() {
149 assert_snapshot_matches!( 169 assert_snapshot_matches!(
150 infer(r#" 170 infer(r#"
@@ -2488,15 +2508,55 @@ struct S;
2488impl Iterable for S { type Item = u32; } 2508impl Iterable for S { type Item = u32; }
2489fn test<T: Iterable>() { 2509fn test<T: Iterable>() {
2490 let x: <S as Iterable>::Item = 1; 2510 let x: <S as Iterable>::Item = 1;
2491 let y: T::Item = no_matter; 2511 let y: <T as Iterable>::Item = no_matter;
2512 let z: T::Item = no_matter;
2513}
2514"#),
2515 @r###"
2516
2517 ⋮[108; 227) '{ ...ter; }': ()
2518 ⋮[118; 119) 'x': u32
2519 ⋮[145; 146) '1': u32
2520 ⋮[156; 157) 'y': {unknown}
2521 ⋮[183; 192) 'no_matter': {unknown}
2522 ⋮[202; 203) 'z': {unknown}
2523 ⋮[215; 224) 'no_matter': {unknown}
2524 "###
2525 );
2526}
2527
2528#[test]
2529fn infer_return_associated_type() {
2530 assert_snapshot_matches!(
2531 infer(r#"
2532trait Iterable {
2533 type Item;
2534}
2535struct S;
2536impl Iterable for S { type Item = u32; }
2537fn foo1<T: Iterable>(t: T) -> T::Item {}
2538fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item {}
2539fn test() {
2540 let x = foo1(S);
2541 let y = foo2(S);
2492} 2542}
2493"#), 2543"#),
2494 @r###" 2544 @r###"
2495[108; 181) '{ ...ter; }': () 2545
2496[118; 119) 'x': i32 2546 ⋮[106; 107) 't': T
2497[145; 146) '1': i32 2547 ⋮[123; 125) '{}': ()
2498[156; 157) 'y': {unknown} 2548 ⋮[147; 148) 't': T
2499[169; 178) 'no_matter': {unknown}"### 2549 ⋮[178; 180) '{}': ()
2550 ⋮[191; 236) '{ ...(S); }': ()
2551 ⋮[201; 202) 'x': {unknown}
2552 ⋮[205; 209) 'foo1': fn foo1<S>(T) -> {unknown}
2553 ⋮[205; 212) 'foo1(S)': {unknown}
2554 ⋮[210; 211) 'S': S
2555 ⋮[222; 223) 'y': u32
2556 ⋮[226; 230) 'foo2': fn foo2<S>(T) -> <T as Iterable>::Item
2557 ⋮[226; 233) 'foo2(S)': u32
2558 ⋮[231; 232) 'S': S
2559 "###
2500 ); 2560 );
2501} 2561}
2502 2562
@@ -3121,6 +3181,55 @@ fn test<T: Trait>(t: T) { (*t)<|>; }
3121 assert_eq!(t, "i128"); 3181 assert_eq!(t, "i128");
3122} 3182}
3123 3183
3184#[test]
3185fn associated_type_placeholder() {
3186 let t = type_at(
3187 r#"
3188//- /main.rs
3189pub trait ApplyL {
3190 type Out;
3191}
3192
3193pub struct RefMutL<T>;
3194
3195impl<T> ApplyL for RefMutL<T> {
3196 type Out = <T as ApplyL>::Out;
3197}
3198
3199fn test<T: ApplyL>() {
3200 let y: <RefMutL<T> as ApplyL>::Out = no_matter;
3201 y<|>;
3202}
3203"#,
3204 );
3205 // inside the generic function, the associated type gets normalized to a placeholder `ApplL::Out<T>` [https://rust-lang.github.io/rustc-guide/traits/associated-types.html#placeholder-associated-types].
3206 // FIXME: fix type parameter names going missing when going through Chalk
3207 assert_eq!(t, "ApplyL::Out<[missing name]>");
3208}
3209
3210#[test]
3211fn associated_type_placeholder_2() {
3212 let t = type_at(
3213 r#"
3214//- /main.rs
3215pub trait ApplyL {
3216 type Out;
3217}
3218fn foo<T: ApplyL>(t: T) -> <T as ApplyL>::Out;
3219
3220fn test<T: ApplyL>(t: T) {
3221 let y = foo(t);
3222 y<|>;
3223}
3224"#,
3225 );
3226 // FIXME here Chalk doesn't normalize the type to a placeholder. I think we
3227 // need to add a rule like Normalize(<T as ApplyL>::Out -> ApplyL::Out<T>)
3228 // to the trait env ourselves here; probably Chalk can't do this by itself.
3229 // assert_eq!(t, "ApplyL::Out<[missing name]>");
3230 assert_eq!(t, "{unknown}");
3231}
3232
3124fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { 3233fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String {
3125 let file = db.parse(pos.file_id).ok().unwrap(); 3234 let file = db.parse(pos.file_id).ok().unwrap();
3126 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); 3235 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap();
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs
index 0769e6e17..fde5d8a47 100644
--- a/crates/ra_hir/src/ty/traits.rs
+++ b/crates/ra_hir/src/ty/traits.rs
@@ -7,7 +7,7 @@ use parking_lot::Mutex;
7use ra_prof::profile; 7use ra_prof::profile;
8use rustc_hash::FxHashSet; 8use rustc_hash::FxHashSet;
9 9
10use super::{Canonical, GenericPredicate, ProjectionTy, TraitRef, Ty}; 10use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty};
11use crate::{db::HirDatabase, Crate, ImplBlock, Trait}; 11use crate::{db::HirDatabase, Crate, ImplBlock, Trait};
12 12
13use self::chalk::{from_chalk, ToChalk}; 13use self::chalk::{from_chalk, ToChalk};
@@ -61,7 +61,6 @@ fn solve(
61) -> Option<chalk_solve::Solution> { 61) -> Option<chalk_solve::Solution> {
62 let context = ChalkContext { db, krate }; 62 let context = ChalkContext { db, krate };
63 let solver = db.trait_solver(krate); 63 let solver = db.trait_solver(krate);
64 debug!("solve goal: {:?}", goal);
65 let solution = solver.lock().solve(&context, goal); 64 let solution = solver.lock().solve(&context, goal);
66 debug!("solve({:?}) => {:?}", goal, solution); 65 debug!("solve({:?}) => {:?}", goal, solution);
67 solution 66 solution
@@ -120,10 +119,11 @@ pub struct ProjectionPredicate {
120pub(crate) fn trait_solve_query( 119pub(crate) fn trait_solve_query(
121 db: &impl HirDatabase, 120 db: &impl HirDatabase,
122 krate: Crate, 121 krate: Crate,
123 trait_ref: Canonical<InEnvironment<Obligation>>, 122 goal: Canonical<InEnvironment<Obligation>>,
124) -> Option<Solution> { 123) -> Option<Solution> {
125 let _p = profile("trait_solve_query"); 124 let _p = profile("trait_solve_query");
126 let canonical = trait_ref.to_chalk(db).cast(); 125 debug!("trait_solve_query({})", goal.value.value.display(db));
126 let canonical = goal.to_chalk(db).cast();
127 // We currently don't deal with universes (I think / hope they're not yet 127 // We currently don't deal with universes (I think / hope they're not yet
128 // relevant for our use cases?) 128 // relevant for our use cases?)
129 let u_canonical = chalk_ir::UCanonical { canonical, universes: 1 }; 129 let u_canonical = chalk_ir::UCanonical { canonical, universes: 1 };
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 9e7ae0724..6df7094c5 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -45,11 +45,33 @@ impl ToChalk for Ty {
45 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Ty { 45 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Ty {
46 match self { 46 match self {
47 Ty::Apply(apply_ty) => { 47 Ty::Apply(apply_ty) => {
48 let struct_id = apply_ty.ctor.to_chalk(db); 48 let name = match apply_ty.ctor {
49 let name = TypeName::TypeKindId(struct_id.into()); 49 TypeCtor::AssociatedType(type_alias) => {
50 let type_id = type_alias.to_chalk(db);
51 TypeName::AssociatedType(type_id)
52 }
53 _ => {
54 // other TypeCtors get interned and turned into a chalk StructId
55 let struct_id = apply_ty.ctor.to_chalk(db);
56 TypeName::TypeKindId(struct_id.into())
57 }
58 };
50 let parameters = apply_ty.parameters.to_chalk(db); 59 let parameters = apply_ty.parameters.to_chalk(db);
51 chalk_ir::ApplicationTy { name, parameters }.cast() 60 chalk_ir::ApplicationTy { name, parameters }.cast()
52 } 61 }
62 Ty::Projection(proj_ty) => {
63 let associated_ty_id = proj_ty.associated_ty.to_chalk(db);
64 let parameters = proj_ty.parameters.to_chalk(db);
65 chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast()
66 }
67 Ty::UnselectedProjection(proj_ty) => {
68 let type_name = lalrpop_intern::intern(&proj_ty.type_name.to_string());
69 let parameters = proj_ty.parameters.to_chalk(db);
70 chalk_ir::Ty::UnselectedProjection(chalk_ir::UnselectedProjectionTy {
71 type_name,
72 parameters,
73 })
74 }
53 Ty::Param { idx, .. } => { 75 Ty::Param { idx, .. } => {
54 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }.to_ty() 76 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }.to_ty()
55 } 77 }
@@ -66,15 +88,21 @@ impl ToChalk for Ty {
66 fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty) -> Self { 88 fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty) -> Self {
67 match chalk { 89 match chalk {
68 chalk_ir::Ty::Apply(apply_ty) => { 90 chalk_ir::Ty::Apply(apply_ty) => {
91 // FIXME this is kind of hacky due to the fact that
92 // TypeName::Placeholder is a Ty::Param on our side
69 match apply_ty.name { 93 match apply_ty.name {
70 TypeName::TypeKindId(TypeKindId::StructId(struct_id)) => { 94 TypeName::TypeKindId(TypeKindId::StructId(struct_id)) => {
71 let ctor = from_chalk(db, struct_id); 95 let ctor = from_chalk(db, struct_id);
72 let parameters = from_chalk(db, apply_ty.parameters); 96 let parameters = from_chalk(db, apply_ty.parameters);
73 Ty::Apply(ApplicationTy { ctor, parameters }) 97 Ty::Apply(ApplicationTy { ctor, parameters })
74 } 98 }
99 TypeName::AssociatedType(type_id) => {
100 let ctor = TypeCtor::AssociatedType(from_chalk(db, type_id));
101 let parameters = from_chalk(db, apply_ty.parameters);
102 Ty::Apply(ApplicationTy { ctor, parameters })
103 }
75 // FIXME handle TypeKindId::Trait/Type here 104 // FIXME handle TypeKindId::Trait/Type here
76 TypeName::TypeKindId(_) => unimplemented!(), 105 TypeName::TypeKindId(_) => unimplemented!(),
77 TypeName::AssociatedType(_) => unimplemented!(),
78 TypeName::Placeholder(idx) => { 106 TypeName::Placeholder(idx) => {
79 assert_eq!(idx.ui, UniverseIndex::ROOT); 107 assert_eq!(idx.ui, UniverseIndex::ROOT);
80 Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() } 108 Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() }
@@ -389,11 +417,12 @@ where
389 &self, 417 &self,
390 projection: &'p chalk_ir::ProjectionTy, 418 projection: &'p chalk_ir::ProjectionTy,
391 ) -> (Arc<AssociatedTyDatum>, &'p [Parameter], &'p [Parameter]) { 419 ) -> (Arc<AssociatedTyDatum>, &'p [Parameter], &'p [Parameter]) {
392 debug!("split_projection {:?}", projection); 420 let proj_ty: ProjectionTy = from_chalk(self.db, projection.clone());
393 unimplemented!() 421 debug!("split_projection {:?} = {}", projection, proj_ty.display(self.db));
422 // we don't support GATs, so I think this should always be correct currently
423 (self.db.associated_ty_data(projection.associated_ty_id), &projection.parameters, &[])
394 } 424 }
395 fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause> { 425 fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause> {
396 debug!("custom_clauses");
397 vec![] 426 vec![]
398 } 427 }
399 fn all_structs(&self) -> Vec<chalk_ir::StructId> { 428 fn all_structs(&self) -> Vec<chalk_ir::StructId> {
@@ -529,6 +558,16 @@ pub(crate) fn struct_datum_query(
529 adt.krate(db) != Some(krate), 558 adt.krate(db) != Some(krate),
530 ) 559 )
531 } 560 }
561 TypeCtor::AssociatedType(type_alias) => {
562 let generic_params = type_alias.generic_params(db);
563 let bound_vars = Substs::bound_vars(&generic_params);
564 let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars);
565 (
566 generic_params.count_params_including_parent(),
567 where_clauses,
568 type_alias.krate(db) != Some(krate),
569 )
570 }
532 }; 571 };
533 let flags = chalk_rust_ir::StructFlags { 572 let flags = chalk_rust_ir::StructFlags {
534 upstream, 573 upstream,