aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src')
-rw-r--r--crates/ra_hir_ty/src/autoderef.rs18
-rw-r--r--crates/ra_hir_ty/src/db.rs47
-rw-r--r--crates/ra_hir_ty/src/diagnostics.rs14
-rw-r--r--crates/ra_hir_ty/src/display.rs12
-rw-r--r--crates/ra_hir_ty/src/expr.rs8
-rw-r--r--crates/ra_hir_ty/src/infer.rs361
-rw-r--r--crates/ra_hir_ty/src/infer/coerce.rs27
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs247
-rw-r--r--crates/ra_hir_ty/src/infer/pat.rs4
-rw-r--r--crates/ra_hir_ty/src/infer/path.rs86
-rw-r--r--crates/ra_hir_ty/src/infer/unify.rs276
-rw-r--r--crates/ra_hir_ty/src/lib.rs96
-rw-r--r--crates/ra_hir_ty/src/lower.rs174
-rw-r--r--crates/ra_hir_ty/src/marks.rs1
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs238
-rw-r--r--crates/ra_hir_ty/src/test_db.rs4
-rw-r--r--crates/ra_hir_ty/src/tests.rs4767
-rw-r--r--crates/ra_hir_ty/src/tests/coercion.rs159
-rw-r--r--crates/ra_hir_ty/src/tests/macros.rs390
-rw-r--r--crates/ra_hir_ty/src/tests/method_resolution.rs1005
-rw-r--r--crates/ra_hir_ty/src/tests/patterns.rs238
-rw-r--r--crates/ra_hir_ty/src/tests/regression.rs333
-rw-r--r--crates/ra_hir_ty/src/tests/simple.rs1663
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs1598
-rw-r--r--crates/ra_hir_ty/src/traits.rs25
-rw-r--r--crates/ra_hir_ty/src/traits/builtin.rs178
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs667
-rw-r--r--crates/ra_hir_ty/src/utils.rs90
28 files changed, 6997 insertions, 5729 deletions
diff --git a/crates/ra_hir_ty/src/autoderef.rs b/crates/ra_hir_ty/src/autoderef.rs
index 9d1d4e48c..f32d5786a 100644
--- a/crates/ra_hir_ty/src/autoderef.rs
+++ b/crates/ra_hir_ty/src/autoderef.rs
@@ -6,14 +6,14 @@
6use std::iter::successors; 6use std::iter::successors;
7 7
8use hir_def::lang_item::LangItemTarget; 8use hir_def::lang_item::LangItemTarget;
9use hir_expand::name; 9use hir_expand::name::name;
10use log::{info, warn}; 10use log::{info, warn};
11use ra_db::CrateId; 11use ra_db::CrateId;
12 12
13use crate::db::HirDatabase; 13use crate::{
14 14 db::HirDatabase,
15use super::{
16 traits::{InEnvironment, Solution}, 15 traits::{InEnvironment, Solution},
16 utils::generics,
17 Canonical, Substs, Ty, TypeWalk, 17 Canonical, Substs, Ty, TypeWalk,
18}; 18};
19 19
@@ -48,14 +48,14 @@ fn deref_by_trait(
48 krate: CrateId, 48 krate: CrateId,
49 ty: InEnvironment<&Canonical<Ty>>, 49 ty: InEnvironment<&Canonical<Ty>>,
50) -> Option<Canonical<Ty>> { 50) -> Option<Canonical<Ty>> {
51 let deref_trait = match db.lang_item(krate.into(), "deref".into())? { 51 let deref_trait = match db.lang_item(krate, "deref".into())? {
52 LangItemTarget::TraitId(it) => it, 52 LangItemTarget::TraitId(it) => it,
53 _ => return None, 53 _ => return None,
54 }; 54 };
55 let target = db.trait_data(deref_trait).associated_type_by_name(&name::TARGET_TYPE)?; 55 let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?;
56 56
57 let generic_params = db.generic_params(target.into()); 57 let generic_params = generics(db, target.into());
58 if generic_params.count_params_including_parent() != 1 { 58 if generic_params.len() != 1 {
59 // the Target type + Deref trait should only have one generic parameter, 59 // the Target type + Deref trait should only have one generic parameter,
60 // namely Deref's Self type 60 // namely Deref's Self type
61 return None; 61 return None;
@@ -78,7 +78,7 @@ fn deref_by_trait(
78 78
79 let canonical = super::Canonical { num_vars: 1 + ty.value.num_vars, value: in_env }; 79 let canonical = super::Canonical { num_vars: 1 + ty.value.num_vars, value: in_env };
80 80
81 let solution = db.trait_solve(krate.into(), canonical)?; 81 let solution = db.trait_solve(krate, canonical)?;
82 82
83 match &solution { 83 match &solution {
84 Solution::Unique(vars) => { 84 Solution::Unique(vars) => {
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs
index 9ce154593..d52f65b83 100644
--- a/crates/ra_hir_ty/src/db.rs
+++ b/crates/ra_hir_ty/src/db.rs
@@ -10,8 +10,8 @@ use ra_db::{salsa, CrateId};
10 10
11use crate::{ 11use crate::{
12 method_resolution::CrateImplBlocks, 12 method_resolution::CrateImplBlocks,
13 traits::{AssocTyValue, Impl}, 13 traits::{chalk, AssocTyValue, Impl},
14 CallableDef, FnSig, GenericPredicate, ImplTy, InferenceResult, Substs, Ty, TyDefId, TypeCtor, 14 CallableDef, FnSig, GenericPredicate, InferenceResult, Substs, TraitRef, Ty, TyDefId, TypeCtor,
15 ValueTyDefId, 15 ValueTyDefId,
16}; 16};
17 17
@@ -22,13 +22,18 @@ pub trait HirDatabase: DefDatabase {
22 fn infer(&self, def: DefWithBodyId) -> Arc<InferenceResult>; 22 fn infer(&self, def: DefWithBodyId) -> Arc<InferenceResult>;
23 23
24 #[salsa::invoke(crate::lower::ty_query)] 24 #[salsa::invoke(crate::lower::ty_query)]
25 #[salsa::cycle(crate::lower::ty_recover)]
25 fn ty(&self, def: TyDefId) -> Ty; 26 fn ty(&self, def: TyDefId) -> Ty;
26 27
27 #[salsa::invoke(crate::lower::value_ty_query)] 28 #[salsa::invoke(crate::lower::value_ty_query)]
28 fn value_ty(&self, def: ValueTyDefId) -> Ty; 29 fn value_ty(&self, def: ValueTyDefId) -> Ty;
29 30
30 #[salsa::invoke(crate::lower::impl_ty_query)] 31 #[salsa::invoke(crate::lower::impl_self_ty_query)]
31 fn impl_ty(&self, def: ImplId) -> ImplTy; 32 #[salsa::cycle(crate::lower::impl_self_ty_recover)]
33 fn impl_self_ty(&self, def: ImplId) -> Ty;
34
35 #[salsa::invoke(crate::lower::impl_trait_query)]
36 fn impl_trait(&self, def: ImplId) -> Option<TraitRef>;
32 37
33 #[salsa::invoke(crate::lower::field_types_query)] 38 #[salsa::invoke(crate::lower::field_types_query)]
34 fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Ty>>; 39 fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Ty>>;
@@ -37,6 +42,7 @@ pub trait HirDatabase: DefDatabase {
37 fn callable_item_signature(&self, def: CallableDef) -> FnSig; 42 fn callable_item_signature(&self, def: CallableDef) -> FnSig;
38 43
39 #[salsa::invoke(crate::lower::generic_predicates_for_param_query)] 44 #[salsa::invoke(crate::lower::generic_predicates_for_param_query)]
45 #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)]
40 fn generic_predicates_for_param( 46 fn generic_predicates_for_param(
41 &self, 47 &self,
42 def: GenericDefId, 48 def: GenericDefId,
@@ -71,39 +77,24 @@ pub trait HirDatabase: DefDatabase {
71 #[salsa::interned] 77 #[salsa::interned]
72 fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> crate::traits::AssocTyValueId; 78 fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> crate::traits::AssocTyValueId;
73 79
74 #[salsa::invoke(crate::traits::chalk::associated_ty_data_query)] 80 #[salsa::invoke(chalk::associated_ty_data_query)]
75 fn associated_ty_data( 81 fn associated_ty_data(&self, id: chalk::AssocTypeId) -> Arc<chalk::AssociatedTyDatum>;
76 &self,
77 id: chalk_ir::TypeId,
78 ) -> Arc<chalk_rust_ir::AssociatedTyDatum<chalk_ir::family::ChalkIr>>;
79 82
80 #[salsa::invoke(crate::traits::chalk::trait_datum_query)] 83 #[salsa::invoke(chalk::trait_datum_query)]
81 fn trait_datum( 84 fn trait_datum(&self, krate: CrateId, trait_id: chalk::TraitId) -> Arc<chalk::TraitDatum>;
82 &self,
83 krate: CrateId,
84 trait_id: chalk_ir::TraitId,
85 ) -> Arc<chalk_rust_ir::TraitDatum<chalk_ir::family::ChalkIr>>;
86 85
87 #[salsa::invoke(crate::traits::chalk::struct_datum_query)] 86 #[salsa::invoke(chalk::struct_datum_query)]
88 fn struct_datum( 87 fn struct_datum(&self, krate: CrateId, struct_id: chalk::StructId) -> Arc<chalk::StructDatum>;
89 &self,
90 krate: CrateId,
91 struct_id: chalk_ir::StructId,
92 ) -> Arc<chalk_rust_ir::StructDatum<chalk_ir::family::ChalkIr>>;
93 88
94 #[salsa::invoke(crate::traits::chalk::impl_datum_query)] 89 #[salsa::invoke(crate::traits::chalk::impl_datum_query)]
95 fn impl_datum( 90 fn impl_datum(&self, krate: CrateId, impl_id: chalk::ImplId) -> Arc<chalk::ImplDatum>;
96 &self,
97 krate: CrateId,
98 impl_id: chalk_ir::ImplId,
99 ) -> Arc<chalk_rust_ir::ImplDatum<chalk_ir::family::ChalkIr>>;
100 91
101 #[salsa::invoke(crate::traits::chalk::associated_ty_value_query)] 92 #[salsa::invoke(crate::traits::chalk::associated_ty_value_query)]
102 fn associated_ty_value( 93 fn associated_ty_value(
103 &self, 94 &self,
104 krate: CrateId, 95 krate: CrateId,
105 id: chalk_rust_ir::AssociatedTyValueId, 96 id: chalk::AssociatedTyValueId,
106 ) -> Arc<chalk_rust_ir::AssociatedTyValue<chalk_ir::family::ChalkIr>>; 97 ) -> Arc<chalk::AssociatedTyValue>;
107 98
108 #[salsa::invoke(crate::traits::trait_solve_query)] 99 #[salsa::invoke(crate::traits::trait_solve_query)]
109 fn trait_solve( 100 fn trait_solve(
diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs
index 4a13fac23..5054189cc 100644
--- a/crates/ra_hir_ty/src/diagnostics.rs
+++ b/crates/ra_hir_ty/src/diagnostics.rs
@@ -2,7 +2,7 @@
2 2
3use std::any::Any; 3use std::any::Any;
4 4
5use hir_expand::{db::AstDatabase, name::Name, HirFileId, Source}; 5use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile};
6use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr}; 6use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr};
7 7
8pub use hir_def::diagnostics::UnresolvedModule; 8pub use hir_def::diagnostics::UnresolvedModule;
@@ -19,8 +19,8 @@ impl Diagnostic for NoSuchField {
19 "no such field".to_string() 19 "no such field".to_string()
20 } 20 }
21 21
22 fn source(&self) -> Source<SyntaxNodePtr> { 22 fn source(&self) -> InFile<SyntaxNodePtr> {
23 Source { file_id: self.file, value: self.field.into() } 23 InFile { file_id: self.file, value: self.field.into() }
24 } 24 }
25 25
26 fn as_any(&self) -> &(dyn Any + Send + 'static) { 26 fn as_any(&self) -> &(dyn Any + Send + 'static) {
@@ -44,8 +44,8 @@ impl Diagnostic for MissingFields {
44 } 44 }
45 message 45 message
46 } 46 }
47 fn source(&self) -> Source<SyntaxNodePtr> { 47 fn source(&self) -> InFile<SyntaxNodePtr> {
48 Source { file_id: self.file, value: self.field_list.into() } 48 InFile { file_id: self.file, value: self.field_list.into() }
49 } 49 }
50 fn as_any(&self) -> &(dyn Any + Send + 'static) { 50 fn as_any(&self) -> &(dyn Any + Send + 'static) {
51 self 51 self
@@ -72,8 +72,8 @@ impl Diagnostic for MissingOkInTailExpr {
72 fn message(&self) -> String { 72 fn message(&self) -> String {
73 "wrap return expression in Ok".to_string() 73 "wrap return expression in Ok".to_string()
74 } 74 }
75 fn source(&self) -> Source<SyntaxNodePtr> { 75 fn source(&self) -> InFile<SyntaxNodePtr> {
76 Source { file_id: self.file, value: self.expr.into() } 76 InFile { file_id: self.file, value: self.expr.into() }
77 } 77 }
78 fn as_any(&self) -> &(dyn Any + Send + 'static) { 78 fn as_any(&self) -> &(dyn Any + Send + 'static) {
79 self 79 self
diff --git a/crates/ra_hir_ty/src/display.rs b/crates/ra_hir_ty/src/display.rs
index 9bb3ece6c..dcca1bace 100644
--- a/crates/ra_hir_ty/src/display.rs
+++ b/crates/ra_hir_ty/src/display.rs
@@ -10,6 +10,7 @@ pub struct HirFormatter<'a, 'b, DB> {
10 buf: String, 10 buf: String,
11 curr_size: usize, 11 curr_size: usize,
12 max_size: Option<usize>, 12 max_size: Option<usize>,
13 should_display_default_types: bool,
13} 14}
14 15
15pub trait HirDisplay { 16pub trait HirDisplay {
@@ -19,7 +20,7 @@ pub trait HirDisplay {
19 where 20 where
20 Self: Sized, 21 Self: Sized,
21 { 22 {
22 HirDisplayWrapper(db, self, None) 23 HirDisplayWrapper(db, self, None, true)
23 } 24 }
24 25
25 fn display_truncated<'a, DB>( 26 fn display_truncated<'a, DB>(
@@ -30,7 +31,7 @@ pub trait HirDisplay {
30 where 31 where
31 Self: Sized, 32 Self: Sized,
32 { 33 {
33 HirDisplayWrapper(db, self, max_size) 34 HirDisplayWrapper(db, self, max_size, false)
34 } 35 }
35} 36}
36 37
@@ -72,9 +73,13 @@ where
72 false 73 false
73 } 74 }
74 } 75 }
76
77 pub fn should_display_default_types(&self) -> bool {
78 self.should_display_default_types
79 }
75} 80}
76 81
77pub struct HirDisplayWrapper<'a, DB, T>(&'a DB, &'a T, Option<usize>); 82pub struct HirDisplayWrapper<'a, DB, T>(&'a DB, &'a T, Option<usize>, bool);
78 83
79impl<'a, DB, T> fmt::Display for HirDisplayWrapper<'a, DB, T> 84impl<'a, DB, T> fmt::Display for HirDisplayWrapper<'a, DB, T>
80where 85where
@@ -88,6 +93,7 @@ where
88 buf: String::with_capacity(20), 93 buf: String::with_capacity(20),
89 curr_size: 0, 94 curr_size: 0,
90 max_size: self.2, 95 max_size: self.2,
96 should_display_default_types: self.3,
91 }) 97 })
92 } 98 }
93} 99}
diff --git a/crates/ra_hir_ty/src/expr.rs b/crates/ra_hir_ty/src/expr.rs
index 5c65f9370..f752a9f09 100644
--- a/crates/ra_hir_ty/src/expr.rs
+++ b/crates/ra_hir_ty/src/expr.rs
@@ -3,7 +3,7 @@
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::{ 5use hir_def::{
6 path::{known, Path}, 6 path::{path, Path},
7 resolver::HasResolver, 7 resolver::HasResolver,
8 AdtId, FunctionId, 8 AdtId, FunctionId,
9}; 9};
@@ -97,7 +97,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
97 let (_, source_map) = db.body_with_source_map(self.func.into()); 97 let (_, source_map) = db.body_with_source_map(self.func.into());
98 98
99 if let Some(source_ptr) = source_map.expr_syntax(id) { 99 if let Some(source_ptr) = source_map.expr_syntax(id) {
100 if let Some(expr) = source_ptr.value.a() { 100 if let Some(expr) = source_ptr.value.left() {
101 let root = source_ptr.file_syntax(db); 101 let root = source_ptr.file_syntax(db);
102 if let ast::Expr::RecordLit(record_lit) = expr.to_node(&root) { 102 if let ast::Expr::RecordLit(record_lit) = expr.to_node(&root) {
103 if let Some(field_list) = record_lit.record_field_list() { 103 if let Some(field_list) = record_lit.record_field_list() {
@@ -124,7 +124,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
124 None => return, 124 None => return,
125 }; 125 };
126 126
127 let std_result_path = known::std_result_result(); 127 let std_result_path = path![std::result::Result];
128 128
129 let resolver = self.func.resolver(db); 129 let resolver = self.func.resolver(db);
130 let std_result_enum = match resolver.resolve_known_enum(db, &std_result_path) { 130 let std_result_enum = match resolver.resolve_known_enum(db, &std_result_path) {
@@ -142,7 +142,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
142 let (_, source_map) = db.body_with_source_map(self.func.into()); 142 let (_, source_map) = db.body_with_source_map(self.func.into());
143 143
144 if let Some(source_ptr) = source_map.expr_syntax(id) { 144 if let Some(source_ptr) = source_map.expr_syntax(id) {
145 if let Some(expr) = source_ptr.value.a() { 145 if let Some(expr) = source_ptr.value.left() {
146 self.sink.push(MissingOkInTailExpr { file: source_ptr.file_id, expr }); 146 self.sink.push(MissingOkInTailExpr { file: source_ptr.file_id, expr });
147 } 147 }
148 } 148 }
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
index 1e9f4b208..e97b81473 100644
--- a/crates/ra_hir_ty/src/infer.rs
+++ b/crates/ra_hir_ty/src/infer.rs
@@ -18,19 +18,18 @@ use std::mem;
18use std::ops::Index; 18use std::ops::Index;
19use std::sync::Arc; 19use std::sync::Arc;
20 20
21use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
22use rustc_hash::FxHashMap; 21use rustc_hash::FxHashMap;
23 22
24use hir_def::{ 23use hir_def::{
25 body::Body, 24 body::Body,
26 data::{ConstData, FunctionData}, 25 data::{ConstData, FunctionData},
27 expr::{BindingAnnotation, ExprId, PatId}, 26 expr::{BindingAnnotation, ExprId, PatId},
28 path::{known, Path}, 27 path::{path, Path},
29 resolver::{HasResolver, Resolver, TypeNs}, 28 resolver::{HasResolver, Resolver, TypeNs},
30 type_ref::{Mutability, TypeRef}, 29 type_ref::{Mutability, TypeRef},
31 AdtId, AssocItemId, DefWithBodyId, FunctionId, StructFieldId, TypeAliasId, VariantId, 30 AdtId, AssocItemId, DefWithBodyId, FunctionId, StructFieldId, TypeAliasId, VariantId,
32}; 31};
33use hir_expand::{diagnostics::DiagnosticSink, name}; 32use hir_expand::{diagnostics::DiagnosticSink, name::name};
34use ra_arena::map::ArenaMap; 33use ra_arena::map::ArenaMap;
35use ra_prof::profile; 34use ra_prof::profile;
36use test_utils::tested_by; 35use test_utils::tested_by;
@@ -43,6 +42,8 @@ use super::{
43}; 42};
44use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic}; 43use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic};
45 44
45pub(crate) use unify::unify;
46
46macro_rules! ty_app { 47macro_rules! ty_app {
47 ($ctor:pat, $param:pat) => { 48 ($ctor:pat, $param:pat) => {
48 crate::Ty::Apply(crate::ApplicationTy { ctor: $ctor, parameters: $param }) 49 crate::Ty::Apply(crate::ApplicationTy { ctor: $ctor, parameters: $param })
@@ -191,11 +192,16 @@ struct InferenceContext<'a, D: HirDatabase> {
191 owner: DefWithBodyId, 192 owner: DefWithBodyId,
192 body: Arc<Body>, 193 body: Arc<Body>,
193 resolver: Resolver, 194 resolver: Resolver,
194 var_unification_table: InPlaceUnificationTable<TypeVarId>, 195 table: unify::InferenceTable,
195 trait_env: Arc<TraitEnvironment>, 196 trait_env: Arc<TraitEnvironment>,
196 obligations: Vec<Obligation>, 197 obligations: Vec<Obligation>,
197 result: InferenceResult, 198 result: InferenceResult,
198 /// The return type of the function being inferred. 199 /// The return type of the function being inferred, or the closure if we're
200 /// currently within one.
201 ///
202 /// We might consider using a nested inference context for checking
203 /// closures, but currently this is the only field that will change there,
204 /// so it doesn't make sense.
199 return_ty: Ty, 205 return_ty: Ty,
200 206
201 /// Impls of `CoerceUnsized` used in coercion. 207 /// Impls of `CoerceUnsized` used in coercion.
@@ -209,7 +215,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
209 fn new(db: &'a D, owner: DefWithBodyId, resolver: Resolver) -> Self { 215 fn new(db: &'a D, owner: DefWithBodyId, resolver: Resolver) -> Self {
210 InferenceContext { 216 InferenceContext {
211 result: InferenceResult::default(), 217 result: InferenceResult::default(),
212 var_unification_table: InPlaceUnificationTable::new(), 218 table: unify::InferenceTable::new(),
213 obligations: Vec::default(), 219 obligations: Vec::default(),
214 return_ty: Ty::Unknown, // set in collect_fn_signature 220 return_ty: Ty::Unknown, // set in collect_fn_signature
215 trait_env: TraitEnvironment::lower(db, &resolver), 221 trait_env: TraitEnvironment::lower(db, &resolver),
@@ -224,13 +230,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
224 fn resolve_all(mut self) -> InferenceResult { 230 fn resolve_all(mut self) -> InferenceResult {
225 // FIXME resolve obligations as well (use Guidance if necessary) 231 // FIXME resolve obligations as well (use Guidance if necessary)
226 let mut result = mem::replace(&mut self.result, InferenceResult::default()); 232 let mut result = mem::replace(&mut self.result, InferenceResult::default());
227 let mut tv_stack = Vec::new();
228 for ty in result.type_of_expr.values_mut() { 233 for ty in result.type_of_expr.values_mut() {
229 let resolved = self.resolve_ty_completely(&mut tv_stack, mem::replace(ty, Ty::Unknown)); 234 let resolved = self.table.resolve_ty_completely(mem::replace(ty, Ty::Unknown));
230 *ty = resolved; 235 *ty = resolved;
231 } 236 }
232 for ty in result.type_of_pat.values_mut() { 237 for ty in result.type_of_pat.values_mut() {
233 let resolved = self.resolve_ty_completely(&mut tv_stack, mem::replace(ty, Ty::Unknown)); 238 let resolved = self.table.resolve_ty_completely(mem::replace(ty, Ty::Unknown));
234 *ty = resolved; 239 *ty = resolved;
235 } 240 }
236 result 241 result
@@ -275,96 +280,38 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
275 self.normalize_associated_types_in(ty) 280 self.normalize_associated_types_in(ty)
276 } 281 }
277 282
278 fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs, depth: usize) -> bool { 283 /// Replaces `impl Trait` in `ty` by type variables and obligations for
279 substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth)) 284 /// those variables. This is done for function arguments when calling a
280 } 285 /// function, and for return types when inside the function body, i.e. in
281 286 /// the cases where the `impl Trait` is 'transparent'. In other cases, `impl
282 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { 287 /// Trait` is represented by `Ty::Opaque`.
283 self.unify_inner(ty1, ty2, 0) 288 fn insert_vars_for_impl_trait(&mut self, ty: Ty) -> Ty {
284 } 289 ty.fold(&mut |ty| match ty {
285 290 Ty::Opaque(preds) => {
286 fn unify_inner(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool { 291 tested_by!(insert_vars_for_impl_trait);
287 if depth > 1000 { 292 let var = self.table.new_type_var();
288 // prevent stackoverflows 293 let var_subst = Substs::builder(1).push(var.clone()).build();
289 panic!("infinite recursion in unification"); 294 self.obligations.extend(
290 } 295 preds
291 if ty1 == ty2 { 296 .iter()
292 return true; 297 .map(|pred| pred.clone().subst_bound_vars(&var_subst))
293 } 298 .filter_map(Obligation::from_predicate),
294 // try to resolve type vars first 299 );
295 let ty1 = self.resolve_ty_shallow(ty1); 300 var
296 let ty2 = self.resolve_ty_shallow(ty2);
297 match (&*ty1, &*ty2) {
298 (Ty::Apply(a_ty1), Ty::Apply(a_ty2)) if a_ty1.ctor == a_ty2.ctor => {
299 self.unify_substs(&a_ty1.parameters, &a_ty2.parameters, depth + 1)
300 }
301 _ => self.unify_inner_trivial(&ty1, &ty2),
302 }
303 }
304
305 fn unify_inner_trivial(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
306 match (ty1, ty2) {
307 (Ty::Unknown, _) | (_, Ty::Unknown) => true,
308
309 (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2)))
310 | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2)))
311 | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2)))
312 | (
313 Ty::Infer(InferTy::MaybeNeverTypeVar(tv1)),
314 Ty::Infer(InferTy::MaybeNeverTypeVar(tv2)),
315 ) => {
316 // both type vars are unknown since we tried to resolve them
317 self.var_unification_table.union(*tv1, *tv2);
318 true
319 }
320
321 // The order of MaybeNeverTypeVar matters here.
322 // Unifying MaybeNeverTypeVar and TypeVar will let the latter become MaybeNeverTypeVar.
323 // Unifying MaybeNeverTypeVar and other concrete type will let the former become it.
324 (Ty::Infer(InferTy::TypeVar(tv)), other)
325 | (other, Ty::Infer(InferTy::TypeVar(tv)))
326 | (Ty::Infer(InferTy::MaybeNeverTypeVar(tv)), other)
327 | (other, Ty::Infer(InferTy::MaybeNeverTypeVar(tv)))
328 | (Ty::Infer(InferTy::IntVar(tv)), other @ ty_app!(TypeCtor::Int(_)))
329 | (other @ ty_app!(TypeCtor::Int(_)), Ty::Infer(InferTy::IntVar(tv)))
330 | (Ty::Infer(InferTy::FloatVar(tv)), other @ ty_app!(TypeCtor::Float(_)))
331 | (other @ ty_app!(TypeCtor::Float(_)), Ty::Infer(InferTy::FloatVar(tv))) => {
332 // the type var is unknown since we tried to resolve it
333 self.var_unification_table.union_value(*tv, TypeVarValue::Known(other.clone()));
334 true
335 } 301 }
336 302 _ => ty,
337 _ => false, 303 })
338 }
339 }
340
341 fn new_type_var(&mut self) -> Ty {
342 Ty::Infer(InferTy::TypeVar(self.var_unification_table.new_key(TypeVarValue::Unknown)))
343 }
344
345 fn new_integer_var(&mut self) -> Ty {
346 Ty::Infer(InferTy::IntVar(self.var_unification_table.new_key(TypeVarValue::Unknown)))
347 }
348
349 fn new_float_var(&mut self) -> Ty {
350 Ty::Infer(InferTy::FloatVar(self.var_unification_table.new_key(TypeVarValue::Unknown)))
351 }
352
353 fn new_maybe_never_type_var(&mut self) -> Ty {
354 Ty::Infer(InferTy::MaybeNeverTypeVar(
355 self.var_unification_table.new_key(TypeVarValue::Unknown),
356 ))
357 } 304 }
358 305
359 /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. 306 /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it.
360 fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { 307 fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
361 match ty { 308 match ty {
362 Ty::Unknown => self.new_type_var(), 309 Ty::Unknown => self.table.new_type_var(),
363 Ty::Apply(ApplicationTy { ctor: TypeCtor::Int(Uncertain::Unknown), .. }) => { 310 Ty::Apply(ApplicationTy { ctor: TypeCtor::Int(Uncertain::Unknown), .. }) => {
364 self.new_integer_var() 311 self.table.new_integer_var()
365 } 312 }
366 Ty::Apply(ApplicationTy { ctor: TypeCtor::Float(Uncertain::Unknown), .. }) => { 313 Ty::Apply(ApplicationTy { ctor: TypeCtor::Float(Uncertain::Unknown), .. }) => {
367 self.new_float_var() 314 self.table.new_float_var()
368 } 315 }
369 _ => ty, 316 _ => ty,
370 } 317 }
@@ -402,64 +349,52 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
402 } 349 }
403 } 350 }
404 351
352 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
353 self.table.unify(ty1, ty2)
354 }
355
405 /// Resolves the type as far as currently possible, replacing type variables 356 /// Resolves the type as far as currently possible, replacing type variables
406 /// by their known types. All types returned by the infer_* functions should 357 /// by their known types. All types returned by the infer_* functions should
407 /// be resolved as far as possible, i.e. contain no type variables with 358 /// be resolved as far as possible, i.e. contain no type variables with
408 /// known type. 359 /// known type.
409 fn resolve_ty_as_possible(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { 360 fn resolve_ty_as_possible(&mut self, ty: Ty) -> Ty {
410 self.resolve_obligations_as_possible(); 361 self.resolve_obligations_as_possible();
411 362
412 ty.fold(&mut |ty| match ty { 363 self.table.resolve_ty_as_possible(ty)
413 Ty::Infer(tv) => {
414 let inner = tv.to_inner();
415 if tv_stack.contains(&inner) {
416 tested_by!(type_var_cycles_resolve_as_possible);
417 // recursive type
418 return tv.fallback_value();
419 }
420 if let Some(known_ty) =
421 self.var_unification_table.inlined_probe_value(inner).known()
422 {
423 // known_ty may contain other variables that are known by now
424 tv_stack.push(inner);
425 let result = self.resolve_ty_as_possible(tv_stack, known_ty.clone());
426 tv_stack.pop();
427 result
428 } else {
429 ty
430 }
431 }
432 _ => ty,
433 })
434 } 364 }
435 365
436 /// If `ty` is a type variable with known type, returns that type;
437 /// otherwise, return ty.
438 fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> { 366 fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> {
439 let mut ty = Cow::Borrowed(ty); 367 self.table.resolve_ty_shallow(ty)
440 // The type variable could resolve to a int/float variable. Hence try 368 }
441 // resolving up to three times; each type of variable shouldn't occur 369
442 // more than once 370 fn resolve_associated_type(&mut self, inner_ty: Ty, assoc_ty: Option<TypeAliasId>) -> Ty {
443 for i in 0..3 { 371 self.resolve_associated_type_with_params(inner_ty, assoc_ty, &[])
444 if i > 0 { 372 }
445 tested_by!(type_var_resolves_to_int_var); 373
446 } 374 fn resolve_associated_type_with_params(
447 match &*ty { 375 &mut self,
448 Ty::Infer(tv) => { 376 inner_ty: Ty,
449 let inner = tv.to_inner(); 377 assoc_ty: Option<TypeAliasId>,
450 match self.var_unification_table.inlined_probe_value(inner).known() { 378 params: &[Ty],
451 Some(known_ty) => { 379 ) -> Ty {
452 // The known_ty can't be a type var itself 380 match assoc_ty {
453 ty = Cow::Owned(known_ty.clone()); 381 Some(res_assoc_ty) => {
454 } 382 let ty = self.table.new_type_var();
455 _ => return ty, 383 let builder = Substs::build_for_def(self.db, res_assoc_ty)
456 } 384 .push(inner_ty)
457 } 385 .fill(params.iter().cloned());
458 _ => return ty, 386 let projection = ProjectionPredicate {
387 ty: ty.clone(),
388 projection_ty: ProjectionTy {
389 associated_ty: res_assoc_ty,
390 parameters: builder.build(),
391 },
392 };
393 self.obligations.push(Obligation::Projection(projection));
394 self.resolve_ty_as_possible(ty)
459 } 395 }
396 None => Ty::Unknown,
460 } 397 }
461 log::error!("Inference variable still not resolved: {:?}", ty);
462 ty
463 } 398 }
464 399
465 /// Recurses through the given type, normalizing associated types mentioned 400 /// Recurses through the given type, normalizing associated types mentioned
@@ -469,7 +404,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
469 /// call). `make_ty` handles this already, but e.g. for field types we need 404 /// call). `make_ty` handles this already, but e.g. for field types we need
470 /// to do it as well. 405 /// to do it as well.
471 fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { 406 fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty {
472 let ty = self.resolve_ty_as_possible(&mut vec![], ty); 407 let ty = self.resolve_ty_as_possible(ty);
473 ty.fold(&mut |ty| match ty { 408 ty.fold(&mut |ty| match ty {
474 Ty::Projection(proj_ty) => self.normalize_projection_ty(proj_ty), 409 Ty::Projection(proj_ty) => self.normalize_projection_ty(proj_ty),
475 _ => ty, 410 _ => ty,
@@ -477,40 +412,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
477 } 412 }
478 413
479 fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { 414 fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
480 let var = self.new_type_var(); 415 let var = self.table.new_type_var();
481 let predicate = ProjectionPredicate { projection_ty: proj_ty, ty: var.clone() }; 416 let predicate = ProjectionPredicate { projection_ty: proj_ty, ty: var.clone() };
482 let obligation = Obligation::Projection(predicate); 417 let obligation = Obligation::Projection(predicate);
483 self.obligations.push(obligation); 418 self.obligations.push(obligation);
484 var 419 var
485 } 420 }
486 421
487 /// Resolves the type completely; type variables without known type are
488 /// replaced by Ty::Unknown.
489 fn resolve_ty_completely(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
490 ty.fold(&mut |ty| match ty {
491 Ty::Infer(tv) => {
492 let inner = tv.to_inner();
493 if tv_stack.contains(&inner) {
494 tested_by!(type_var_cycles_resolve_completely);
495 // recursive type
496 return tv.fallback_value();
497 }
498 if let Some(known_ty) =
499 self.var_unification_table.inlined_probe_value(inner).known()
500 {
501 // known_ty may contain other variables that are known by now
502 tv_stack.push(inner);
503 let result = self.resolve_ty_completely(tv_stack, known_ty.clone());
504 tv_stack.pop();
505 result
506 } else {
507 tv.fallback_value()
508 }
509 }
510 _ => ty,
511 })
512 }
513
514 fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantId>) { 422 fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantId>) {
515 let path = match path { 423 let path = match path {
516 Some(path) => path, 424 Some(path) => path,
@@ -519,7 +427,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
519 let resolver = &self.resolver; 427 let resolver = &self.resolver;
520 // FIXME: this should resolve assoc items as well, see this example: 428 // FIXME: this should resolve assoc items as well, see this example:
521 // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521 429 // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521
522 match resolver.resolve_path_in_type_ns_fully(self.db, &path) { 430 match resolver.resolve_path_in_type_ns_fully(self.db, path.mod_path()) {
523 Some(TypeNs::AdtId(AdtId::StructId(strukt))) => { 431 Some(TypeNs::AdtId(AdtId::StructId(strukt))) => {
524 let substs = Ty::substs_from_path(self.db, resolver, path, strukt.into()); 432 let substs = Ty::substs_from_path(self.db, resolver, path, strukt.into());
525 let ty = self.db.ty(strukt.into()); 433 let ty = self.db.ty(strukt.into());
@@ -547,93 +455,90 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
547 455
548 self.infer_pat(*pat, &ty, BindingMode::default()); 456 self.infer_pat(*pat, &ty, BindingMode::default());
549 } 457 }
550 self.return_ty = self.make_ty(&data.ret_type); 458 let return_ty = self.make_ty(&data.ret_type);
459 self.return_ty = self.insert_vars_for_impl_trait(return_ty);
551 } 460 }
552 461
553 fn infer_body(&mut self) { 462 fn infer_body(&mut self) {
554 self.infer_expr(self.body.body_expr, &Expectation::has_type(self.return_ty.clone())); 463 self.infer_expr_coerce(self.body.body_expr, &Expectation::has_type(self.return_ty.clone()));
555 } 464 }
556 465
557 fn resolve_into_iter_item(&self) -> Option<TypeAliasId> { 466 fn resolve_into_iter_item(&self) -> Option<TypeAliasId> {
558 let path = known::std_iter_into_iterator(); 467 let path = path![std::iter::IntoIterator];
559 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; 468 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
560 self.db.trait_data(trait_).associated_type_by_name(&name::ITEM_TYPE) 469 self.db.trait_data(trait_).associated_type_by_name(&name![Item])
561 } 470 }
562 471
563 fn resolve_ops_try_ok(&self) -> Option<TypeAliasId> { 472 fn resolve_ops_try_ok(&self) -> Option<TypeAliasId> {
564 let path = known::std_ops_try(); 473 let path = path![std::ops::Try];
474 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
475 self.db.trait_data(trait_).associated_type_by_name(&name![Ok])
476 }
477
478 fn resolve_ops_neg_output(&self) -> Option<TypeAliasId> {
479 let path = path![std::ops::Neg];
480 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
481 self.db.trait_data(trait_).associated_type_by_name(&name![Output])
482 }
483
484 fn resolve_ops_not_output(&self) -> Option<TypeAliasId> {
485 let path = path![std::ops::Not];
565 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; 486 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
566 self.db.trait_data(trait_).associated_type_by_name(&name::OK_TYPE) 487 self.db.trait_data(trait_).associated_type_by_name(&name![Output])
567 } 488 }
568 489
569 fn resolve_future_future_output(&self) -> Option<TypeAliasId> { 490 fn resolve_future_future_output(&self) -> Option<TypeAliasId> {
570 let path = known::std_future_future(); 491 let path = path![std::future::Future];
571 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; 492 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
572 self.db.trait_data(trait_).associated_type_by_name(&name::OUTPUT_TYPE) 493 self.db.trait_data(trait_).associated_type_by_name(&name![Output])
573 } 494 }
574 495
575 fn resolve_boxed_box(&self) -> Option<AdtId> { 496 fn resolve_boxed_box(&self) -> Option<AdtId> {
576 let path = known::std_boxed_box(); 497 let path = path![std::boxed::Box];
577 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; 498 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
578 Some(struct_.into()) 499 Some(struct_.into())
579 } 500 }
580}
581
582/// The ID of a type variable.
583#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
584pub struct TypeVarId(pub(super) u32);
585
586impl UnifyKey for TypeVarId {
587 type Value = TypeVarValue;
588 501
589 fn index(&self) -> u32 { 502 fn resolve_range_full(&self) -> Option<AdtId> {
590 self.0 503 let path = path![std::ops::RangeFull];
504 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
505 Some(struct_.into())
591 } 506 }
592 507
593 fn from_index(i: u32) -> Self { 508 fn resolve_range(&self) -> Option<AdtId> {
594 TypeVarId(i) 509 let path = path![std::ops::Range];
510 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
511 Some(struct_.into())
595 } 512 }
596 513
597 fn tag() -> &'static str { 514 fn resolve_range_inclusive(&self) -> Option<AdtId> {
598 "TypeVarId" 515 let path = path![std::ops::RangeInclusive];
516 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
517 Some(struct_.into())
599 } 518 }
600}
601
602/// The value of a type variable: either we already know the type, or we don't
603/// know it yet.
604#[derive(Clone, PartialEq, Eq, Debug)]
605pub enum TypeVarValue {
606 Known(Ty),
607 Unknown,
608}
609 519
610impl TypeVarValue { 520 fn resolve_range_from(&self) -> Option<AdtId> {
611 fn known(&self) -> Option<&Ty> { 521 let path = path![std::ops::RangeFrom];
612 match self { 522 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
613 TypeVarValue::Known(ty) => Some(ty), 523 Some(struct_.into())
614 TypeVarValue::Unknown => None,
615 }
616 } 524 }
617}
618 525
619impl UnifyValue for TypeVarValue { 526 fn resolve_range_to(&self) -> Option<AdtId> {
620 type Error = NoError; 527 let path = path![std::ops::RangeTo];
621 528 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
622 fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> { 529 Some(struct_.into())
623 match (value1, value2) { 530 }
624 // We should never equate two type variables, both of which have
625 // known types. Instead, we recursively equate those types.
626 (TypeVarValue::Known(t1), TypeVarValue::Known(t2)) => panic!(
627 "equating two type variables, both of which have known types: {:?} and {:?}",
628 t1, t2
629 ),
630 531
631 // If one side is known, prefer that one. 532 fn resolve_range_to_inclusive(&self) -> Option<AdtId> {
632 (TypeVarValue::Known(..), TypeVarValue::Unknown) => Ok(value1.clone()), 533 let path = path![std::ops::RangeToInclusive];
633 (TypeVarValue::Unknown, TypeVarValue::Known(..)) => Ok(value2.clone()), 534 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
535 Some(struct_.into())
536 }
634 537
635 (TypeVarValue::Unknown, TypeVarValue::Unknown) => Ok(TypeVarValue::Unknown), 538 fn resolve_ops_index_output(&self) -> Option<TypeAliasId> {
636 } 539 let path = path![std::ops::Index];
540 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
541 self.db.trait_data(trait_).associated_type_by_name(&name![Output])
637 } 542 }
638} 543}
639 544
@@ -643,14 +548,14 @@ impl UnifyValue for TypeVarValue {
643/// several integer types). 548/// several integer types).
644#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] 549#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
645pub enum InferTy { 550pub enum InferTy {
646 TypeVar(TypeVarId), 551 TypeVar(unify::TypeVarId),
647 IntVar(TypeVarId), 552 IntVar(unify::TypeVarId),
648 FloatVar(TypeVarId), 553 FloatVar(unify::TypeVarId),
649 MaybeNeverTypeVar(TypeVarId), 554 MaybeNeverTypeVar(unify::TypeVarId),
650} 555}
651 556
652impl InferTy { 557impl InferTy {
653 fn to_inner(self) -> TypeVarId { 558 fn to_inner(self) -> unify::TypeVarId {
654 match self { 559 match self {
655 InferTy::TypeVar(ty) 560 InferTy::TypeVar(ty)
656 | InferTy::IntVar(ty) 561 | InferTy::IntVar(ty)
@@ -693,7 +598,7 @@ impl Expectation {
693} 598}
694 599
695mod diagnostics { 600mod diagnostics {
696 use hir_def::{expr::ExprId, FunctionId, HasSource, Lookup}; 601 use hir_def::{expr::ExprId, src::HasSource, FunctionId, Lookup};
697 use hir_expand::diagnostics::DiagnosticSink; 602 use hir_expand::diagnostics::DiagnosticSink;
698 603
699 use crate::{db::HirDatabase, diagnostics::NoSuchField}; 604 use crate::{db::HirDatabase, diagnostics::NoSuchField};
diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs
index 719a0f395..83c0c2c3f 100644
--- a/crates/ra_hir_ty/src/infer/coerce.rs
+++ b/crates/ra_hir_ty/src/infer/coerce.rs
@@ -8,9 +8,9 @@ use hir_def::{lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutabilit
8use rustc_hash::FxHashMap; 8use rustc_hash::FxHashMap;
9use test_utils::tested_by; 9use test_utils::tested_by;
10 10
11use crate::{autoderef, db::HirDatabase, ImplTy, Substs, Ty, TypeCtor, TypeWalk}; 11use crate::{autoderef, db::HirDatabase, Substs, Ty, TypeCtor, TypeWalk};
12 12
13use super::{InEnvironment, InferTy, InferenceContext, TypeVarValue}; 13use super::{unify::TypeVarValue, InEnvironment, InferTy, InferenceContext};
14 14
15impl<'a, D: HirDatabase> InferenceContext<'a, D> { 15impl<'a, D: HirDatabase> InferenceContext<'a, D> {
16 /// Unify two types, but may coerce the first one to the second one 16 /// Unify two types, but may coerce the first one to the second one
@@ -54,10 +54,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
54 impls 54 impls
55 .iter() 55 .iter()
56 .filter_map(|&impl_id| { 56 .filter_map(|&impl_id| {
57 let trait_ref = match db.impl_ty(impl_id) { 57 let trait_ref = db.impl_trait(impl_id)?;
58 ImplTy::TraitRef(it) => it,
59 ImplTy::Inherent(_) => return None,
60 };
61 58
62 // `CoerseUnsized` has one generic parameter for the target type. 59 // `CoerseUnsized` has one generic parameter for the target type.
63 let cur_from_ty = trait_ref.substs.0.get(0)?; 60 let cur_from_ty = trait_ref.substs.0.get(0)?;
@@ -88,8 +85,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
88 match (&from_ty, to_ty) { 85 match (&from_ty, to_ty) {
89 // Never type will make type variable to fallback to Never Type instead of Unknown. 86 // Never type will make type variable to fallback to Never Type instead of Unknown.
90 (ty_app!(TypeCtor::Never), Ty::Infer(InferTy::TypeVar(tv))) => { 87 (ty_app!(TypeCtor::Never), Ty::Infer(InferTy::TypeVar(tv))) => {
91 let var = self.new_maybe_never_type_var(); 88 let var = self.table.new_maybe_never_type_var();
92 self.var_unification_table.union_value(*tv, TypeVarValue::Known(var)); 89 self.table.var_unification_table.union_value(*tv, TypeVarValue::Known(var));
93 return true; 90 return true;
94 } 91 }
95 (ty_app!(TypeCtor::Never), _) => return true, 92 (ty_app!(TypeCtor::Never), _) => return true,
@@ -97,7 +94,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
97 // Trivial cases, this should go after `never` check to 94 // Trivial cases, this should go after `never` check to
98 // avoid infer result type to be never 95 // avoid infer result type to be never
99 _ => { 96 _ => {
100 if self.unify_inner_trivial(&from_ty, &to_ty) { 97 if self.table.unify_inner_trivial(&from_ty, &to_ty) {
101 return true; 98 return true;
102 } 99 }
103 } 100 }
@@ -137,6 +134,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
137 } 134 }
138 } 135 }
139 136
137 (ty_app!(TypeCtor::Closure { .. }, params), ty_app!(TypeCtor::FnPtr { .. })) => {
138 from_ty = params[0].clone();
139 }
140
140 _ => {} 141 _ => {}
141 } 142 }
142 143
@@ -333,9 +334,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
333 // Stop when constructor matches. 334 // Stop when constructor matches.
334 (ty_app!(from_ctor, st1), ty_app!(to_ctor, st2)) if from_ctor == to_ctor => { 335 (ty_app!(from_ctor, st1), ty_app!(to_ctor, st2)) if from_ctor == to_ctor => {
335 // It will not recurse to `coerce`. 336 // It will not recurse to `coerce`.
336 return self.unify_substs(st1, st2, 0); 337 return self.table.unify_substs(st1, st2, 0);
338 }
339 _ => {
340 if self.table.unify_inner_trivial(&derefed_ty, &to_ty) {
341 return true;
342 }
337 } 343 }
338 _ => {}
339 } 344 }
340 } 345 }
341 346
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index 2f9ca4bbb..3af05394c 100644
--- a/crates/ra_hir_ty/src/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -6,17 +6,21 @@ use std::sync::Arc;
6use hir_def::{ 6use hir_def::{
7 builtin_type::Signedness, 7 builtin_type::Signedness,
8 expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, 8 expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
9 generics::GenericParams,
10 path::{GenericArg, GenericArgs}, 9 path::{GenericArg, GenericArgs},
11 resolver::resolver_for_expr, 10 resolver::resolver_for_expr,
12 AdtId, ContainerId, Lookup, StructFieldId, 11 AdtId, AssocContainerId, Lookup, StructFieldId,
13}; 12};
14use hir_expand::name::{self, Name}; 13use hir_expand::name::{name, Name};
14use ra_syntax::ast::RangeOp;
15 15
16use crate::{ 16use crate::{
17 autoderef, db::HirDatabase, method_resolution, op, traits::InEnvironment, utils::variant_data, 17 autoderef,
18 CallableDef, InferTy, IntTy, Mutability, Obligation, ProjectionPredicate, ProjectionTy, Substs, 18 db::HirDatabase,
19 TraitRef, Ty, TypeCtor, TypeWalk, Uncertain, 19 method_resolution, op,
20 traits::InEnvironment,
21 utils::{generics, variant_data, Generics},
22 ApplicationTy, CallableDef, InferTy, IntTy, Mutability, Obligation, Substs, TraitRef, Ty,
23 TypeCtor, TypeWalk, Uncertain,
20}; 24};
21 25
22use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; 26use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch};
@@ -31,13 +35,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
31 TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() }, 35 TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() },
32 ); 36 );
33 } 37 }
34 let ty = self.resolve_ty_as_possible(&mut vec![], ty); 38 let ty = self.resolve_ty_as_possible(ty);
35 ty 39 ty
36 } 40 }
37 41
38 /// Infer type of expression with possibly implicit coerce to the expected type. 42 /// Infer type of expression with possibly implicit coerce to the expected type.
39 /// Return the type after possible coercion. 43 /// Return the type after possible coercion.
40 fn infer_expr_coerce(&mut self, expr: ExprId, expected: &Expectation) -> Ty { 44 pub(super) fn infer_expr_coerce(&mut self, expr: ExprId, expected: &Expectation) -> Ty {
41 let ty = self.infer_expr_inner(expr, &expected); 45 let ty = self.infer_expr_inner(expr, &expected);
42 let ty = if !self.coerce(&ty, &expected.ty) { 46 let ty = if !self.coerce(&ty, &expected.ty) {
43 self.result 47 self.result
@@ -52,7 +56,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
52 expected.ty.clone() 56 expected.ty.clone()
53 }; 57 };
54 58
55 self.resolve_ty_as_possible(&mut vec![], ty) 59 self.resolve_ty_as_possible(ty)
56 } 60 }
57 61
58 fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { 62 fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
@@ -91,27 +95,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
91 Expr::For { iterable, body, pat } => { 95 Expr::For { iterable, body, pat } => {
92 let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); 96 let iterable_ty = self.infer_expr(*iterable, &Expectation::none());
93 97
94 let pat_ty = match self.resolve_into_iter_item() { 98 let pat_ty =
95 Some(into_iter_item_alias) => { 99 self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item());
96 let pat_ty = self.new_type_var();
97 let projection = ProjectionPredicate {
98 ty: pat_ty.clone(),
99 projection_ty: ProjectionTy {
100 associated_ty: into_iter_item_alias,
101 parameters: Substs::single(iterable_ty),
102 },
103 };
104 self.obligations.push(Obligation::Projection(projection));
105 self.resolve_ty_as_possible(&mut vec![], pat_ty)
106 }
107 None => Ty::Unknown,
108 };
109 100
110 self.infer_pat(*pat, &pat_ty, BindingMode::default()); 101 self.infer_pat(*pat, &pat_ty, BindingMode::default());
111 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 102 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
112 Ty::unit() 103 Ty::unit()
113 } 104 }
114 Expr::Lambda { body, args, arg_types } => { 105 Expr::Lambda { body, args, ret_type, arg_types } => {
115 assert_eq!(args.len(), arg_types.len()); 106 assert_eq!(args.len(), arg_types.len());
116 107
117 let mut sig_tys = Vec::new(); 108 let mut sig_tys = Vec::new();
@@ -127,7 +118,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
127 } 118 }
128 119
129 // add return type 120 // add return type
130 let ret_ty = self.new_type_var(); 121 let ret_ty = match ret_type {
122 Some(type_ref) => self.make_ty(type_ref),
123 None => self.table.new_type_var(),
124 };
131 sig_tys.push(ret_ty.clone()); 125 sig_tys.push(ret_ty.clone());
132 let sig_ty = Ty::apply( 126 let sig_ty = Ty::apply(
133 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, 127 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 },
@@ -143,7 +137,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
143 // infer the body. 137 // infer the body.
144 self.coerce(&closure_ty, &expected.ty); 138 self.coerce(&closure_ty, &expected.ty);
145 139
146 self.infer_expr(*body, &Expectation::has_type(ret_ty)); 140 let prev_ret_ty = std::mem::replace(&mut self.return_ty, ret_ty.clone());
141
142 self.infer_expr_coerce(*body, &Expectation::has_type(ret_ty));
143
144 self.return_ty = prev_ret_ty;
145
147 closure_ty 146 closure_ty
148 } 147 }
149 Expr::Call { callee, args } => { 148 Expr::Call { callee, args } => {
@@ -166,7 +165,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
166 Expr::Match { expr, arms } => { 165 Expr::Match { expr, arms } => {
167 let input_ty = self.infer_expr(*expr, &Expectation::none()); 166 let input_ty = self.infer_expr(*expr, &Expectation::none());
168 167
169 let mut result_ty = self.new_maybe_never_type_var(); 168 let mut result_ty = self.table.new_maybe_never_type_var();
170 169
171 for arm in arms { 170 for arm in arms {
172 for &pat in &arm.pats { 171 for &pat in &arm.pats {
@@ -200,7 +199,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
200 } 199 }
201 Expr::Return { expr } => { 200 Expr::Return { expr } => {
202 if let Some(expr) = expr { 201 if let Some(expr) = expr {
203 self.infer_expr(*expr, &Expectation::has_type(self.return_ty.clone())); 202 self.infer_expr_coerce(*expr, &Expectation::has_type(self.return_ty.clone()));
203 } else {
204 let unit = Ty::unit();
205 self.coerce(&unit, &self.return_ty.clone());
204 } 206 }
205 Ty::simple(TypeCtor::Never) 207 Ty::simple(TypeCtor::Never)
206 } 208 }
@@ -244,7 +246,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
244 ty 246 ty
245 } 247 }
246 Expr::Field { expr, name } => { 248 Expr::Field { expr, name } => {
247 let receiver_ty = self.infer_expr(*expr, &Expectation::none()); 249 let receiver_ty = self.infer_expr_inner(*expr, &Expectation::none());
248 let canonicalized = self.canonicalizer().canonicalize_ty(receiver_ty); 250 let canonicalized = self.canonicalizer().canonicalize_ty(receiver_ty);
249 let ty = autoderef::autoderef( 251 let ty = autoderef::autoderef(
250 self.db, 252 self.db,
@@ -279,45 +281,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
279 self.normalize_associated_types_in(ty) 281 self.normalize_associated_types_in(ty)
280 } 282 }
281 Expr::Await { expr } => { 283 Expr::Await { expr } => {
282 let inner_ty = self.infer_expr(*expr, &Expectation::none()); 284 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
283 let ty = match self.resolve_future_future_output() { 285 let ty =
284 Some(future_future_output_alias) => { 286 self.resolve_associated_type(inner_ty, self.resolve_future_future_output());
285 let ty = self.new_type_var();
286 let projection = ProjectionPredicate {
287 ty: ty.clone(),
288 projection_ty: ProjectionTy {
289 associated_ty: future_future_output_alias,
290 parameters: Substs::single(inner_ty),
291 },
292 };
293 self.obligations.push(Obligation::Projection(projection));
294 self.resolve_ty_as_possible(&mut vec![], ty)
295 }
296 None => Ty::Unknown,
297 };
298 ty 287 ty
299 } 288 }
300 Expr::Try { expr } => { 289 Expr::Try { expr } => {
301 let inner_ty = self.infer_expr(*expr, &Expectation::none()); 290 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
302 let ty = match self.resolve_ops_try_ok() { 291 let ty = self.resolve_associated_type(inner_ty, self.resolve_ops_try_ok());
303 Some(ops_try_ok_alias) => {
304 let ty = self.new_type_var();
305 let projection = ProjectionPredicate {
306 ty: ty.clone(),
307 projection_ty: ProjectionTy {
308 associated_ty: ops_try_ok_alias,
309 parameters: Substs::single(inner_ty),
310 },
311 };
312 self.obligations.push(Obligation::Projection(projection));
313 self.resolve_ty_as_possible(&mut vec![], ty)
314 }
315 None => Ty::Unknown,
316 };
317 ty 292 ty
318 } 293 }
319 Expr::Cast { expr, type_ref } => { 294 Expr::Cast { expr, type_ref } => {
320 let _inner_ty = self.infer_expr(*expr, &Expectation::none()); 295 let _inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
321 let cast_ty = self.make_ty(type_ref); 296 let cast_ty = self.make_ty(type_ref);
322 // FIXME check the cast... 297 // FIXME check the cast...
323 cast_ty 298 cast_ty
@@ -333,12 +308,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
333 } else { 308 } else {
334 Expectation::none() 309 Expectation::none()
335 }; 310 };
336 // FIXME reference coercions etc. 311 let inner_ty = self.infer_expr_inner(*expr, &expectation);
337 let inner_ty = self.infer_expr(*expr, &expectation);
338 Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) 312 Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty)
339 } 313 }
340 Expr::Box { expr } => { 314 Expr::Box { expr } => {
341 let inner_ty = self.infer_expr(*expr, &Expectation::none()); 315 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
342 if let Some(box_) = self.resolve_boxed_box() { 316 if let Some(box_) = self.resolve_boxed_box() {
343 Ty::apply_one(TypeCtor::Adt(box_), inner_ty) 317 Ty::apply_one(TypeCtor::Adt(box_), inner_ty)
344 } else { 318 } else {
@@ -346,7 +320,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
346 } 320 }
347 } 321 }
348 Expr::UnaryOp { expr, op } => { 322 Expr::UnaryOp { expr, op } => {
349 let inner_ty = self.infer_expr(*expr, &Expectation::none()); 323 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
350 match op { 324 match op {
351 UnaryOp::Deref => match self.resolver.krate() { 325 UnaryOp::Deref => match self.resolver.krate() {
352 Some(krate) => { 326 Some(krate) => {
@@ -369,31 +343,36 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
369 }, 343 },
370 UnaryOp::Neg => { 344 UnaryOp::Neg => {
371 match &inner_ty { 345 match &inner_ty {
372 Ty::Apply(a_ty) => match a_ty.ctor { 346 // Fast path for builtins
373 TypeCtor::Int(Uncertain::Unknown) 347 Ty::Apply(ApplicationTy {
374 | TypeCtor::Int(Uncertain::Known(IntTy { 348 ctor:
375 signedness: Signedness::Signed, 349 TypeCtor::Int(Uncertain::Known(IntTy {
376 .. 350 signedness: Signedness::Signed,
377 })) 351 ..
378 | TypeCtor::Float(..) => inner_ty, 352 })),
379 _ => Ty::Unknown, 353 ..
380 }, 354 })
381 Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => { 355 | Ty::Apply(ApplicationTy {
382 inner_ty 356 ctor: TypeCtor::Int(Uncertain::Unknown),
383 } 357 ..
384 // FIXME: resolve ops::Neg trait 358 })
385 _ => Ty::Unknown, 359 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Float(_), .. })
360 | Ty::Infer(InferTy::IntVar(..))
361 | Ty::Infer(InferTy::FloatVar(..)) => inner_ty,
362 // Otherwise we resolve via the std::ops::Neg trait
363 _ => self
364 .resolve_associated_type(inner_ty, self.resolve_ops_neg_output()),
386 } 365 }
387 } 366 }
388 UnaryOp::Not => { 367 UnaryOp::Not => {
389 match &inner_ty { 368 match &inner_ty {
390 Ty::Apply(a_ty) => match a_ty.ctor { 369 // Fast path for builtins
391 TypeCtor::Bool | TypeCtor::Int(_) => inner_ty, 370 Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. })
392 _ => Ty::Unknown, 371 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Int(_), .. })
393 }, 372 | Ty::Infer(InferTy::IntVar(..)) => inner_ty,
394 Ty::Infer(InferTy::IntVar(..)) => inner_ty, 373 // Otherwise we resolve via the std::ops::Not trait
395 // FIXME: resolve ops::Not trait for inner_ty 374 _ => self
396 _ => Ty::Unknown, 375 .resolve_associated_type(inner_ty, self.resolve_ops_not_output()),
397 } 376 }
398 } 377 }
399 } 378 }
@@ -415,21 +394,63 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
415 } 394 }
416 _ => Ty::Unknown, 395 _ => Ty::Unknown,
417 }, 396 },
397 Expr::Range { lhs, rhs, range_type } => {
398 let lhs_ty = lhs.map(|e| self.infer_expr_inner(e, &Expectation::none()));
399 let rhs_expect = lhs_ty
400 .as_ref()
401 .map_or_else(Expectation::none, |ty| Expectation::has_type(ty.clone()));
402 let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect));
403 match (range_type, lhs_ty, rhs_ty) {
404 (RangeOp::Exclusive, None, None) => match self.resolve_range_full() {
405 Some(adt) => Ty::simple(TypeCtor::Adt(adt)),
406 None => Ty::Unknown,
407 },
408 (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() {
409 Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty),
410 None => Ty::Unknown,
411 },
412 (RangeOp::Inclusive, None, Some(ty)) => {
413 match self.resolve_range_to_inclusive() {
414 Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty),
415 None => Ty::Unknown,
416 }
417 }
418 (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() {
419 Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty),
420 None => Ty::Unknown,
421 },
422 (RangeOp::Inclusive, Some(_), Some(ty)) => {
423 match self.resolve_range_inclusive() {
424 Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty),
425 None => Ty::Unknown,
426 }
427 }
428 (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() {
429 Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty),
430 None => Ty::Unknown,
431 },
432 (RangeOp::Inclusive, _, None) => Ty::Unknown,
433 }
434 }
418 Expr::Index { base, index } => { 435 Expr::Index { base, index } => {
419 let _base_ty = self.infer_expr(*base, &Expectation::none()); 436 let base_ty = self.infer_expr_inner(*base, &Expectation::none());
420 let _index_ty = self.infer_expr(*index, &Expectation::none()); 437 let index_ty = self.infer_expr(*index, &Expectation::none());
421 // FIXME: use `std::ops::Index::Output` to figure out the real return type 438
422 Ty::Unknown 439 self.resolve_associated_type_with_params(
440 base_ty,
441 self.resolve_ops_index_output(),
442 &[index_ty],
443 )
423 } 444 }
424 Expr::Tuple { exprs } => { 445 Expr::Tuple { exprs } => {
425 let mut tys = match &expected.ty { 446 let mut tys = match &expected.ty {
426 ty_app!(TypeCtor::Tuple { .. }, st) => st 447 ty_app!(TypeCtor::Tuple { .. }, st) => st
427 .iter() 448 .iter()
428 .cloned() 449 .cloned()
429 .chain(repeat_with(|| self.new_type_var())) 450 .chain(repeat_with(|| self.table.new_type_var()))
430 .take(exprs.len()) 451 .take(exprs.len())
431 .collect::<Vec<_>>(), 452 .collect::<Vec<_>>(),
432 _ => (0..exprs.len()).map(|_| self.new_type_var()).collect(), 453 _ => (0..exprs.len()).map(|_| self.table.new_type_var()).collect(),
433 }; 454 };
434 455
435 for (expr, ty) in exprs.iter().zip(tys.iter_mut()) { 456 for (expr, ty) in exprs.iter().zip(tys.iter_mut()) {
@@ -443,7 +464,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
443 ty_app!(TypeCtor::Array, st) | ty_app!(TypeCtor::Slice, st) => { 464 ty_app!(TypeCtor::Array, st) | ty_app!(TypeCtor::Slice, st) => {
444 st.as_single().clone() 465 st.as_single().clone()
445 } 466 }
446 _ => self.new_type_var(), 467 _ => self.table.new_type_var(),
447 }; 468 };
448 469
449 match array { 470 match array {
@@ -485,7 +506,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
485 }; 506 };
486 // use a new type variable if we got Ty::Unknown here 507 // use a new type variable if we got Ty::Unknown here
487 let ty = self.insert_type_vars_shallow(ty); 508 let ty = self.insert_type_vars_shallow(ty);
488 let ty = self.resolve_ty_as_possible(&mut vec![], ty); 509 let ty = self.resolve_ty_as_possible(ty);
489 self.write_expr_ty(tgt_expr, ty.clone()); 510 self.write_expr_ty(tgt_expr, ty.clone());
490 ty 511 ty
491 } 512 }
@@ -514,7 +535,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
514 } 535 }
515 } 536 }
516 537
517 let ty = self.resolve_ty_as_possible(&mut vec![], ty); 538 let ty = self.resolve_ty_as_possible(ty);
518 self.infer_pat(*pat, &ty, BindingMode::default()); 539 self.infer_pat(*pat, &ty, BindingMode::default());
519 } 540 }
520 Statement::Expr(expr) => { 541 Statement::Expr(expr) => {
@@ -558,7 +579,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
558 Some((ty, func)) => { 579 Some((ty, func)) => {
559 let ty = canonicalized_receiver.decanonicalize_ty(ty); 580 let ty = canonicalized_receiver.decanonicalize_ty(ty);
560 self.write_method_resolution(tgt_expr, func); 581 self.write_method_resolution(tgt_expr, func);
561 (ty, self.db.value_ty(func.into()), Some(self.db.generic_params(func.into()))) 582 (ty, self.db.value_ty(func.into()), Some(generics(self.db, func.into())))
562 } 583 }
563 None => (receiver_ty, Ty::Unknown, None), 584 None => (receiver_ty, Ty::Unknown, None),
564 }; 585 };
@@ -607,6 +628,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
607 continue; 628 continue;
608 } 629 }
609 630
631 let param_ty = self.insert_vars_for_impl_trait(param_ty);
610 let param_ty = self.normalize_associated_types_in(param_ty); 632 let param_ty = self.normalize_associated_types_in(param_ty);
611 self.infer_expr_coerce(arg, &Expectation::has_type(param_ty.clone())); 633 self.infer_expr_coerce(arg, &Expectation::has_type(param_ty.clone()));
612 } 634 }
@@ -615,17 +637,17 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
615 637
616 fn substs_for_method_call( 638 fn substs_for_method_call(
617 &mut self, 639 &mut self,
618 def_generics: Option<Arc<GenericParams>>, 640 def_generics: Option<Generics>,
619 generic_args: Option<&GenericArgs>, 641 generic_args: Option<&GenericArgs>,
620 receiver_ty: &Ty, 642 receiver_ty: &Ty,
621 ) -> Substs { 643 ) -> Substs {
622 let (parent_param_count, param_count) = 644 let (total_len, _parent_len, child_len) =
623 def_generics.as_ref().map_or((0, 0), |g| (g.count_parent_params(), g.params.len())); 645 def_generics.as_ref().map_or((0, 0, 0), |g| g.len_split());
624 let mut substs = Vec::with_capacity(parent_param_count + param_count); 646 let mut substs = Vec::with_capacity(total_len);
625 // Parent arguments are unknown, except for the receiver type 647 // Parent arguments are unknown, except for the receiver type
626 if let Some(parent_generics) = def_generics.and_then(|p| p.parent_params.clone()) { 648 if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) {
627 for param in &parent_generics.params { 649 for (_id, param) in parent_generics {
628 if param.name == name::SELF_TYPE { 650 if param.name == name![Self] {
629 substs.push(receiver_ty.clone()); 651 substs.push(receiver_ty.clone());
630 } else { 652 } else {
631 substs.push(Ty::Unknown); 653 substs.push(Ty::Unknown);
@@ -635,7 +657,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
635 // handle provided type arguments 657 // handle provided type arguments
636 if let Some(generic_args) = generic_args { 658 if let Some(generic_args) = generic_args {
637 // if args are provided, it should be all of them, but we can't rely on that 659 // if args are provided, it should be all of them, but we can't rely on that
638 for arg in generic_args.args.iter().take(param_count) { 660 for arg in generic_args.args.iter().take(child_len) {
639 match arg { 661 match arg {
640 GenericArg::Type(type_ref) => { 662 GenericArg::Type(type_ref) => {
641 let ty = self.make_ty(type_ref); 663 let ty = self.make_ty(type_ref);
@@ -645,10 +667,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
645 } 667 }
646 }; 668 };
647 let supplied_params = substs.len(); 669 let supplied_params = substs.len();
648 for _ in supplied_params..parent_param_count + param_count { 670 for _ in supplied_params..total_len {
649 substs.push(Ty::Unknown); 671 substs.push(Ty::Unknown);
650 } 672 }
651 assert_eq!(substs.len(), parent_param_count + param_count); 673 assert_eq!(substs.len(), total_len);
652 Substs(substs.into()) 674 Substs(substs.into())
653 } 675 }
654 676
@@ -665,13 +687,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
665 // add obligation for trait implementation, if this is a trait method 687 // add obligation for trait implementation, if this is a trait method
666 match def { 688 match def {
667 CallableDef::FunctionId(f) => { 689 CallableDef::FunctionId(f) => {
668 if let ContainerId::TraitId(trait_) = f.lookup(self.db).container { 690 if let AssocContainerId::TraitId(trait_) = f.lookup(self.db).container {
669 // construct a TraitDef 691 // construct a TraitDef
670 let substs = a_ty.parameters.prefix( 692 let substs =
671 self.db 693 a_ty.parameters.prefix(generics(self.db, trait_.into()).len());
672 .generic_params(trait_.into())
673 .count_params_including_parent(),
674 );
675 self.obligations.push(Obligation::Trait(TraitRef { 694 self.obligations.push(Obligation::Trait(TraitRef {
676 trait_: trait_.into(), 695 trait_: trait_.into(),
677 substs, 696 substs,
diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs
index 1ebb36239..a14662884 100644
--- a/crates/ra_hir_ty/src/infer/pat.rs
+++ b/crates/ra_hir_ty/src/infer/pat.rs
@@ -170,7 +170,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
170 } 170 }
171 BindingMode::Move => inner_ty.clone(), 171 BindingMode::Move => inner_ty.clone(),
172 }; 172 };
173 let bound_ty = self.resolve_ty_as_possible(&mut vec![], bound_ty); 173 let bound_ty = self.resolve_ty_as_possible(bound_ty);
174 self.write_pat_ty(pat, bound_ty); 174 self.write_pat_ty(pat, bound_ty);
175 return inner_ty; 175 return inner_ty;
176 } 176 }
@@ -179,7 +179,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
179 // use a new type variable if we got Ty::Unknown here 179 // use a new type variable if we got Ty::Unknown here
180 let ty = self.insert_type_vars_shallow(ty); 180 let ty = self.insert_type_vars_shallow(ty);
181 self.unify(&ty, expected); 181 self.unify(&ty, expected);
182 let ty = self.resolve_ty_as_possible(&mut vec![], ty); 182 let ty = self.resolve_ty_as_possible(ty);
183 self.write_pat_ty(pat, ty.clone()); 183 self.write_pat_ty(pat, ty.clone());
184 ty 184 ty
185 } 185 }
diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs
index 14be66836..ffd358367 100644
--- a/crates/ra_hir_ty/src/infer/path.rs
+++ b/crates/ra_hir_ty/src/infer/path.rs
@@ -1,9 +1,11 @@
1//! Path expression resolution. 1//! Path expression resolution.
2 2
3use std::iter;
4
3use hir_def::{ 5use hir_def::{
4 path::{Path, PathKind, PathSegment}, 6 path::{Path, PathSegment},
5 resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs}, 7 resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs},
6 AssocItemId, ContainerId, Lookup, 8 AssocContainerId, AssocItemId, Lookup,
7}; 9};
8use hir_expand::name::Name; 10use hir_expand::name::Name;
9 11
@@ -30,21 +32,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
30 path: &Path, 32 path: &Path,
31 id: ExprOrPatId, 33 id: ExprOrPatId,
32 ) -> Option<Ty> { 34 ) -> Option<Ty> {
33 let (value, self_subst) = if let PathKind::Type(type_ref) = &path.kind { 35 let (value, self_subst) = if let Some(type_ref) = path.type_anchor() {
34 if path.segments.is_empty() { 36 if path.segments().is_empty() {
35 // This can't actually happen syntax-wise 37 // This can't actually happen syntax-wise
36 return None; 38 return None;
37 } 39 }
38 let ty = self.make_ty(type_ref); 40 let ty = self.make_ty(type_ref);
39 let remaining_segments_for_ty = &path.segments[..path.segments.len() - 1]; 41 let remaining_segments_for_ty = path.segments().take(path.segments().len() - 1);
40 let ty = Ty::from_type_relative_path(self.db, resolver, ty, remaining_segments_for_ty); 42 let ty = Ty::from_type_relative_path(self.db, resolver, ty, remaining_segments_for_ty);
41 self.resolve_ty_assoc_item( 43 self.resolve_ty_assoc_item(
42 ty, 44 ty,
43 &path.segments.last().expect("path had at least one segment").name, 45 &path.segments().last().expect("path had at least one segment").name,
44 id, 46 id,
45 )? 47 )?
46 } else { 48 } else {
47 let value_or_partial = resolver.resolve_path_in_value_ns(self.db, &path)?; 49 let value_or_partial = resolver.resolve_path_in_value_ns(self.db, path.mod_path())?;
48 50
49 match value_or_partial { 51 match value_or_partial {
50 ResolveValueResult::ValueNs(it) => (it, None), 52 ResolveValueResult::ValueNs(it) => (it, None),
@@ -57,7 +59,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
57 let typable: ValueTyDefId = match value { 59 let typable: ValueTyDefId = match value {
58 ValueNs::LocalBinding(pat) => { 60 ValueNs::LocalBinding(pat) => {
59 let ty = self.result.type_of_pat.get(pat)?.clone(); 61 let ty = self.result.type_of_pat.get(pat)?.clone();
60 let ty = self.resolve_ty_as_possible(&mut vec![], ty); 62 let ty = self.resolve_ty_as_possible(ty);
61 return Some(ty); 63 return Some(ty);
62 } 64 }
63 ValueNs::FunctionId(it) => it.into(), 65 ValueNs::FunctionId(it) => it.into(),
@@ -83,13 +85,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
83 remaining_index: usize, 85 remaining_index: usize,
84 id: ExprOrPatId, 86 id: ExprOrPatId,
85 ) -> Option<(ValueNs, Option<Substs>)> { 87 ) -> Option<(ValueNs, Option<Substs>)> {
86 assert!(remaining_index < path.segments.len()); 88 assert!(remaining_index < path.segments().len());
87 // there may be more intermediate segments between the resolved one and 89 // there may be more intermediate segments between the resolved one and
88 // the end. Only the last segment needs to be resolved to a value; from 90 // the end. Only the last segment needs to be resolved to a value; from
89 // the segments before that, we need to get either a type or a trait ref. 91 // the segments before that, we need to get either a type or a trait ref.
90 92
91 let resolved_segment = &path.segments[remaining_index - 1]; 93 let resolved_segment = path.segments().get(remaining_index - 1).unwrap();
92 let remaining_segments = &path.segments[remaining_index..]; 94 let remaining_segments = path.segments().skip(remaining_index);
93 let is_before_last = remaining_segments.len() == 1; 95 let is_before_last = remaining_segments.len() == 1;
94 96
95 match (def, is_before_last) { 97 match (def, is_before_last) {
@@ -110,7 +112,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
110 // trait but it's not the last segment, so the next segment 112 // trait but it's not the last segment, so the next segment
111 // should resolve to an associated type of that trait (e.g. `<T 113 // should resolve to an associated type of that trait (e.g. `<T
112 // as Iterator>::Item::default`) 114 // as Iterator>::Item::default`)
113 let remaining_segments_for_ty = &remaining_segments[..remaining_segments.len() - 1]; 115 let remaining_segments_for_ty =
116 remaining_segments.take(remaining_segments.len() - 1);
114 let ty = Ty::from_partly_resolved_hir_path( 117 let ty = Ty::from_partly_resolved_hir_path(
115 self.db, 118 self.db,
116 &self.resolver, 119 &self.resolver,
@@ -136,7 +139,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
136 fn resolve_trait_assoc_item( 139 fn resolve_trait_assoc_item(
137 &mut self, 140 &mut self,
138 trait_ref: TraitRef, 141 trait_ref: TraitRef,
139 segment: &PathSegment, 142 segment: PathSegment<'_>,
140 id: ExprOrPatId, 143 id: ExprOrPatId,
141 ) -> Option<(ValueNs, Option<Substs>)> { 144 ) -> Option<(ValueNs, Option<Substs>)> {
142 let trait_ = trait_ref.trait_; 145 let trait_ = trait_ref.trait_;
@@ -148,7 +151,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
148 .map(|(_name, id)| (*id).into()) 151 .map(|(_name, id)| (*id).into())
149 .find_map(|item| match item { 152 .find_map(|item| match item {
150 AssocItemId::FunctionId(func) => { 153 AssocItemId::FunctionId(func) => {
151 if segment.name == self.db.function_data(func).name { 154 if segment.name == &self.db.function_data(func).name {
152 Some(AssocItemId::FunctionId(func)) 155 Some(AssocItemId::FunctionId(func))
153 } else { 156 } else {
154 None 157 None
@@ -156,7 +159,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
156 } 159 }
157 160
158 AssocItemId::ConstId(konst) => { 161 AssocItemId::ConstId(konst) => {
159 if self.db.const_data(konst).name.as_ref().map_or(false, |n| n == &segment.name) 162 if self.db.const_data(konst).name.as_ref().map_or(false, |n| n == segment.name)
160 { 163 {
161 Some(AssocItemId::ConstId(konst)) 164 Some(AssocItemId::ConstId(konst))
162 } else { 165 } else {
@@ -206,12 +209,23 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
206 AssocItemId::TypeAliasId(_) => unreachable!(), 209 AssocItemId::TypeAliasId(_) => unreachable!(),
207 }; 210 };
208 let substs = match container { 211 let substs = match container {
209 ContainerId::ImplId(_) => self.find_self_types(&def, ty.clone()), 212 AssocContainerId::ImplId(impl_id) => {
210 ContainerId::TraitId(trait_) => { 213 let impl_substs = Substs::build_for_def(self.db, impl_id)
214 .fill(iter::repeat_with(|| self.table.new_type_var()))
215 .build();
216 let impl_self_ty = self.db.impl_self_ty(impl_id).subst(&impl_substs);
217 let substs = Substs::build_for_def(self.db, item)
218 .use_parent_substs(&impl_substs)
219 .fill_with_params()
220 .build();
221 self.unify(&impl_self_ty, &ty);
222 Some(substs)
223 }
224 AssocContainerId::TraitId(trait_) => {
211 // we're picking this method 225 // we're picking this method
212 let trait_substs = Substs::build_for_def(self.db, trait_) 226 let trait_substs = Substs::build_for_def(self.db, trait_)
213 .push(ty.clone()) 227 .push(ty.clone())
214 .fill(std::iter::repeat_with(|| self.new_type_var())) 228 .fill(std::iter::repeat_with(|| self.table.new_type_var()))
215 .build(); 229 .build();
216 let substs = Substs::build_for_def(self.db, item) 230 let substs = Substs::build_for_def(self.db, item)
217 .use_parent_substs(&trait_substs) 231 .use_parent_substs(&trait_substs)
@@ -223,7 +237,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
223 })); 237 }));
224 Some(substs) 238 Some(substs)
225 } 239 }
226 ContainerId::ModuleId(_) => None, 240 AssocContainerId::ContainerId(_) => None,
227 }; 241 };
228 242
229 self.write_assoc_resolution(id, item.into()); 243 self.write_assoc_resolution(id, item.into());
@@ -231,38 +245,4 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
231 }, 245 },
232 ) 246 )
233 } 247 }
234
235 fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option<Substs> {
236 if let ValueNs::FunctionId(func) = *def {
237 // We only do the infer if parent has generic params
238 let gen = self.db.generic_params(func.into());
239 if gen.count_parent_params() == 0 {
240 return None;
241 }
242
243 let impl_id = match func.lookup(self.db).container {
244 ContainerId::ImplId(it) => it,
245 _ => return None,
246 };
247 let self_ty = self.db.impl_ty(impl_id).self_type().clone();
248 let self_ty_substs = self_ty.substs()?;
249 let actual_substs = actual_def_ty.substs()?;
250
251 let mut new_substs = vec![Ty::Unknown; gen.count_parent_params()];
252
253 // The following code *link up* the function actual parma type
254 // and impl_block type param index
255 self_ty_substs.iter().zip(actual_substs.iter()).for_each(|(param, pty)| {
256 if let Ty::Param { idx, .. } = param {
257 if let Some(s) = new_substs.get_mut(*idx as usize) {
258 *s = pty.clone();
259 }
260 }
261 });
262
263 Some(Substs(new_substs.into()))
264 } else {
265 None
266 }
267 }
268} 248}
diff --git a/crates/ra_hir_ty/src/infer/unify.rs b/crates/ra_hir_ty/src/infer/unify.rs
index f3a875678..fe05642ae 100644
--- a/crates/ra_hir_ty/src/infer/unify.rs
+++ b/crates/ra_hir_ty/src/infer/unify.rs
@@ -1,9 +1,15 @@
1//! Unification and canonicalization logic. 1//! Unification and canonicalization logic.
2 2
3use std::borrow::Cow;
4
5use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
6
7use test_utils::tested_by;
8
3use super::{InferenceContext, Obligation}; 9use super::{InferenceContext, Obligation};
4use crate::{ 10use crate::{
5 db::HirDatabase, utils::make_mut_slice, Canonical, InEnvironment, InferTy, ProjectionPredicate, 11 db::HirDatabase, utils::make_mut_slice, Canonical, InEnvironment, InferTy, ProjectionPredicate,
6 ProjectionTy, Substs, TraitRef, Ty, TypeWalk, 12 ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk,
7}; 13};
8 14
9impl<'a, D: HirDatabase> InferenceContext<'a, D> { 15impl<'a, D: HirDatabase> InferenceContext<'a, D> {
@@ -24,7 +30,7 @@ where
24 /// A stack of type variables that is used to detect recursive types (which 30 /// A stack of type variables that is used to detect recursive types (which
25 /// are an error, but we need to protect against them to avoid stack 31 /// are an error, but we need to protect against them to avoid stack
26 /// overflows). 32 /// overflows).
27 var_stack: Vec<super::TypeVarId>, 33 var_stack: Vec<TypeVarId>,
28} 34}
29 35
30pub(super) struct Canonicalized<T> { 36pub(super) struct Canonicalized<T> {
@@ -53,14 +59,14 @@ where
53 return tv.fallback_value(); 59 return tv.fallback_value();
54 } 60 }
55 if let Some(known_ty) = 61 if let Some(known_ty) =
56 self.ctx.var_unification_table.inlined_probe_value(inner).known() 62 self.ctx.table.var_unification_table.inlined_probe_value(inner).known()
57 { 63 {
58 self.var_stack.push(inner); 64 self.var_stack.push(inner);
59 let result = self.do_canonicalize_ty(known_ty.clone()); 65 let result = self.do_canonicalize_ty(known_ty.clone());
60 self.var_stack.pop(); 66 self.var_stack.pop();
61 result 67 result
62 } else { 68 } else {
63 let root = self.ctx.var_unification_table.find(inner); 69 let root = self.ctx.table.var_unification_table.find(inner);
64 let free_var = match tv { 70 let free_var = match tv {
65 InferTy::TypeVar(_) => InferTy::TypeVar(root), 71 InferTy::TypeVar(_) => InferTy::TypeVar(root),
66 InferTy::IntVar(_) => InferTy::IntVar(root), 72 InferTy::IntVar(_) => InferTy::IntVar(root),
@@ -153,10 +159,268 @@ impl<T> Canonicalized<T> {
153 solution: Canonical<Vec<Ty>>, 159 solution: Canonical<Vec<Ty>>,
154 ) { 160 ) {
155 // the solution may contain new variables, which we need to convert to new inference vars 161 // the solution may contain new variables, which we need to convert to new inference vars
156 let new_vars = Substs((0..solution.num_vars).map(|_| ctx.new_type_var()).collect()); 162 let new_vars = Substs((0..solution.num_vars).map(|_| ctx.table.new_type_var()).collect());
157 for (i, ty) in solution.value.into_iter().enumerate() { 163 for (i, ty) in solution.value.into_iter().enumerate() {
158 let var = self.free_vars[i]; 164 let var = self.free_vars[i];
159 ctx.unify(&Ty::Infer(var), &ty.subst_bound_vars(&new_vars)); 165 ctx.table.unify(&Ty::Infer(var), &ty.subst_bound_vars(&new_vars));
166 }
167 }
168}
169
170pub fn unify(ty1: &Canonical<Ty>, ty2: &Canonical<Ty>) -> Option<Substs> {
171 let mut table = InferenceTable::new();
172 let vars =
173 Substs::builder(ty1.num_vars).fill(std::iter::repeat_with(|| table.new_type_var())).build();
174 let ty_with_vars = ty1.value.clone().subst_bound_vars(&vars);
175 if !table.unify(&ty_with_vars, &ty2.value) {
176 return None;
177 }
178 Some(
179 Substs::builder(ty1.num_vars)
180 .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone())))
181 .build(),
182 )
183}
184
185#[derive(Clone, Debug)]
186pub(crate) struct InferenceTable {
187 pub(super) var_unification_table: InPlaceUnificationTable<TypeVarId>,
188}
189
190impl InferenceTable {
191 pub fn new() -> Self {
192 InferenceTable { var_unification_table: InPlaceUnificationTable::new() }
193 }
194
195 pub fn new_type_var(&mut self) -> Ty {
196 Ty::Infer(InferTy::TypeVar(self.var_unification_table.new_key(TypeVarValue::Unknown)))
197 }
198
199 pub fn new_integer_var(&mut self) -> Ty {
200 Ty::Infer(InferTy::IntVar(self.var_unification_table.new_key(TypeVarValue::Unknown)))
201 }
202
203 pub fn new_float_var(&mut self) -> Ty {
204 Ty::Infer(InferTy::FloatVar(self.var_unification_table.new_key(TypeVarValue::Unknown)))
205 }
206
207 pub fn new_maybe_never_type_var(&mut self) -> Ty {
208 Ty::Infer(InferTy::MaybeNeverTypeVar(
209 self.var_unification_table.new_key(TypeVarValue::Unknown),
210 ))
211 }
212
213 pub fn resolve_ty_completely(&mut self, ty: Ty) -> Ty {
214 self.resolve_ty_completely_inner(&mut Vec::new(), ty)
215 }
216
217 pub fn resolve_ty_as_possible(&mut self, ty: Ty) -> Ty {
218 self.resolve_ty_as_possible_inner(&mut Vec::new(), ty)
219 }
220
221 pub fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
222 self.unify_inner(ty1, ty2, 0)
223 }
224
225 pub fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs, depth: usize) -> bool {
226 substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth))
227 }
228
229 fn unify_inner(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool {
230 if depth > 1000 {
231 // prevent stackoverflows
232 panic!("infinite recursion in unification");
233 }
234 if ty1 == ty2 {
235 return true;
236 }
237 // try to resolve type vars first
238 let ty1 = self.resolve_ty_shallow(ty1);
239 let ty2 = self.resolve_ty_shallow(ty2);
240 match (&*ty1, &*ty2) {
241 (Ty::Apply(a_ty1), Ty::Apply(a_ty2)) if a_ty1.ctor == a_ty2.ctor => {
242 self.unify_substs(&a_ty1.parameters, &a_ty2.parameters, depth + 1)
243 }
244 _ => self.unify_inner_trivial(&ty1, &ty2),
245 }
246 }
247
248 pub(super) fn unify_inner_trivial(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
249 match (ty1, ty2) {
250 (Ty::Unknown, _) | (_, Ty::Unknown) => true,
251
252 (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2)))
253 | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2)))
254 | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2)))
255 | (
256 Ty::Infer(InferTy::MaybeNeverTypeVar(tv1)),
257 Ty::Infer(InferTy::MaybeNeverTypeVar(tv2)),
258 ) => {
259 // both type vars are unknown since we tried to resolve them
260 self.var_unification_table.union(*tv1, *tv2);
261 true
262 }
263
264 // The order of MaybeNeverTypeVar matters here.
265 // Unifying MaybeNeverTypeVar and TypeVar will let the latter become MaybeNeverTypeVar.
266 // Unifying MaybeNeverTypeVar and other concrete type will let the former become it.
267 (Ty::Infer(InferTy::TypeVar(tv)), other)
268 | (other, Ty::Infer(InferTy::TypeVar(tv)))
269 | (Ty::Infer(InferTy::MaybeNeverTypeVar(tv)), other)
270 | (other, Ty::Infer(InferTy::MaybeNeverTypeVar(tv)))
271 | (Ty::Infer(InferTy::IntVar(tv)), other @ ty_app!(TypeCtor::Int(_)))
272 | (other @ ty_app!(TypeCtor::Int(_)), Ty::Infer(InferTy::IntVar(tv)))
273 | (Ty::Infer(InferTy::FloatVar(tv)), other @ ty_app!(TypeCtor::Float(_)))
274 | (other @ ty_app!(TypeCtor::Float(_)), Ty::Infer(InferTy::FloatVar(tv))) => {
275 // the type var is unknown since we tried to resolve it
276 self.var_unification_table.union_value(*tv, TypeVarValue::Known(other.clone()));
277 true
278 }
279
280 _ => false,
281 }
282 }
283
284 /// If `ty` is a type variable with known type, returns that type;
285 /// otherwise, return ty.
286 pub fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> {
287 let mut ty = Cow::Borrowed(ty);
288 // The type variable could resolve to a int/float variable. Hence try
289 // resolving up to three times; each type of variable shouldn't occur
290 // more than once
291 for i in 0..3 {
292 if i > 0 {
293 tested_by!(type_var_resolves_to_int_var);
294 }
295 match &*ty {
296 Ty::Infer(tv) => {
297 let inner = tv.to_inner();
298 match self.var_unification_table.inlined_probe_value(inner).known() {
299 Some(known_ty) => {
300 // The known_ty can't be a type var itself
301 ty = Cow::Owned(known_ty.clone());
302 }
303 _ => return ty,
304 }
305 }
306 _ => return ty,
307 }
308 }
309 log::error!("Inference variable still not resolved: {:?}", ty);
310 ty
311 }
312
313 /// Resolves the type as far as currently possible, replacing type variables
314 /// by their known types. All types returned by the infer_* functions should
315 /// be resolved as far as possible, i.e. contain no type variables with
316 /// known type.
317 fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
318 ty.fold(&mut |ty| match ty {
319 Ty::Infer(tv) => {
320 let inner = tv.to_inner();
321 if tv_stack.contains(&inner) {
322 tested_by!(type_var_cycles_resolve_as_possible);
323 // recursive type
324 return tv.fallback_value();
325 }
326 if let Some(known_ty) =
327 self.var_unification_table.inlined_probe_value(inner).known()
328 {
329 // known_ty may contain other variables that are known by now
330 tv_stack.push(inner);
331 let result = self.resolve_ty_as_possible_inner(tv_stack, known_ty.clone());
332 tv_stack.pop();
333 result
334 } else {
335 ty
336 }
337 }
338 _ => ty,
339 })
340 }
341
342 /// Resolves the type completely; type variables without known type are
343 /// replaced by Ty::Unknown.
344 fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
345 ty.fold(&mut |ty| match ty {
346 Ty::Infer(tv) => {
347 let inner = tv.to_inner();
348 if tv_stack.contains(&inner) {
349 tested_by!(type_var_cycles_resolve_completely);
350 // recursive type
351 return tv.fallback_value();
352 }
353 if let Some(known_ty) =
354 self.var_unification_table.inlined_probe_value(inner).known()
355 {
356 // known_ty may contain other variables that are known by now
357 tv_stack.push(inner);
358 let result = self.resolve_ty_completely_inner(tv_stack, known_ty.clone());
359 tv_stack.pop();
360 result
361 } else {
362 tv.fallback_value()
363 }
364 }
365 _ => ty,
366 })
367 }
368}
369
370/// The ID of a type variable.
371#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
372pub struct TypeVarId(pub(super) u32);
373
374impl UnifyKey for TypeVarId {
375 type Value = TypeVarValue;
376
377 fn index(&self) -> u32 {
378 self.0
379 }
380
381 fn from_index(i: u32) -> Self {
382 TypeVarId(i)
383 }
384
385 fn tag() -> &'static str {
386 "TypeVarId"
387 }
388}
389
390/// The value of a type variable: either we already know the type, or we don't
391/// know it yet.
392#[derive(Clone, PartialEq, Eq, Debug)]
393pub enum TypeVarValue {
394 Known(Ty),
395 Unknown,
396}
397
398impl TypeVarValue {
399 fn known(&self) -> Option<&Ty> {
400 match self {
401 TypeVarValue::Known(ty) => Some(ty),
402 TypeVarValue::Unknown => None,
403 }
404 }
405}
406
407impl UnifyValue for TypeVarValue {
408 type Error = NoError;
409
410 fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> {
411 match (value1, value2) {
412 // We should never equate two type variables, both of which have
413 // known types. Instead, we recursively equate those types.
414 (TypeVarValue::Known(t1), TypeVarValue::Known(t2)) => panic!(
415 "equating two type variables, both of which have known types: {:?} and {:?}",
416 t1, t2
417 ),
418
419 // If one side is known, prefer that one.
420 (TypeVarValue::Known(..), TypeVarValue::Unknown) => Ok(value1.clone()),
421 (TypeVarValue::Unknown, TypeVarValue::Known(..)) => Ok(value2.clone()),
422
423 (TypeVarValue::Unknown, TypeVarValue::Unknown) => Ok(TypeVarValue::Unknown),
160 } 424 }
161 } 425 }
162} 426}
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index b45c8f82f..48abf97c9 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -44,8 +44,8 @@ use std::sync::Arc;
44use std::{fmt, iter, mem}; 44use std::{fmt, iter, mem};
45 45
46use hir_def::{ 46use hir_def::{
47 expr::ExprId, generics::GenericParams, type_ref::Mutability, AdtId, ContainerId, DefWithBodyId, 47 expr::ExprId, type_ref::Mutability, AdtId, AssocContainerId, DefWithBodyId, GenericDefId,
48 GenericDefId, HasModule, Lookup, TraitId, TypeAliasId, 48 HasModule, Lookup, TraitId, TypeAliasId,
49}; 49};
50use hir_expand::name::Name; 50use hir_expand::name::Name;
51use ra_db::{impl_intern_key, salsa, CrateId}; 51use ra_db::{impl_intern_key, salsa, CrateId};
@@ -53,7 +53,7 @@ use ra_db::{impl_intern_key, salsa, CrateId};
53use crate::{ 53use crate::{
54 db::HirDatabase, 54 db::HirDatabase,
55 primitive::{FloatTy, IntTy, Uncertain}, 55 primitive::{FloatTy, IntTy, Uncertain},
56 utils::make_mut_slice, 56 utils::{generics, make_mut_slice, Generics},
57}; 57};
58use display::{HirDisplay, HirFormatter}; 58use display::{HirDisplay, HirFormatter};
59 59
@@ -166,16 +166,16 @@ impl TypeCtor {
166 | TypeCtor::Closure { .. } // 1 param representing the signature of the closure 166 | TypeCtor::Closure { .. } // 1 param representing the signature of the closure
167 => 1, 167 => 1,
168 TypeCtor::Adt(adt) => { 168 TypeCtor::Adt(adt) => {
169 let generic_params = db.generic_params(AdtId::from(adt).into()); 169 let generic_params = generics(db, AdtId::from(adt).into());
170 generic_params.count_params_including_parent() 170 generic_params.len()
171 } 171 }
172 TypeCtor::FnDef(callable) => { 172 TypeCtor::FnDef(callable) => {
173 let generic_params = db.generic_params(callable.into()); 173 let generic_params = generics(db, callable.into());
174 generic_params.count_params_including_parent() 174 generic_params.len()
175 } 175 }
176 TypeCtor::AssociatedType(type_alias) => { 176 TypeCtor::AssociatedType(type_alias) => {
177 let generic_params = db.generic_params(type_alias.into()); 177 let generic_params = generics(db, type_alias.into());
178 generic_params.count_params_including_parent() 178 generic_params.len()
179 } 179 }
180 TypeCtor::FnPtr { num_args } => num_args as usize + 1, 180 TypeCtor::FnPtr { num_args } => num_args as usize + 1,
181 TypeCtor::Tuple { cardinality } => cardinality as usize, 181 TypeCtor::Tuple { cardinality } => cardinality as usize,
@@ -251,7 +251,7 @@ impl ProjectionTy {
251 251
252 fn trait_(&self, db: &impl HirDatabase) -> TraitId { 252 fn trait_(&self, db: &impl HirDatabase) -> TraitId {
253 match self.associated_ty.lookup(db).container { 253 match self.associated_ty.lookup(db).container {
254 ContainerId::TraitId(it) => it, 254 AssocContainerId::TraitId(it) => it,
255 _ => panic!("projection ty without parent trait"), 255 _ => panic!("projection ty without parent trait"),
256 } 256 }
257 } 257 }
@@ -364,36 +364,26 @@ impl Substs {
364 } 364 }
365 365
366 /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). 366 /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`).
367 pub fn identity(generic_params: &GenericParams) -> Substs { 367 pub(crate) fn identity(generic_params: &Generics) -> Substs {
368 Substs( 368 Substs(
369 generic_params 369 generic_params.iter().map(|(idx, p)| Ty::Param { idx, name: p.name.clone() }).collect(),
370 .params_including_parent()
371 .into_iter()
372 .map(|p| Ty::Param { idx: p.idx, name: p.name.clone() })
373 .collect(),
374 ) 370 )
375 } 371 }
376 372
377 /// Return Substs that replace each parameter by a bound variable. 373 /// Return Substs that replace each parameter by a bound variable.
378 pub fn bound_vars(generic_params: &GenericParams) -> Substs { 374 pub(crate) fn bound_vars(generic_params: &Generics) -> Substs {
379 Substs( 375 Substs(generic_params.iter().map(|(idx, _p)| Ty::Bound(idx)).collect())
380 generic_params
381 .params_including_parent()
382 .into_iter()
383 .map(|p| Ty::Bound(p.idx))
384 .collect(),
385 )
386 } 376 }
387 377
388 pub fn build_for_def(db: &impl HirDatabase, def: impl Into<GenericDefId>) -> SubstsBuilder { 378 pub fn build_for_def(db: &impl HirDatabase, def: impl Into<GenericDefId>) -> SubstsBuilder {
389 let def = def.into(); 379 let def = def.into();
390 let params = db.generic_params(def); 380 let params = generics(db, def);
391 let param_count = params.count_params_including_parent(); 381 let param_count = params.len();
392 Substs::builder(param_count) 382 Substs::builder(param_count)
393 } 383 }
394 384
395 pub fn build_for_generics(generic_params: &GenericParams) -> SubstsBuilder { 385 pub(crate) fn build_for_generics(generic_params: &Generics) -> SubstsBuilder {
396 Substs::builder(generic_params.count_params_including_parent()) 386 Substs::builder(generic_params.len())
397 } 387 }
398 388
399 pub fn build_for_type_ctor(db: &impl HirDatabase, type_ctor: TypeCtor) -> SubstsBuilder { 389 pub fn build_for_type_ctor(db: &impl HirDatabase, type_ctor: TypeCtor) -> SubstsBuilder {
@@ -486,21 +476,6 @@ impl TypeWalk for TraitRef {
486 } 476 }
487} 477}
488 478
489#[derive(Clone, PartialEq, Eq, Debug)]
490pub enum ImplTy {
491 Inherent(Ty),
492 TraitRef(TraitRef),
493}
494
495impl ImplTy {
496 pub(crate) fn self_type(&self) -> &Ty {
497 match self {
498 ImplTy::Inherent(it) => it,
499 ImplTy::TraitRef(tr) => &tr.substs[0],
500 }
501 }
502}
503
504/// Like `generics::WherePredicate`, but with resolved types: A condition on the 479/// Like `generics::WherePredicate`, but with resolved types: A condition on the
505/// parameters of a generic item. 480/// parameters of a generic item.
506#[derive(Debug, Clone, PartialEq, Eq, Hash)] 481#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -931,13 +906,44 @@ impl HirDisplay for ApplicationTy {
931 write!(f, "{}", name)?; 906 write!(f, "{}", name)?;
932 if self.parameters.len() > 0 { 907 if self.parameters.len() > 0 {
933 write!(f, "<")?; 908 write!(f, "<")?;
934 f.write_joined(&*self.parameters.0, ", ")?; 909
910 let mut non_default_parameters = Vec::with_capacity(self.parameters.len());
911 let parameters_to_write = if f.should_display_default_types() {
912 self.parameters.0.as_ref()
913 } else {
914 match self
915 .ctor
916 .as_generic_def()
917 .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
918 .filter(|defaults| !defaults.is_empty())
919 {
920 Option::None => self.parameters.0.as_ref(),
921 Option::Some(default_parameters) => {
922 for (i, parameter) in self.parameters.iter().enumerate() {
923 match (parameter, default_parameters.get(i)) {
924 (&Ty::Unknown, _) | (_, None) => {
925 non_default_parameters.push(parameter.clone())
926 }
927 (_, Some(default_parameter))
928 if parameter != default_parameter =>
929 {
930 non_default_parameters.push(parameter.clone())
931 }
932 _ => (),
933 }
934 }
935 &non_default_parameters
936 }
937 }
938 };
939
940 f.write_joined(parameters_to_write, ", ")?;
935 write!(f, ">")?; 941 write!(f, ">")?;
936 } 942 }
937 } 943 }
938 TypeCtor::AssociatedType(type_alias) => { 944 TypeCtor::AssociatedType(type_alias) => {
939 let trait_ = match type_alias.lookup(f.db).container { 945 let trait_ = match type_alias.lookup(f.db).container {
940 ContainerId::TraitId(it) => it, 946 AssocContainerId::TraitId(it) => it,
941 _ => panic!("not an associated type"), 947 _ => panic!("not an associated type"),
942 }; 948 };
943 let trait_name = f.db.trait_data(trait_).name.clone(); 949 let trait_name = f.db.trait_data(trait_).name.clone();
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index 091c60f4f..af3db2e1d 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -11,10 +11,10 @@ use std::sync::Arc;
11use hir_def::{ 11use hir_def::{
12 builtin_type::BuiltinType, 12 builtin_type::BuiltinType,
13 generics::WherePredicate, 13 generics::WherePredicate,
14 path::{GenericArg, Path, PathKind, PathSegment}, 14 path::{GenericArg, Path, PathSegment, PathSegments},
15 resolver::{HasResolver, Resolver, TypeNs}, 15 resolver::{HasResolver, Resolver, TypeNs},
16 type_ref::{TypeBound, TypeRef}, 16 type_ref::{TypeBound, TypeRef},
17 AdtId, AstItemDef, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, 17 AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId,
18 LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId, 18 LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId,
19}; 19};
20use ra_arena::map::ArenaMap; 20use ra_arena::map::ArenaMap;
@@ -24,11 +24,11 @@ use crate::{
24 db::HirDatabase, 24 db::HirDatabase,
25 primitive::{FloatTy, IntTy}, 25 primitive::{FloatTy, IntTy},
26 utils::{ 26 utils::{
27 all_super_traits, associated_type_by_name_including_super_traits, make_mut_slice, 27 all_super_traits, associated_type_by_name_including_super_traits, generics, make_mut_slice,
28 variant_data, 28 variant_data,
29 }, 29 },
30 FnSig, GenericPredicate, ImplTy, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, 30 FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef,
31 TraitRef, Ty, TypeCtor, TypeWalk, 31 Ty, TypeCtor, TypeWalk,
32}; 32};
33 33
34impl Ty { 34impl Ty {
@@ -101,17 +101,19 @@ impl Ty {
101 TypeRef::Path(path) => path, 101 TypeRef::Path(path) => path,
102 _ => return None, 102 _ => return None,
103 }; 103 };
104 if let PathKind::Type(_) = &path.kind { 104 if path.type_anchor().is_some() {
105 return None; 105 return None;
106 } 106 }
107 if path.segments.len() > 1 { 107 if path.segments().len() > 1 {
108 return None; 108 return None;
109 } 109 }
110 let resolution = match resolver.resolve_path_in_type_ns(db, path) { 110 let resolution = match resolver.resolve_path_in_type_ns(db, path.mod_path()) {
111 Some((it, None)) => it, 111 Some((it, None)) => it,
112 _ => return None, 112 _ => return None,
113 }; 113 };
114 if let TypeNs::GenericParam(idx) = resolution { 114 if let TypeNs::GenericParam(param_id) = resolution {
115 let generics = generics(db, resolver.generic_def().expect("generics in scope"));
116 let idx = generics.param_idx(param_id);
115 Some(idx) 117 Some(idx)
116 } else { 118 } else {
117 None 119 None
@@ -122,11 +124,11 @@ impl Ty {
122 db: &impl HirDatabase, 124 db: &impl HirDatabase,
123 resolver: &Resolver, 125 resolver: &Resolver,
124 ty: Ty, 126 ty: Ty,
125 remaining_segments: &[PathSegment], 127 remaining_segments: PathSegments<'_>,
126 ) -> Ty { 128 ) -> Ty {
127 if remaining_segments.len() == 1 { 129 if remaining_segments.len() == 1 {
128 // resolve unselected assoc types 130 // resolve unselected assoc types
129 let segment = &remaining_segments[0]; 131 let segment = remaining_segments.first().unwrap();
130 Ty::select_associated_type(db, resolver, ty, segment) 132 Ty::select_associated_type(db, resolver, ty, segment)
131 } else if remaining_segments.len() > 1 { 133 } else if remaining_segments.len() > 1 {
132 // FIXME report error (ambiguous associated type) 134 // FIXME report error (ambiguous associated type)
@@ -140,15 +142,15 @@ impl Ty {
140 db: &impl HirDatabase, 142 db: &impl HirDatabase,
141 resolver: &Resolver, 143 resolver: &Resolver,
142 resolution: TypeNs, 144 resolution: TypeNs,
143 resolved_segment: &PathSegment, 145 resolved_segment: PathSegment<'_>,
144 remaining_segments: &[PathSegment], 146 remaining_segments: PathSegments<'_>,
145 ) -> Ty { 147 ) -> Ty {
146 let ty = match resolution { 148 let ty = match resolution {
147 TypeNs::TraitId(trait_) => { 149 TypeNs::TraitId(trait_) => {
148 let trait_ref = 150 let trait_ref =
149 TraitRef::from_resolved_path(db, resolver, trait_, resolved_segment, None); 151 TraitRef::from_resolved_path(db, resolver, trait_, resolved_segment, None);
150 return if remaining_segments.len() == 1 { 152 return if remaining_segments.len() == 1 {
151 let segment = &remaining_segments[0]; 153 let segment = remaining_segments.first().unwrap();
152 let associated_ty = associated_type_by_name_including_super_traits( 154 let associated_ty = associated_type_by_name_including_super_traits(
153 db, 155 db,
154 trait_ref.trait_, 156 trait_ref.trait_,
@@ -174,12 +176,14 @@ impl Ty {
174 Ty::Dyn(Arc::new([GenericPredicate::Implemented(trait_ref)])) 176 Ty::Dyn(Arc::new([GenericPredicate::Implemented(trait_ref)]))
175 }; 177 };
176 } 178 }
177 TypeNs::GenericParam(idx) => { 179 TypeNs::GenericParam(param_id) => {
180 let generics = generics(db, resolver.generic_def().expect("generics in scope"));
181 let idx = generics.param_idx(param_id);
178 // FIXME: maybe return name in resolution? 182 // FIXME: maybe return name in resolution?
179 let name = resolved_segment.name.clone(); 183 let name = generics.param_name(param_id);
180 Ty::Param { idx, name } 184 Ty::Param { idx, name }
181 } 185 }
182 TypeNs::SelfType(impl_id) => db.impl_ty(impl_id).self_type().clone(), 186 TypeNs::SelfType(impl_id) => db.impl_self_ty(impl_id).clone(),
183 TypeNs::AdtSelfType(adt) => db.ty(adt.into()), 187 TypeNs::AdtSelfType(adt) => db.ty(adt.into()),
184 188
185 TypeNs::AdtId(it) => Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()), 189 TypeNs::AdtId(it) => Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()),
@@ -198,21 +202,21 @@ impl Ty {
198 202
199 pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty { 203 pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty {
200 // Resolve the path (in type namespace) 204 // Resolve the path (in type namespace)
201 if let PathKind::Type(type_ref) = &path.kind { 205 if let Some(type_ref) = path.type_anchor() {
202 let ty = Ty::from_hir(db, resolver, &type_ref); 206 let ty = Ty::from_hir(db, resolver, &type_ref);
203 let remaining_segments = &path.segments[..]; 207 return Ty::from_type_relative_path(db, resolver, ty, path.segments());
204 return Ty::from_type_relative_path(db, resolver, ty, remaining_segments);
205 } 208 }
206 let (resolution, remaining_index) = match resolver.resolve_path_in_type_ns(db, path) { 209 let (resolution, remaining_index) =
207 Some(it) => it, 210 match resolver.resolve_path_in_type_ns(db, path.mod_path()) {
208 None => return Ty::Unknown, 211 Some(it) => it,
209 }; 212 None => return Ty::Unknown,
213 };
210 let (resolved_segment, remaining_segments) = match remaining_index { 214 let (resolved_segment, remaining_segments) = match remaining_index {
211 None => ( 215 None => (
212 path.segments.last().expect("resolved path has at least one element"), 216 path.segments().last().expect("resolved path has at least one element"),
213 &[] as &[PathSegment], 217 PathSegments::EMPTY,
214 ), 218 ),
215 Some(i) => (&path.segments[i - 1], &path.segments[i..]), 219 Some(i) => (path.segments().get(i - 1).unwrap(), path.segments().skip(i)),
216 }; 220 };
217 Ty::from_partly_resolved_hir_path( 221 Ty::from_partly_resolved_hir_path(
218 db, 222 db,
@@ -227,7 +231,7 @@ impl Ty {
227 db: &impl HirDatabase, 231 db: &impl HirDatabase,
228 resolver: &Resolver, 232 resolver: &Resolver,
229 self_ty: Ty, 233 self_ty: Ty,
230 segment: &PathSegment, 234 segment: PathSegment<'_>,
231 ) -> Ty { 235 ) -> Ty {
232 let param_idx = match self_ty { 236 let param_idx = match self_ty {
233 Ty::Param { idx, .. } => idx, 237 Ty::Param { idx, .. } => idx,
@@ -257,7 +261,7 @@ impl Ty {
257 fn from_hir_path_inner( 261 fn from_hir_path_inner(
258 db: &impl HirDatabase, 262 db: &impl HirDatabase,
259 resolver: &Resolver, 263 resolver: &Resolver,
260 segment: &PathSegment, 264 segment: PathSegment<'_>,
261 typable: TyDefId, 265 typable: TyDefId,
262 ) -> Ty { 266 ) -> Ty {
263 let generic_def = match typable { 267 let generic_def = match typable {
@@ -280,7 +284,7 @@ impl Ty {
280 // special-case enum variants 284 // special-case enum variants
281 resolved: ValueTyDefId, 285 resolved: ValueTyDefId,
282 ) -> Substs { 286 ) -> Substs {
283 let last = path.segments.last().expect("path should have at least one segment"); 287 let last = path.segments().last().expect("path should have at least one segment");
284 let (segment, generic_def) = match resolved { 288 let (segment, generic_def) = match resolved {
285 ValueTyDefId::FunctionId(it) => (last, Some(it.into())), 289 ValueTyDefId::FunctionId(it) => (last, Some(it.into())),
286 ValueTyDefId::StructId(it) => (last, Some(it.into())), 290 ValueTyDefId::StructId(it) => (last, Some(it.into())),
@@ -292,13 +296,11 @@ impl Ty {
292 // referring to the variant. So `Option::<T>::None` and 296 // referring to the variant. So `Option::<T>::None` and
293 // `Option::None::<T>` are both allowed (though the former is 297 // `Option::None::<T>` are both allowed (though the former is
294 // preferred). See also `def_ids_for_path_segments` in rustc. 298 // preferred). See also `def_ids_for_path_segments` in rustc.
295 let len = path.segments.len(); 299 let len = path.segments().len();
296 let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some() { 300 let penultimate = if len >= 2 { path.segments().get(len - 2) } else { None };
297 // Option::<T>::None 301 let segment = match penultimate {
298 &path.segments[len - 2] 302 Some(segment) if segment.args_and_bindings.is_some() => segment,
299 } else { 303 _ => last,
300 // Option::None::<T>
301 last
302 }; 304 };
303 (segment, Some(var.parent.into())) 305 (segment, Some(var.parent.into()))
304 } 306 }
@@ -310,16 +312,15 @@ impl Ty {
310pub(super) fn substs_from_path_segment( 312pub(super) fn substs_from_path_segment(
311 db: &impl HirDatabase, 313 db: &impl HirDatabase,
312 resolver: &Resolver, 314 resolver: &Resolver,
313 segment: &PathSegment, 315 segment: PathSegment<'_>,
314 def_generic: Option<GenericDefId>, 316 def_generic: Option<GenericDefId>,
315 add_self_param: bool, 317 add_self_param: bool,
316) -> Substs { 318) -> Substs {
317 let mut substs = Vec::new(); 319 let mut substs = Vec::new();
318 let def_generics = def_generic.map(|def| db.generic_params(def.into())); 320 let def_generics = def_generic.map(|def| generics(db, def.into()));
319 321
320 let (parent_param_count, param_count) = 322 let (total_len, parent_len, child_len) = def_generics.map_or((0, 0, 0), |g| g.len_split());
321 def_generics.map_or((0, 0), |g| (g.count_parent_params(), g.params.len())); 323 substs.extend(iter::repeat(Ty::Unknown).take(parent_len));
322 substs.extend(iter::repeat(Ty::Unknown).take(parent_param_count));
323 if add_self_param { 324 if add_self_param {
324 // FIXME this add_self_param argument is kind of a hack: Traits have the 325 // FIXME this add_self_param argument is kind of a hack: Traits have the
325 // Self type as an implicit first type parameter, but it can't be 326 // Self type as an implicit first type parameter, but it can't be
@@ -330,8 +331,8 @@ pub(super) fn substs_from_path_segment(
330 if let Some(generic_args) = &segment.args_and_bindings { 331 if let Some(generic_args) = &segment.args_and_bindings {
331 // if args are provided, it should be all of them, but we can't rely on that 332 // if args are provided, it should be all of them, but we can't rely on that
332 let self_param_correction = if add_self_param { 1 } else { 0 }; 333 let self_param_correction = if add_self_param { 1 } else { 0 };
333 let param_count = param_count - self_param_correction; 334 let child_len = child_len + self_param_correction;
334 for arg in generic_args.args.iter().take(param_count) { 335 for arg in generic_args.args.iter().take(child_len) {
335 match arg { 336 match arg {
336 GenericArg::Type(type_ref) => { 337 GenericArg::Type(type_ref) => {
337 let ty = Ty::from_hir(db, resolver, type_ref); 338 let ty = Ty::from_hir(db, resolver, type_ref);
@@ -342,10 +343,10 @@ pub(super) fn substs_from_path_segment(
342 } 343 }
343 // add placeholders for args that were not provided 344 // add placeholders for args that were not provided
344 let supplied_params = substs.len(); 345 let supplied_params = substs.len();
345 for _ in supplied_params..parent_param_count + param_count { 346 for _ in supplied_params..total_len {
346 substs.push(Ty::Unknown); 347 substs.push(Ty::Unknown);
347 } 348 }
348 assert_eq!(substs.len(), parent_param_count + param_count); 349 assert_eq!(substs.len(), total_len);
349 350
350 // handle defaults 351 // handle defaults
351 if let Some(def_generic) = def_generic { 352 if let Some(def_generic) = def_generic {
@@ -369,11 +370,11 @@ impl TraitRef {
369 path: &Path, 370 path: &Path,
370 explicit_self_ty: Option<Ty>, 371 explicit_self_ty: Option<Ty>,
371 ) -> Option<Self> { 372 ) -> Option<Self> {
372 let resolved = match resolver.resolve_path_in_type_ns_fully(db, &path)? { 373 let resolved = match resolver.resolve_path_in_type_ns_fully(db, path.mod_path())? {
373 TypeNs::TraitId(tr) => tr, 374 TypeNs::TraitId(tr) => tr,
374 _ => return None, 375 _ => return None,
375 }; 376 };
376 let segment = path.segments.last().expect("path should have at least one segment"); 377 let segment = path.segments().last().expect("path should have at least one segment");
377 Some(TraitRef::from_resolved_path(db, resolver, resolved.into(), segment, explicit_self_ty)) 378 Some(TraitRef::from_resolved_path(db, resolver, resolved.into(), segment, explicit_self_ty))
378 } 379 }
379 380
@@ -381,7 +382,7 @@ impl TraitRef {
381 db: &impl HirDatabase, 382 db: &impl HirDatabase,
382 resolver: &Resolver, 383 resolver: &Resolver,
383 resolved: TraitId, 384 resolved: TraitId,
384 segment: &PathSegment, 385 segment: PathSegment<'_>,
385 explicit_self_ty: Option<Ty>, 386 explicit_self_ty: Option<Ty>,
386 ) -> Self { 387 ) -> Self {
387 let mut substs = TraitRef::substs_from_path(db, resolver, segment, resolved); 388 let mut substs = TraitRef::substs_from_path(db, resolver, segment, resolved);
@@ -407,7 +408,7 @@ impl TraitRef {
407 fn substs_from_path( 408 fn substs_from_path(
408 db: &impl HirDatabase, 409 db: &impl HirDatabase,
409 resolver: &Resolver, 410 resolver: &Resolver,
410 segment: &PathSegment, 411 segment: PathSegment<'_>,
411 resolved: TraitId, 412 resolved: TraitId,
412 ) -> Substs { 413 ) -> Substs {
413 let has_self_param = 414 let has_self_param =
@@ -461,12 +462,12 @@ fn assoc_type_bindings_from_type_bound<'a>(
461 trait_ref: TraitRef, 462 trait_ref: TraitRef,
462) -> impl Iterator<Item = GenericPredicate> + 'a { 463) -> impl Iterator<Item = GenericPredicate> + 'a {
463 let last_segment = match bound { 464 let last_segment = match bound {
464 TypeBound::Path(path) => path.segments.last(), 465 TypeBound::Path(path) => path.segments().last(),
465 TypeBound::Error => None, 466 TypeBound::Error => None,
466 }; 467 };
467 last_segment 468 last_segment
468 .into_iter() 469 .into_iter()
469 .flat_map(|segment| segment.args_and_bindings.iter()) 470 .flat_map(|segment| segment.args_and_bindings.into_iter())
470 .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) 471 .flat_map(|args_and_bindings| args_and_bindings.bindings.iter())
471 .map(move |(name, type_ref)| { 472 .map(move |(name, type_ref)| {
472 let associated_ty = 473 let associated_ty =
@@ -532,6 +533,15 @@ pub(crate) fn generic_predicates_for_param_query(
532 .collect() 533 .collect()
533} 534}
534 535
536pub(crate) fn generic_predicates_for_param_recover(
537 _db: &impl HirDatabase,
538 _cycle: &[String],
539 _def: &GenericDefId,
540 _param_idx: &u32,
541) -> Arc<[GenericPredicate]> {
542 Arc::new([])
543}
544
535impl TraitEnvironment { 545impl TraitEnvironment {
536 pub fn lower(db: &impl HirDatabase, resolver: &Resolver) -> Arc<TraitEnvironment> { 546 pub fn lower(db: &impl HirDatabase, resolver: &Resolver) -> Arc<TraitEnvironment> {
537 let predicates = resolver 547 let predicates = resolver
@@ -558,12 +568,11 @@ pub(crate) fn generic_predicates_query(
558/// Resolve the default type params from generics 568/// Resolve the default type params from generics
559pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDefId) -> Substs { 569pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDefId) -> Substs {
560 let resolver = def.resolver(db); 570 let resolver = def.resolver(db);
561 let generic_params = db.generic_params(def.into()); 571 let generic_params = generics(db, def.into());
562 572
563 let defaults = generic_params 573 let defaults = generic_params
564 .params_including_parent() 574 .iter()
565 .into_iter() 575 .map(|(_idx, p)| p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(db, &resolver, t)))
566 .map(|p| p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(db, &resolver, t)))
567 .collect(); 576 .collect();
568 577
569 Substs(defaults) 578 Substs(defaults)
@@ -580,7 +589,7 @@ fn fn_sig_for_fn(db: &impl HirDatabase, def: FunctionId) -> FnSig {
580/// Build the declared type of a function. This should not need to look at the 589/// Build the declared type of a function. This should not need to look at the
581/// function body. 590/// function body.
582fn type_for_fn(db: &impl HirDatabase, def: FunctionId) -> Ty { 591fn type_for_fn(db: &impl HirDatabase, def: FunctionId) -> Ty {
583 let generics = db.generic_params(def.into()); 592 let generics = generics(db, def.into());
584 let substs = Substs::identity(&generics); 593 let substs = Substs::identity(&generics);
585 Ty::apply(TypeCtor::FnDef(def.into()), substs) 594 Ty::apply(TypeCtor::FnDef(def.into()), substs)
586} 595}
@@ -630,7 +639,7 @@ fn type_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> Ty {
630 if struct_data.variant_data.is_unit() { 639 if struct_data.variant_data.is_unit() {
631 return type_for_adt(db, def.into()); // Unit struct 640 return type_for_adt(db, def.into()); // Unit struct
632 } 641 }
633 let generics = db.generic_params(def.into()); 642 let generics = generics(db, def.into());
634 let substs = Substs::identity(&generics); 643 let substs = Substs::identity(&generics);
635 Ty::apply(TypeCtor::FnDef(def.into()), substs) 644 Ty::apply(TypeCtor::FnDef(def.into()), substs)
636} 645}
@@ -644,7 +653,7 @@ fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId
644 .iter() 653 .iter()
645 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) 654 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref))
646 .collect::<Vec<_>>(); 655 .collect::<Vec<_>>();
647 let generics = db.generic_params(def.parent.into()); 656 let generics = generics(db, def.parent.into());
648 let substs = Substs::identity(&generics); 657 let substs = Substs::identity(&generics);
649 let ret = type_for_adt(db, def.parent.into()).subst(&substs); 658 let ret = type_for_adt(db, def.parent.into()).subst(&substs);
650 FnSig::from_params_and_return(params, ret) 659 FnSig::from_params_and_return(params, ret)
@@ -657,18 +666,18 @@ fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId)
657 if var_data.is_unit() { 666 if var_data.is_unit() {
658 return type_for_adt(db, def.parent.into()); // Unit variant 667 return type_for_adt(db, def.parent.into()); // Unit variant
659 } 668 }
660 let generics = db.generic_params(def.parent.into()); 669 let generics = generics(db, def.parent.into());
661 let substs = Substs::identity(&generics); 670 let substs = Substs::identity(&generics);
662 Ty::apply(TypeCtor::FnDef(EnumVariantId::from(def).into()), substs) 671 Ty::apply(TypeCtor::FnDef(EnumVariantId::from(def).into()), substs)
663} 672}
664 673
665fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Ty { 674fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Ty {
666 let generics = db.generic_params(adt.into()); 675 let generics = generics(db, adt.into());
667 Ty::apply(TypeCtor::Adt(adt), Substs::identity(&generics)) 676 Ty::apply(TypeCtor::Adt(adt), Substs::identity(&generics))
668} 677}
669 678
670fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Ty { 679fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Ty {
671 let generics = db.generic_params(t.into()); 680 let generics = generics(db, t.into());
672 let resolver = t.resolver(db); 681 let resolver = t.resolver(db);
673 let type_ref = &db.type_alias_data(t).type_ref; 682 let type_ref = &db.type_alias_data(t).type_ref;
674 let substs = Substs::identity(&generics); 683 let substs = Substs::identity(&generics);
@@ -687,10 +696,11 @@ impl_froms!(CallableDef: FunctionId, StructId, EnumVariantId);
687impl CallableDef { 696impl CallableDef {
688 pub fn krate(self, db: &impl HirDatabase) -> CrateId { 697 pub fn krate(self, db: &impl HirDatabase) -> CrateId {
689 match self { 698 match self {
690 CallableDef::FunctionId(f) => f.lookup(db).module(db).krate, 699 CallableDef::FunctionId(f) => f.lookup(db).module(db),
691 CallableDef::StructId(s) => s.module(db).krate, 700 CallableDef::StructId(s) => s.lookup(db).container.module(db),
692 CallableDef::EnumVariantId(e) => e.parent.module(db).krate, 701 CallableDef::EnumVariantId(e) => e.parent.lookup(db).container.module(db),
693 } 702 }
703 .krate
694 } 704 }
695} 705}
696 706
@@ -733,6 +743,11 @@ pub(crate) fn ty_query(db: &impl HirDatabase, def: TyDefId) -> Ty {
733 TyDefId::TypeAliasId(it) => type_for_type_alias(db, it), 743 TyDefId::TypeAliasId(it) => type_for_type_alias(db, it),
734 } 744 }
735} 745}
746
747pub(crate) fn ty_recover(_db: &impl HirDatabase, _cycle: &[String], _def: &TyDefId) -> Ty {
748 Ty::Unknown
749}
750
736pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty { 751pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty {
737 match def { 752 match def {
738 ValueTyDefId::FunctionId(it) => type_for_fn(db, it), 753 ValueTyDefId::FunctionId(it) => type_for_fn(db, it),
@@ -743,17 +758,24 @@ pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty {
743 } 758 }
744} 759}
745 760
746pub(crate) fn impl_ty_query(db: &impl HirDatabase, impl_id: ImplId) -> ImplTy { 761pub(crate) fn impl_self_ty_query(db: &impl HirDatabase, impl_id: ImplId) -> Ty {
747 let impl_data = db.impl_data(impl_id); 762 let impl_data = db.impl_data(impl_id);
748 let resolver = impl_id.resolver(db); 763 let resolver = impl_id.resolver(db);
749 let self_ty = Ty::from_hir(db, &resolver, &impl_data.target_type); 764 Ty::from_hir(db, &resolver, &impl_data.target_type)
750 match impl_data.target_trait.as_ref() { 765}
751 Some(trait_ref) => { 766
752 match TraitRef::from_hir(db, &resolver, trait_ref, Some(self_ty.clone())) { 767pub(crate) fn impl_self_ty_recover(
753 Some(it) => ImplTy::TraitRef(it), 768 _db: &impl HirDatabase,
754 None => ImplTy::Inherent(self_ty), 769 _cycle: &[String],
755 } 770 _impl_id: &ImplId,
756 } 771) -> Ty {
757 None => ImplTy::Inherent(self_ty), 772 Ty::Unknown
758 } 773}
774
775pub(crate) fn impl_trait_query(db: &impl HirDatabase, impl_id: ImplId) -> Option<TraitRef> {
776 let impl_data = db.impl_data(impl_id);
777 let resolver = impl_id.resolver(db);
778 let self_ty = db.impl_self_ty(impl_id);
779 let target_trait = impl_data.target_trait.as_ref()?;
780 TraitRef::from_hir(db, &resolver, target_trait, Some(self_ty.clone()))
759} 781}
diff --git a/crates/ra_hir_ty/src/marks.rs b/crates/ra_hir_ty/src/marks.rs
index 0f754eb9c..fe74acf11 100644
--- a/crates/ra_hir_ty/src/marks.rs
+++ b/crates/ra_hir_ty/src/marks.rs
@@ -6,4 +6,5 @@ test_utils::marks!(
6 type_var_resolves_to_int_var 6 type_var_resolves_to_int_var
7 match_ergonomics_ref 7 match_ergonomics_ref
8 coerce_merge_fail_fallback 8 coerce_merge_fail_fallback
9 insert_vars_for_impl_trait
9); 10);
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index ee1936b0e..888dc3116 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -6,20 +6,21 @@ use std::sync::Arc;
6 6
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use hir_def::{ 8use hir_def::{
9 lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocItemId, AstItemDef, 9 lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocContainerId,
10 FunctionId, HasModule, ImplId, TraitId, 10 AssocItemId, FunctionId, HasModule, ImplId, Lookup, TraitId,
11}; 11};
12use hir_expand::name::Name; 12use hir_expand::name::Name;
13use ra_db::CrateId; 13use ra_db::CrateId;
14use ra_prof::profile; 14use ra_prof::profile;
15use rustc_hash::FxHashMap; 15use rustc_hash::FxHashMap;
16 16
17use super::Substs;
17use crate::{ 18use crate::{
18 autoderef, 19 autoderef,
19 db::HirDatabase, 20 db::HirDatabase,
20 primitive::{FloatBitness, Uncertain}, 21 primitive::{FloatBitness, Uncertain},
21 utils::all_super_traits, 22 utils::all_super_traits,
22 Canonical, ImplTy, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor, 23 Canonical, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk,
23}; 24};
24 25
25/// This is used as a key for indexing impls. 26/// This is used as a key for indexing impls.
@@ -57,12 +58,13 @@ impl CrateImplBlocks {
57 58
58 let crate_def_map = db.crate_def_map(krate); 59 let crate_def_map = db.crate_def_map(krate);
59 for (_module_id, module_data) in crate_def_map.modules.iter() { 60 for (_module_id, module_data) in crate_def_map.modules.iter() {
60 for &impl_id in module_data.impls.iter() { 61 for impl_id in module_data.scope.impls() {
61 match db.impl_ty(impl_id) { 62 match db.impl_trait(impl_id) {
62 ImplTy::TraitRef(tr) => { 63 Some(tr) => {
63 res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id); 64 res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id);
64 } 65 }
65 ImplTy::Inherent(self_ty) => { 66 None => {
67 let self_ty = db.impl_self_ty(impl_id);
66 if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty) { 68 if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty) {
67 res.impls.entry(self_ty_fp).or_default().push(impl_id); 69 res.impls.entry(self_ty_fp).or_default().push(impl_id);
68 } 70 }
@@ -132,7 +134,7 @@ impl Ty {
132 LangItemTarget::ImplBlockId(it) => Some(it), 134 LangItemTarget::ImplBlockId(it) => Some(it),
133 _ => None, 135 _ => None,
134 }) 136 })
135 .map(|it| it.module(db).krate) 137 .map(|it| it.lookup(db).container.module(db).krate)
136 .collect(); 138 .collect();
137 Some(res) 139 Some(res)
138 } 140 }
@@ -175,7 +177,6 @@ pub fn iterate_method_candidates<T>(
175 mode: LookupMode, 177 mode: LookupMode,
176 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, 178 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
177) -> Option<T> { 179) -> Option<T> {
178 let krate = resolver.krate()?;
179 match mode { 180 match mode {
180 LookupMode::MethodCall => { 181 LookupMode::MethodCall => {
181 // For method calls, rust first does any number of autoderef, and then one 182 // For method calls, rust first does any number of autoderef, and then one
@@ -188,57 +189,159 @@ pub fn iterate_method_candidates<T>(
188 // rustc does an autoderef and then autoref again). 189 // rustc does an autoderef and then autoref again).
189 let environment = TraitEnvironment::lower(db, resolver); 190 let environment = TraitEnvironment::lower(db, resolver);
190 let ty = InEnvironment { value: ty.clone(), environment }; 191 let ty = InEnvironment { value: ty.clone(), environment };
191 for derefed_ty in autoderef::autoderef(db, resolver.krate(), ty) { 192 let krate = resolver.krate()?;
192 if let Some(result) = 193
193 iterate_inherent_methods(&derefed_ty, db, name, mode, krate, &mut callback) 194 // We have to be careful about the order we're looking at candidates
194 { 195 // in here. Consider the case where we're resolving `x.clone()`
195 return Some(result); 196 // where `x: &Vec<_>`. This resolves to the clone method with self
196 } 197 // type `Vec<_>`, *not* `&_`. I.e. we need to consider methods where
197 if let Some(result) = iterate_trait_method_candidates( 198 // the receiver type exactly matches before cases where we have to
198 &derefed_ty, 199 // do autoref. But in the autoderef steps, the `&_` self type comes
200 // up *before* the `Vec<_>` self type.
201 //
202 // On the other hand, we don't want to just pick any by-value method
203 // before any by-autoref method; it's just that we need to consider
204 // the methods by autoderef order of *receiver types*, not *self
205 // types*.
206
207 let deref_chain: Vec<_> = autoderef::autoderef(db, Some(krate), ty.clone()).collect();
208 for i in 0..deref_chain.len() {
209 if let Some(result) = iterate_method_candidates_with_autoref(
210 &deref_chain[i..],
199 db, 211 db,
200 resolver, 212 resolver,
201 name, 213 name,
202 mode,
203 &mut callback, 214 &mut callback,
204 ) { 215 ) {
205 return Some(result); 216 return Some(result);
206 } 217 }
207 } 218 }
219 None
208 } 220 }
209 LookupMode::Path => { 221 LookupMode::Path => {
210 // No autoderef for path lookups 222 // No autoderef for path lookups
211 if let Some(result) = 223 iterate_method_candidates_for_self_ty(&ty, db, resolver, name, &mut callback)
212 iterate_inherent_methods(&ty, db, name, mode, krate.into(), &mut callback) 224 }
213 { 225 }
214 return Some(result); 226}
215 } 227
216 if let Some(result) = 228fn iterate_method_candidates_with_autoref<T>(
217 iterate_trait_method_candidates(&ty, db, resolver, name, mode, &mut callback) 229 deref_chain: &[Canonical<Ty>],
218 { 230 db: &impl HirDatabase,
219 return Some(result); 231 resolver: &Resolver,
220 } 232 name: Option<&Name>,
233 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
234) -> Option<T> {
235 if let Some(result) = iterate_method_candidates_by_receiver(
236 &deref_chain[0],
237 &deref_chain[1..],
238 db,
239 resolver,
240 name,
241 &mut callback,
242 ) {
243 return Some(result);
244 }
245 let refed = Canonical {
246 num_vars: deref_chain[0].num_vars,
247 value: Ty::apply_one(TypeCtor::Ref(Mutability::Shared), deref_chain[0].value.clone()),
248 };
249 if let Some(result) = iterate_method_candidates_by_receiver(
250 &refed,
251 deref_chain,
252 db,
253 resolver,
254 name,
255 &mut callback,
256 ) {
257 return Some(result);
258 }
259 let ref_muted = Canonical {
260 num_vars: deref_chain[0].num_vars,
261 value: Ty::apply_one(TypeCtor::Ref(Mutability::Mut), deref_chain[0].value.clone()),
262 };
263 if let Some(result) = iterate_method_candidates_by_receiver(
264 &ref_muted,
265 deref_chain,
266 db,
267 resolver,
268 name,
269 &mut callback,
270 ) {
271 return Some(result);
272 }
273 None
274}
275
276fn iterate_method_candidates_by_receiver<T>(
277 receiver_ty: &Canonical<Ty>,
278 rest_of_deref_chain: &[Canonical<Ty>],
279 db: &impl HirDatabase,
280 resolver: &Resolver,
281 name: Option<&Name>,
282 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
283) -> Option<T> {
284 // We're looking for methods with *receiver* type receiver_ty. These could
285 // be found in any of the derefs of receiver_ty, so we have to go through
286 // that.
287 let krate = resolver.krate()?;
288 for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) {
289 if let Some(result) =
290 iterate_inherent_methods(self_ty, db, name, Some(receiver_ty), krate, &mut callback)
291 {
292 return Some(result);
293 }
294 }
295 for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) {
296 if let Some(result) = iterate_trait_method_candidates(
297 self_ty,
298 db,
299 resolver,
300 name,
301 Some(receiver_ty),
302 &mut callback,
303 ) {
304 return Some(result);
221 } 305 }
222 } 306 }
223 None 307 None
224} 308}
225 309
310fn iterate_method_candidates_for_self_ty<T>(
311 self_ty: &Canonical<Ty>,
312 db: &impl HirDatabase,
313 resolver: &Resolver,
314 name: Option<&Name>,
315 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
316) -> Option<T> {
317 let krate = resolver.krate()?;
318 if let Some(result) = iterate_inherent_methods(self_ty, db, name, None, krate, &mut callback) {
319 return Some(result);
320 }
321 if let Some(result) =
322 iterate_trait_method_candidates(self_ty, db, resolver, name, None, &mut callback)
323 {
324 return Some(result);
325 }
326 None
327}
328
226fn iterate_trait_method_candidates<T>( 329fn iterate_trait_method_candidates<T>(
227 ty: &Canonical<Ty>, 330 self_ty: &Canonical<Ty>,
228 db: &impl HirDatabase, 331 db: &impl HirDatabase,
229 resolver: &Resolver, 332 resolver: &Resolver,
230 name: Option<&Name>, 333 name: Option<&Name>,
231 mode: LookupMode, 334 receiver_ty: Option<&Canonical<Ty>>,
232 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, 335 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
233) -> Option<T> { 336) -> Option<T> {
234 let krate = resolver.krate()?; 337 let krate = resolver.krate()?;
235 // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that) 338 // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that)
236 let env = TraitEnvironment::lower(db, resolver); 339 let env = TraitEnvironment::lower(db, resolver);
237 // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope 340 // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope
238 let inherent_trait = ty.value.inherent_trait().into_iter(); 341 let inherent_trait = self_ty.value.inherent_trait().into_iter();
239 // if we have `T: Trait` in the param env, the trait doesn't need to be in scope 342 // if we have `T: Trait` in the param env, the trait doesn't need to be in scope
240 let traits_from_env = env 343 let traits_from_env = env
241 .trait_predicates_for_self_ty(&ty.value) 344 .trait_predicates_for_self_ty(&self_ty.value)
242 .map(|tr| tr.trait_) 345 .map(|tr| tr.trait_)
243 .flat_map(|t| all_super_traits(db, t)); 346 .flat_map(|t| all_super_traits(db, t));
244 let traits = 347 let traits =
@@ -251,17 +354,17 @@ fn iterate_trait_method_candidates<T>(
251 // iteration 354 // iteration
252 let mut known_implemented = false; 355 let mut known_implemented = false;
253 for (_name, item) in data.items.iter() { 356 for (_name, item) in data.items.iter() {
254 if !is_valid_candidate(db, name, mode, (*item).into()) { 357 if !is_valid_candidate(db, name, receiver_ty, (*item).into(), self_ty) {
255 continue; 358 continue;
256 } 359 }
257 if !known_implemented { 360 if !known_implemented {
258 let goal = generic_implements_goal(db, env.clone(), t, ty.clone()); 361 let goal = generic_implements_goal(db, env.clone(), t, self_ty.clone());
259 if db.trait_solve(krate.into(), goal).is_none() { 362 if db.trait_solve(krate.into(), goal).is_none() {
260 continue 'traits; 363 continue 'traits;
261 } 364 }
262 } 365 }
263 known_implemented = true; 366 known_implemented = true;
264 if let Some(result) = callback(&ty.value, (*item).into()) { 367 if let Some(result) = callback(&self_ty.value, (*item).into()) {
265 return Some(result); 368 return Some(result);
266 } 369 }
267 } 370 }
@@ -270,22 +373,22 @@ fn iterate_trait_method_candidates<T>(
270} 373}
271 374
272fn iterate_inherent_methods<T>( 375fn iterate_inherent_methods<T>(
273 ty: &Canonical<Ty>, 376 self_ty: &Canonical<Ty>,
274 db: &impl HirDatabase, 377 db: &impl HirDatabase,
275 name: Option<&Name>, 378 name: Option<&Name>,
276 mode: LookupMode, 379 receiver_ty: Option<&Canonical<Ty>>,
277 krate: CrateId, 380 krate: CrateId,
278 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, 381 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
279) -> Option<T> { 382) -> Option<T> {
280 for krate in ty.value.def_crates(db, krate)? { 383 for krate in self_ty.value.def_crates(db, krate)? {
281 let impls = db.impls_in_crate(krate); 384 let impls = db.impls_in_crate(krate);
282 385
283 for impl_block in impls.lookup_impl_blocks(&ty.value) { 386 for impl_block in impls.lookup_impl_blocks(&self_ty.value) {
284 for &item in db.impl_data(impl_block).items.iter() { 387 for &item in db.impl_data(impl_block).items.iter() {
285 if !is_valid_candidate(db, name, mode, item) { 388 if !is_valid_candidate(db, name, receiver_ty, item, self_ty) {
286 continue; 389 continue;
287 } 390 }
288 if let Some(result) = callback(&ty.value, item.into()) { 391 if let Some(result) = callback(&self_ty.value, item) {
289 return Some(result); 392 return Some(result);
290 } 393 }
291 } 394 }
@@ -297,23 +400,68 @@ fn iterate_inherent_methods<T>(
297fn is_valid_candidate( 400fn is_valid_candidate(
298 db: &impl HirDatabase, 401 db: &impl HirDatabase,
299 name: Option<&Name>, 402 name: Option<&Name>,
300 mode: LookupMode, 403 receiver_ty: Option<&Canonical<Ty>>,
301 item: AssocItemId, 404 item: AssocItemId,
405 self_ty: &Canonical<Ty>,
302) -> bool { 406) -> bool {
303 match item { 407 match item {
304 AssocItemId::FunctionId(m) => { 408 AssocItemId::FunctionId(m) => {
305 let data = db.function_data(m); 409 let data = db.function_data(m);
306 name.map_or(true, |name| &data.name == name) 410 if let Some(name) = name {
307 && (data.has_self_param || mode == LookupMode::Path) 411 if &data.name != name {
412 return false;
413 }
414 }
415 if let Some(receiver_ty) = receiver_ty {
416 if !data.has_self_param {
417 return false;
418 }
419 let transformed_receiver_ty = match transform_receiver_ty(db, m, self_ty) {
420 Some(ty) => ty,
421 None => return false,
422 };
423 if transformed_receiver_ty != receiver_ty.value {
424 return false;
425 }
426 }
427 true
308 } 428 }
309 AssocItemId::ConstId(c) => { 429 AssocItemId::ConstId(c) => {
310 let data = db.const_data(c); 430 let data = db.const_data(c);
311 name.map_or(true, |name| data.name.as_ref() == Some(name)) && (mode == LookupMode::Path) 431 name.map_or(true, |name| data.name.as_ref() == Some(name)) && receiver_ty.is_none()
312 } 432 }
313 _ => false, 433 _ => false,
314 } 434 }
315} 435}
316 436
437pub(crate) fn inherent_impl_substs(
438 db: &impl HirDatabase,
439 impl_id: ImplId,
440 self_ty: &Canonical<Ty>,
441) -> Option<Substs> {
442 let vars = Substs::build_for_def(db, impl_id).fill_with_bound_vars(0).build();
443 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars);
444 let self_ty_with_vars = Canonical { num_vars: vars.len(), value: self_ty_with_vars };
445 super::infer::unify(&self_ty_with_vars, self_ty)
446}
447
448fn transform_receiver_ty(
449 db: &impl HirDatabase,
450 function_id: FunctionId,
451 self_ty: &Canonical<Ty>,
452) -> Option<Ty> {
453 let substs = match function_id.lookup(db).container {
454 AssocContainerId::TraitId(_) => Substs::build_for_def(db, function_id)
455 .push(self_ty.value.clone())
456 .fill_with_unknown()
457 .build(),
458 AssocContainerId::ImplId(impl_id) => inherent_impl_substs(db, impl_id, &self_ty)?,
459 AssocContainerId::ContainerId(_) => unreachable!(),
460 };
461 let sig = db.callable_item_signature(function_id.into());
462 Some(sig.params()[0].clone().subst(&substs))
463}
464
317pub fn implements_trait( 465pub fn implements_trait(
318 ty: &Canonical<Ty>, 466 ty: &Canonical<Ty>,
319 db: &impl HirDatabase, 467 db: &impl HirDatabase,
diff --git a/crates/ra_hir_ty/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs
index 1dc9793f9..1a31b587b 100644
--- a/crates/ra_hir_ty/src/test_db.rs
+++ b/crates/ra_hir_ty/src/test_db.rs
@@ -74,7 +74,7 @@ impl TestDB {
74 for &krate in self.relevant_crates(file_id).iter() { 74 for &krate in self.relevant_crates(file_id).iter() {
75 let crate_def_map = self.crate_def_map(krate); 75 let crate_def_map = self.crate_def_map(krate);
76 for (local_id, data) in crate_def_map.modules.iter() { 76 for (local_id, data) in crate_def_map.modules.iter() {
77 if data.definition == Some(file_id) { 77 if data.origin.file_id() == Some(file_id) {
78 return ModuleId { krate, local_id }; 78 return ModuleId { krate, local_id };
79 } 79 }
80 } 80 }
@@ -98,7 +98,7 @@ impl TestDB {
98 } 98 }
99 } 99 }
100 100
101 for &impl_id in crate_def_map[module_id].impls.iter() { 101 for impl_id in crate_def_map[module_id].scope.impls() {
102 let impl_data = self.impl_data(impl_id); 102 let impl_data = self.impl_data(impl_id);
103 for item in impl_data.items.iter() { 103 for item in impl_data.items.iter() {
104 if let AssocItemId::FunctionId(f) = item { 104 if let AssocItemId::FunctionId(f) = item {
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs
index c8461b447..d447b4571 100644
--- a/crates/ra_hir_ty/src/tests.rs
+++ b/crates/ra_hir_ty/src/tests.rs
@@ -1,21 +1,26 @@
1mod never_type; 1mod never_type;
2mod coercion; 2mod coercion;
3mod regression;
4mod simple;
5mod patterns;
6mod traits;
7mod method_resolution;
8mod macros;
3 9
4use std::fmt::Write; 10use std::fmt::Write;
5use std::sync::Arc; 11use std::sync::Arc;
6 12
7use hir_def::{ 13use hir_def::{
8 body::BodySourceMap, db::DefDatabase, nameres::CrateDefMap, AssocItemId, DefWithBodyId, 14 body::BodySourceMap, child_by_source::ChildBySource, db::DefDatabase, keys,
9 LocalModuleId, Lookup, ModuleDefId, 15 nameres::CrateDefMap, AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId,
10}; 16};
11use hir_expand::Source; 17use hir_expand::InFile;
12use insta::assert_snapshot; 18use insta::assert_snapshot;
13use ra_db::{fixture::WithFixture, salsa::Database, FilePosition, SourceDatabase}; 19use ra_db::{fixture::WithFixture, salsa::Database, FilePosition, SourceDatabase};
14use ra_syntax::{ 20use ra_syntax::{
15 algo, 21 algo,
16 ast::{self, AstNode}, 22 ast::{self, AstNode},
17}; 23};
18use test_utils::covers;
19 24
20use crate::{db::HirDatabase, display::HirDisplay, test_db::TestDB, InferenceResult}; 25use crate::{db::HirDatabase, display::HirDisplay, test_db::TestDB, InferenceResult};
21 26
@@ -23,4669 +28,20 @@ use crate::{db::HirDatabase, display::HirDisplay, test_db::TestDB, InferenceResu
23// against snapshots of the expected results using insta. Use cargo-insta to 28// against snapshots of the expected results using insta. Use cargo-insta to
24// update the snapshots. 29// update the snapshots.
25 30
26#[test]
27fn cfg_impl_block() {
28 let (db, pos) = TestDB::with_position(
29 r#"
30//- /main.rs crate:main deps:foo cfg:test
31use foo::S as T;
32struct S;
33
34#[cfg(test)]
35impl S {
36 fn foo1(&self) -> i32 { 0 }
37}
38
39#[cfg(not(test))]
40impl S {
41 fn foo2(&self) -> i32 { 0 }
42}
43
44fn test() {
45 let t = (S.foo1(), S.foo2(), T.foo3(), T.foo4());
46 t<|>;
47}
48
49//- /foo.rs crate:foo
50struct S;
51
52#[cfg(not(test))]
53impl S {
54 fn foo3(&self) -> i32 { 0 }
55}
56
57#[cfg(test)]
58impl S {
59 fn foo4(&self) -> i32 { 0 }
60}
61"#,
62 );
63 assert_eq!("(i32, {unknown}, i32, {unknown})", type_at_pos(&db, pos));
64}
65
66#[test]
67fn infer_await() {
68 let (db, pos) = TestDB::with_position(
69 r#"
70//- /main.rs crate:main deps:std
71
72struct IntFuture;
73
74impl Future for IntFuture {
75 type Output = u64;
76}
77
78fn test() {
79 let r = IntFuture;
80 let v = r.await;
81 v<|>;
82}
83
84//- /std.rs crate:std
85#[prelude_import] use future::*;
86mod future {
87 trait Future {
88 type Output;
89 }
90}
91
92"#,
93 );
94 assert_eq!("u64", type_at_pos(&db, pos));
95}
96
97#[test]
98fn infer_box() {
99 let (db, pos) = TestDB::with_position(
100 r#"
101//- /main.rs crate:main deps:std
102
103fn test() {
104 let x = box 1;
105 let t = (x, box x, box &1, box [1]);
106 t<|>;
107}
108
109//- /std.rs crate:std
110#[prelude_import] use prelude::*;
111mod prelude {}
112
113mod boxed {
114 pub struct Box<T: ?Sized> {
115 inner: *mut T,
116 }
117}
118
119"#,
120 );
121 assert_eq!("(Box<i32>, Box<Box<i32>>, Box<&i32>, Box<[i32;_]>)", type_at_pos(&db, pos));
122}
123
124#[test]
125fn infer_adt_self() {
126 let (db, pos) = TestDB::with_position(
127 r#"
128//- /main.rs
129enum Nat { Succ(Self), Demo(Nat), Zero }
130
131fn test() {
132 let foo: Nat = Nat::Zero;
133 if let Nat::Succ(x) = foo {
134 x<|>
135 }
136}
137
138"#,
139 );
140 assert_eq!("Nat", type_at_pos(&db, pos));
141}
142
143#[test]
144fn infer_try() {
145 let (db, pos) = TestDB::with_position(
146 r#"
147//- /main.rs crate:main deps:std
148
149fn test() {
150 let r: Result<i32, u64> = Result::Ok(1);
151 let v = r?;
152 v<|>;
153}
154
155//- /std.rs crate:std
156
157#[prelude_import] use ops::*;
158mod ops {
159 trait Try {
160 type Ok;
161 type Error;
162 }
163}
164
165#[prelude_import] use result::*;
166mod result {
167 enum Result<O, E> {
168 Ok(O),
169 Err(E)
170 }
171
172 impl<O, E> crate::ops::Try for Result<O, E> {
173 type Ok = O;
174 type Error = E;
175 }
176}
177
178"#,
179 );
180 assert_eq!("i32", type_at_pos(&db, pos));
181}
182
183#[test]
184fn infer_for_loop() {
185 let (db, pos) = TestDB::with_position(
186 r#"
187//- /main.rs crate:main deps:std
188
189use std::collections::Vec;
190
191fn test() {
192 let v = Vec::new();
193 v.push("foo");
194 for x in v {
195 x<|>;
196 }
197}
198
199//- /std.rs crate:std
200
201#[prelude_import] use iter::*;
202mod iter {
203 trait IntoIterator {
204 type Item;
205 }
206}
207
208mod collections {
209 struct Vec<T> {}
210 impl<T> Vec<T> {
211 fn new() -> Self { Vec {} }
212 fn push(&mut self, t: T) { }
213 }
214
215 impl<T> crate::iter::IntoIterator for Vec<T> {
216 type Item=T;
217 }
218}
219"#,
220 );
221 assert_eq!("&str", type_at_pos(&db, pos));
222}
223
224#[test]
225fn infer_while_let() {
226 let (db, pos) = TestDB::with_position(
227 r#"
228//- /main.rs
229enum Option<T> { Some(T), None }
230
231fn test() {
232 let foo: Option<f32> = None;
233 while let Option::Some(x) = foo {
234 <|>x
235 }
236}
237
238"#,
239 );
240 assert_eq!("f32", type_at_pos(&db, pos));
241}
242
243#[test]
244fn infer_basics() {
245 assert_snapshot!(
246 infer(r#"
247fn test(a: u32, b: isize, c: !, d: &str) {
248 a;
249 b;
250 c;
251 d;
252 1usize;
253 1isize;
254 "test";
255 1.0f32;
256}"#),
257 @r###"
258 [9; 10) 'a': u32
259 [17; 18) 'b': isize
260 [27; 28) 'c': !
261 [33; 34) 'd': &str
262 [42; 121) '{ ...f32; }': !
263 [48; 49) 'a': u32
264 [55; 56) 'b': isize
265 [62; 63) 'c': !
266 [69; 70) 'd': &str
267 [76; 82) '1usize': usize
268 [88; 94) '1isize': isize
269 [100; 106) '"test"': &str
270 [112; 118) '1.0f32': f32
271 "###
272 );
273}
274
275#[test]
276fn infer_let() {
277 assert_snapshot!(
278 infer(r#"
279fn test() {
280 let a = 1isize;
281 let b: usize = 1;
282 let c = b;
283 let d: u32;
284 let e;
285 let f: i32 = e;
286}
287"#),
288 @r###"
289 [11; 118) '{ ...= e; }': ()
290 [21; 22) 'a': isize
291 [25; 31) '1isize': isize
292 [41; 42) 'b': usize
293 [52; 53) '1': usize
294 [63; 64) 'c': usize
295 [67; 68) 'b': usize
296 [78; 79) 'd': u32
297 [94; 95) 'e': i32
298 [105; 106) 'f': i32
299 [114; 115) 'e': i32
300 "###
301 );
302}
303
304#[test]
305fn infer_paths() {
306 assert_snapshot!(
307 infer(r#"
308fn a() -> u32 { 1 }
309
310mod b {
311 fn c() -> u32 { 1 }
312}
313
314fn test() {
315 a();
316 b::c();
317}
318"#),
319 @r###"
320 [15; 20) '{ 1 }': u32
321 [17; 18) '1': u32
322 [48; 53) '{ 1 }': u32
323 [50; 51) '1': u32
324 [67; 91) '{ ...c(); }': ()
325 [73; 74) 'a': fn a() -> u32
326 [73; 76) 'a()': u32
327 [82; 86) 'b::c': fn c() -> u32
328 [82; 88) 'b::c()': u32
329 "###
330 );
331}
332
333#[test]
334fn infer_path_type() {
335 assert_snapshot!(
336 infer(r#"
337struct S;
338
339impl S {
340 fn foo() -> i32 { 1 }
341}
342
343fn test() {
344 S::foo();
345 <S>::foo();
346}
347"#),
348 @r###"
349 [41; 46) '{ 1 }': i32
350 [43; 44) '1': i32
351 [60; 93) '{ ...o(); }': ()
352 [66; 72) 'S::foo': fn foo() -> i32
353 [66; 74) 'S::foo()': i32
354 [80; 88) '<S>::foo': fn foo() -> i32
355 [80; 90) '<S>::foo()': i32
356 "###
357 );
358}
359
360#[test]
361fn infer_slice_method() {
362 assert_snapshot!(
363 infer(r#"
364#[lang = "slice"]
365impl<T> [T] {
366 fn foo(&self) -> T {
367 loop {}
368 }
369}
370
371#[lang = "slice_alloc"]
372impl<T> [T] {}
373
374fn test() {
375 <[_]>::foo(b"foo");
376}
377"#),
378 @r###"
379 [45; 49) 'self': &[T]
380 [56; 79) '{ ... }': T
381 [66; 73) 'loop {}': !
382 [71; 73) '{}': ()
383 [133; 160) '{ ...o"); }': ()
384 [139; 149) '<[_]>::foo': fn foo<u8>(&[T]) -> T
385 [139; 157) '<[_]>:..."foo")': u8
386 [150; 156) 'b"foo"': &[u8]
387 "###
388 );
389}
390
391#[test]
392fn infer_struct() {
393 assert_snapshot!(
394 infer(r#"
395struct A {
396 b: B,
397 c: C,
398}
399struct B;
400struct C(usize);
401
402fn test() {
403 let c = C(1);
404 B;
405 let a: A = A { b: B, c: C(1) };
406 a.b;
407 a.c;
408}
409"#),
410 @r###"
411 [72; 154) '{ ...a.c; }': ()
412 [82; 83) 'c': C
413 [86; 87) 'C': C(usize) -> C
414 [86; 90) 'C(1)': C
415 [88; 89) '1': usize
416 [96; 97) 'B': B
417 [107; 108) 'a': A
418 [114; 133) 'A { b:...C(1) }': A
419 [121; 122) 'B': B
420 [127; 128) 'C': C(usize) -> C
421 [127; 131) 'C(1)': C
422 [129; 130) '1': usize
423 [139; 140) 'a': A
424 [139; 142) 'a.b': B
425 [148; 149) 'a': A
426 [148; 151) 'a.c': C
427 "###
428 );
429}
430
431#[test]
432fn infer_enum() {
433 assert_snapshot!(
434 infer(r#"
435enum E {
436 V1 { field: u32 },
437 V2
438}
439fn test() {
440 E::V1 { field: 1 };
441 E::V2;
442}"#),
443 @r###"
444 [48; 82) '{ E:...:V2; }': ()
445 [52; 70) 'E::V1 ...d: 1 }': E
446 [67; 68) '1': u32
447 [74; 79) 'E::V2': E
448 "###
449 );
450}
451
452#[test]
453fn infer_refs() {
454 assert_snapshot!(
455 infer(r#"
456fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) {
457 a;
458 *a;
459 &a;
460 &mut a;
461 b;
462 *b;
463 &b;
464 c;
465 *c;
466 d;
467 *d;
468}
469"#),
470 @r###"
471 [9; 10) 'a': &u32
472 [18; 19) 'b': &mut u32
473 [31; 32) 'c': *const u32
474 [46; 47) 'd': *mut u32
475 [59; 150) '{ ... *d; }': ()
476 [65; 66) 'a': &u32
477 [72; 74) '*a': u32
478 [73; 74) 'a': &u32
479 [80; 82) '&a': &&u32
480 [81; 82) 'a': &u32
481 [88; 94) '&mut a': &mut &u32
482 [93; 94) 'a': &u32
483 [100; 101) 'b': &mut u32
484 [107; 109) '*b': u32
485 [108; 109) 'b': &mut u32
486 [115; 117) '&b': &&mut u32
487 [116; 117) 'b': &mut u32
488 [123; 124) 'c': *const u32
489 [130; 132) '*c': u32
490 [131; 132) 'c': *const u32
491 [138; 139) 'd': *mut u32
492 [145; 147) '*d': u32
493 [146; 147) 'd': *mut u32
494 "###
495 );
496}
497
498#[test]
499fn infer_literals() {
500 assert_snapshot!(
501 infer(r##"
502fn test() {
503 5i32;
504 5f32;
505 5f64;
506 "hello";
507 b"bytes";
508 'c';
509 b'b';
510 3.14;
511 5000;
512 false;
513 true;
514 r#"
515 //! doc
516 // non-doc
517 mod foo {}
518 "#;
519 br#"yolo"#;
520}
521"##),
522 @r###"
523 [11; 221) '{ ...o"#; }': ()
524 [17; 21) '5i32': i32
525 [27; 31) '5f32': f32
526 [37; 41) '5f64': f64
527 [47; 54) '"hello"': &str
528 [60; 68) 'b"bytes"': &[u8]
529 [74; 77) ''c'': char
530 [83; 87) 'b'b'': u8
531 [93; 97) '3.14': f64
532 [103; 107) '5000': i32
533 [113; 118) 'false': bool
534 [124; 128) 'true': bool
535 [134; 202) 'r#" ... "#': &str
536 [208; 218) 'br#"yolo"#': &[u8]
537 "###
538 );
539}
540
541#[test]
542fn infer_unary_op() {
543 assert_snapshot!(
544 infer(r#"
545enum SomeType {}
546
547fn test(x: SomeType) {
548 let b = false;
549 let c = !b;
550 let a = 100;
551 let d: i128 = -a;
552 let e = -100;
553 let f = !!!true;
554 let g = !42;
555 let h = !10u32;
556 let j = !a;
557 -3.14;
558 !3;
559 -x;
560 !x;
561 -"hello";
562 !"hello";
563}
564"#),
565 @r###"
566 [27; 28) 'x': SomeType
567 [40; 272) '{ ...lo"; }': ()
568 [50; 51) 'b': bool
569 [54; 59) 'false': bool
570 [69; 70) 'c': bool
571 [73; 75) '!b': bool
572 [74; 75) 'b': bool
573 [85; 86) 'a': i128
574 [89; 92) '100': i128
575 [102; 103) 'd': i128
576 [112; 114) '-a': i128
577 [113; 114) 'a': i128
578 [124; 125) 'e': i32
579 [128; 132) '-100': i32
580 [129; 132) '100': i32
581 [142; 143) 'f': bool
582 [146; 153) '!!!true': bool
583 [147; 153) '!!true': bool
584 [148; 153) '!true': bool
585 [149; 153) 'true': bool
586 [163; 164) 'g': i32
587 [167; 170) '!42': i32
588 [168; 170) '42': i32
589 [180; 181) 'h': u32
590 [184; 190) '!10u32': u32
591 [185; 190) '10u32': u32
592 [200; 201) 'j': i128
593 [204; 206) '!a': i128
594 [205; 206) 'a': i128
595 [212; 217) '-3.14': f64
596 [213; 217) '3.14': f64
597 [223; 225) '!3': i32
598 [224; 225) '3': i32
599 [231; 233) '-x': {unknown}
600 [232; 233) 'x': SomeType
601 [239; 241) '!x': {unknown}
602 [240; 241) 'x': SomeType
603 [247; 255) '-"hello"': {unknown}
604 [248; 255) '"hello"': &str
605 [261; 269) '!"hello"': {unknown}
606 [262; 269) '"hello"': &str
607 "###
608 );
609}
610
611#[test]
612fn infer_backwards() {
613 assert_snapshot!(
614 infer(r#"
615fn takes_u32(x: u32) {}
616
617struct S { i32_field: i32 }
618
619fn test() -> &mut &f64 {
620 let a = unknown_function();
621 takes_u32(a);
622 let b = unknown_function();
623 S { i32_field: b };
624 let c = unknown_function();
625 &mut &c
626}
627"#),
628 @r###"
629 [14; 15) 'x': u32
630 [22; 24) '{}': ()
631 [78; 231) '{ ...t &c }': &mut &f64
632 [88; 89) 'a': u32
633 [92; 108) 'unknow...nction': {unknown}
634 [92; 110) 'unknow...tion()': u32
635 [116; 125) 'takes_u32': fn takes_u32(u32) -> ()
636 [116; 128) 'takes_u32(a)': ()
637 [126; 127) 'a': u32
638 [138; 139) 'b': i32
639 [142; 158) 'unknow...nction': {unknown}
640 [142; 160) 'unknow...tion()': i32
641 [166; 184) 'S { i3...d: b }': S
642 [181; 182) 'b': i32
643 [194; 195) 'c': f64
644 [198; 214) 'unknow...nction': {unknown}
645 [198; 216) 'unknow...tion()': f64
646 [222; 229) '&mut &c': &mut &f64
647 [227; 229) '&c': &f64
648 [228; 229) 'c': f64
649 "###
650 );
651}
652
653#[test]
654fn infer_self() {
655 assert_snapshot!(
656 infer(r#"
657struct S;
658
659impl S {
660 fn test(&self) {
661 self;
662 }
663 fn test2(self: &Self) {
664 self;
665 }
666 fn test3() -> Self {
667 S {}
668 }
669 fn test4() -> Self {
670 Self {}
671 }
672}
673"#),
674 @r###"
675 [34; 38) 'self': &S
676 [40; 61) '{ ... }': ()
677 [50; 54) 'self': &S
678 [75; 79) 'self': &S
679 [88; 109) '{ ... }': ()
680 [98; 102) 'self': &S
681 [133; 153) '{ ... }': S
682 [143; 147) 'S {}': S
683 [177; 200) '{ ... }': S
684 [187; 194) 'Self {}': S
685 "###
686 );
687}
688
689#[test]
690fn infer_binary_op() {
691 assert_snapshot!(
692 infer(r#"
693fn f(x: bool) -> i32 {
694 0i32
695}
696
697fn test() -> bool {
698 let x = a && b;
699 let y = true || false;
700 let z = x == y;
701 let t = x != y;
702 let minus_forty: isize = -40isize;
703 let h = minus_forty <= CONST_2;
704 let c = f(z || y) + 5;
705 let d = b;
706 let g = minus_forty ^= i;
707 let ten: usize = 10;
708 let ten_is_eleven = ten == some_num;
709
710 ten < 3
711}
712"#),
713 @r###"
714 [6; 7) 'x': bool
715 [22; 34) '{ 0i32 }': i32
716 [28; 32) '0i32': i32
717 [54; 370) '{ ... < 3 }': bool
718 [64; 65) 'x': bool
719 [68; 69) 'a': bool
720 [68; 74) 'a && b': bool
721 [73; 74) 'b': bool
722 [84; 85) 'y': bool
723 [88; 92) 'true': bool
724 [88; 101) 'true || false': bool
725 [96; 101) 'false': bool
726 [111; 112) 'z': bool
727 [115; 116) 'x': bool
728 [115; 121) 'x == y': bool
729 [120; 121) 'y': bool
730 [131; 132) 't': bool
731 [135; 136) 'x': bool
732 [135; 141) 'x != y': bool
733 [140; 141) 'y': bool
734 [151; 162) 'minus_forty': isize
735 [172; 180) '-40isize': isize
736 [173; 180) '40isize': isize
737 [190; 191) 'h': bool
738 [194; 205) 'minus_forty': isize
739 [194; 216) 'minus_...ONST_2': bool
740 [209; 216) 'CONST_2': isize
741 [226; 227) 'c': i32
742 [230; 231) 'f': fn f(bool) -> i32
743 [230; 239) 'f(z || y)': i32
744 [230; 243) 'f(z || y) + 5': i32
745 [232; 233) 'z': bool
746 [232; 238) 'z || y': bool
747 [237; 238) 'y': bool
748 [242; 243) '5': i32
749 [253; 254) 'd': {unknown}
750 [257; 258) 'b': {unknown}
751 [268; 269) 'g': ()
752 [272; 283) 'minus_forty': isize
753 [272; 288) 'minus_...y ^= i': ()
754 [287; 288) 'i': isize
755 [298; 301) 'ten': usize
756 [311; 313) '10': usize
757 [323; 336) 'ten_is_eleven': bool
758 [339; 342) 'ten': usize
759 [339; 354) 'ten == some_num': bool
760 [346; 354) 'some_num': usize
761 [361; 364) 'ten': usize
762 [361; 368) 'ten < 3': bool
763 [367; 368) '3': usize
764 "###
765 );
766}
767
768#[test]
769fn infer_field_autoderef() {
770 assert_snapshot!(
771 infer(r#"
772struct A {
773 b: B,
774}
775struct B;
776
777fn test1(a: A) {
778 let a1 = a;
779 a1.b;
780 let a2 = &a;
781 a2.b;
782 let a3 = &mut a;
783 a3.b;
784 let a4 = &&&&&&&a;
785 a4.b;
786 let a5 = &mut &&mut &&mut a;
787 a5.b;
788}
789
790fn test2(a1: *const A, a2: *mut A) {
791 a1.b;
792 a2.b;
793}
794"#),
795 @r###"
796 [44; 45) 'a': A
797 [50; 213) '{ ...5.b; }': ()
798 [60; 62) 'a1': A
799 [65; 66) 'a': A
800 [72; 74) 'a1': A
801 [72; 76) 'a1.b': B
802 [86; 88) 'a2': &A
803 [91; 93) '&a': &A
804 [92; 93) 'a': A
805 [99; 101) 'a2': &A
806 [99; 103) 'a2.b': B
807 [113; 115) 'a3': &mut A
808 [118; 124) '&mut a': &mut A
809 [123; 124) 'a': A
810 [130; 132) 'a3': &mut A
811 [130; 134) 'a3.b': B
812 [144; 146) 'a4': &&&&&&&A
813 [149; 157) '&&&&&&&a': &&&&&&&A
814 [150; 157) '&&&&&&a': &&&&&&A
815 [151; 157) '&&&&&a': &&&&&A
816 [152; 157) '&&&&a': &&&&A
817 [153; 157) '&&&a': &&&A
818 [154; 157) '&&a': &&A
819 [155; 157) '&a': &A
820 [156; 157) 'a': A
821 [163; 165) 'a4': &&&&&&&A
822 [163; 167) 'a4.b': B
823 [177; 179) 'a5': &mut &&mut &&mut A
824 [182; 200) '&mut &...&mut a': &mut &&mut &&mut A
825 [187; 200) '&&mut &&mut a': &&mut &&mut A
826 [188; 200) '&mut &&mut a': &mut &&mut A
827 [193; 200) '&&mut a': &&mut A
828 [194; 200) '&mut a': &mut A
829 [199; 200) 'a': A
830 [206; 208) 'a5': &mut &&mut &&mut A
831 [206; 210) 'a5.b': B
832 [224; 226) 'a1': *const A
833 [238; 240) 'a2': *mut A
834 [250; 273) '{ ...2.b; }': ()
835 [256; 258) 'a1': *const A
836 [256; 260) 'a1.b': B
837 [266; 268) 'a2': *mut A
838 [266; 270) 'a2.b': B
839 "###
840 );
841}
842
843#[test]
844fn infer_argument_autoderef() {
845 assert_snapshot!(
846 infer(r#"
847#[lang = "deref"]
848pub trait Deref {
849 type Target;
850 fn deref(&self) -> &Self::Target;
851}
852
853struct A<T>(T);
854
855impl<T> A<T> {
856 fn foo(&self) -> &T {
857 &self.0
858 }
859}
860
861struct B<T>(T);
862
863impl<T> Deref for B<T> {
864 type Target = T;
865 fn deref(&self) -> &Self::Target {
866 &self.0
867 }
868}
869
870fn test() {
871 let t = A::foo(&&B(B(A(42))));
872}
873"#),
874 @r###"
875 [68; 72) 'self': &Self
876 [139; 143) 'self': &A<T>
877 [151; 174) '{ ... }': &T
878 [161; 168) '&self.0': &T
879 [162; 166) 'self': &A<T>
880 [162; 168) 'self.0': T
881 [255; 259) 'self': &B<T>
882 [278; 301) '{ ... }': &T
883 [288; 295) '&self.0': &T
884 [289; 293) 'self': &B<T>
885 [289; 295) 'self.0': T
886 [315; 353) '{ ...))); }': ()
887 [325; 326) 't': &i32
888 [329; 335) 'A::foo': fn foo<i32>(&A<T>) -> &T
889 [329; 350) 'A::foo...42))))': &i32
890 [336; 349) '&&B(B(A(42)))': &&B<B<A<i32>>>
891 [337; 349) '&B(B(A(42)))': &B<B<A<i32>>>
892 [338; 339) 'B': B<B<A<i32>>>(T) -> B<T>
893 [338; 349) 'B(B(A(42)))': B<B<A<i32>>>
894 [340; 341) 'B': B<A<i32>>(T) -> B<T>
895 [340; 348) 'B(A(42))': B<A<i32>>
896 [342; 343) 'A': A<i32>(T) -> A<T>
897 [342; 347) 'A(42)': A<i32>
898 [344; 346) '42': i32
899 "###
900 );
901}
902
903#[test]
904fn infer_method_argument_autoderef() {
905 assert_snapshot!(
906 infer(r#"
907#[lang = "deref"]
908pub trait Deref {
909 type Target;
910 fn deref(&self) -> &Self::Target;
911}
912
913struct A<T>(*mut T);
914
915impl<T> A<T> {
916 fn foo(&self, x: &A<T>) -> &T {
917 &*x.0
918 }
919}
920
921struct B<T>(T);
922
923impl<T> Deref for B<T> {
924 type Target = T;
925 fn deref(&self) -> &Self::Target {
926 &self.0
927 }
928}
929
930fn test(a: A<i32>) {
931 let t = A(0 as *mut _).foo(&&B(B(a)));
932}
933"#),
934 @r###"
935 [68; 72) 'self': &Self
936 [144; 148) 'self': &A<T>
937 [150; 151) 'x': &A<T>
938 [166; 187) '{ ... }': &T
939 [176; 181) '&*x.0': &T
940 [177; 181) '*x.0': T
941 [178; 179) 'x': &A<T>
942 [178; 181) 'x.0': *mut T
943 [268; 272) 'self': &B<T>
944 [291; 314) '{ ... }': &T
945 [301; 308) '&self.0': &T
946 [302; 306) 'self': &B<T>
947 [302; 308) 'self.0': T
948 [326; 327) 'a': A<i32>
949 [337; 383) '{ ...))); }': ()
950 [347; 348) 't': &i32
951 [351; 352) 'A': A<i32>(*mut T) -> A<T>
952 [351; 365) 'A(0 as *mut _)': A<i32>
953 [351; 380) 'A(0 as...B(a)))': &i32
954 [353; 354) '0': i32
955 [353; 364) '0 as *mut _': *mut i32
956 [370; 379) '&&B(B(a))': &&B<B<A<i32>>>
957 [371; 379) '&B(B(a))': &B<B<A<i32>>>
958 [372; 373) 'B': B<B<A<i32>>>(T) -> B<T>
959 [372; 379) 'B(B(a))': B<B<A<i32>>>
960 [374; 375) 'B': B<A<i32>>(T) -> B<T>
961 [374; 378) 'B(a)': B<A<i32>>
962 [376; 377) 'a': A<i32>
963 "###
964 );
965}
966
967#[test]
968fn bug_484() {
969 assert_snapshot!(
970 infer(r#"
971fn test() {
972 let x = if true {};
973}
974"#),
975 @r###"
976 [11; 37) '{ l... {}; }': ()
977 [20; 21) 'x': ()
978 [24; 34) 'if true {}': ()
979 [27; 31) 'true': bool
980 [32; 34) '{}': ()
981 "###
982 );
983}
984
985#[test]
986fn infer_in_elseif() {
987 assert_snapshot!(
988 infer(r#"
989struct Foo { field: i32 }
990fn main(foo: Foo) {
991 if true {
992
993 } else if false {
994 foo.field
995 }
996}
997"#),
998 @r###"
999 [35; 38) 'foo': Foo
1000 [45; 109) '{ ... } }': ()
1001 [51; 107) 'if tru... }': ()
1002 [54; 58) 'true': bool
1003 [59; 67) '{ }': ()
1004 [73; 107) 'if fal... }': ()
1005 [76; 81) 'false': bool
1006 [82; 107) '{ ... }': i32
1007 [92; 95) 'foo': Foo
1008 [92; 101) 'foo.field': i32
1009 "###
1010 )
1011}
1012
1013#[test]
1014fn infer_if_match_with_return() {
1015 assert_snapshot!(
1016 infer(r#"
1017fn foo() {
1018 let _x1 = if true {
1019 1
1020 } else {
1021 return;
1022 };
1023 let _x2 = if true {
1024 2
1025 } else {
1026 return
1027 };
1028 let _x3 = match true {
1029 true => 3,
1030 _ => {
1031 return;
1032 }
1033 };
1034 let _x4 = match true {
1035 true => 4,
1036 _ => return
1037 };
1038}"#),
1039 @r###"
1040 [10; 323) '{ ... }; }': ()
1041 [20; 23) '_x1': i32
1042 [26; 80) 'if tru... }': i32
1043 [29; 33) 'true': bool
1044 [34; 51) '{ ... }': i32
1045 [44; 45) '1': i32
1046 [57; 80) '{ ... }': !
1047 [67; 73) 'return': !
1048 [90; 93) '_x2': i32
1049 [96; 149) 'if tru... }': i32
1050 [99; 103) 'true': bool
1051 [104; 121) '{ ... }': i32
1052 [114; 115) '2': i32
1053 [127; 149) '{ ... }': !
1054 [137; 143) 'return': !
1055 [159; 162) '_x3': i32
1056 [165; 247) 'match ... }': i32
1057 [171; 175) 'true': bool
1058 [186; 190) 'true': bool
1059 [194; 195) '3': i32
1060 [205; 206) '_': bool
1061 [210; 241) '{ ... }': !
1062 [224; 230) 'return': !
1063 [257; 260) '_x4': i32
1064 [263; 320) 'match ... }': i32
1065 [269; 273) 'true': bool
1066 [284; 288) 'true': bool
1067 [292; 293) '4': i32
1068 [303; 304) '_': bool
1069 [308; 314) 'return': !
1070 "###
1071 )
1072}
1073
1074#[test]
1075fn infer_inherent_method() {
1076 assert_snapshot!(
1077 infer(r#"
1078struct A;
1079
1080impl A {
1081 fn foo(self, x: u32) -> i32 {}
1082}
1083
1084mod b {
1085 impl super::A {
1086 fn bar(&self, x: u64) -> i64 {}
1087 }
1088}
1089
1090fn test(a: A) {
1091 a.foo(1);
1092 (&a).bar(1);
1093 a.bar(1);
1094}
1095"#),
1096 @r###"
1097 [32; 36) 'self': A
1098 [38; 39) 'x': u32
1099 [53; 55) '{}': ()
1100 [103; 107) 'self': &A
1101 [109; 110) 'x': u64
1102 [124; 126) '{}': ()
1103 [144; 145) 'a': A
1104 [150; 198) '{ ...(1); }': ()
1105 [156; 157) 'a': A
1106 [156; 164) 'a.foo(1)': i32
1107 [162; 163) '1': u32
1108 [170; 181) '(&a).bar(1)': i64
1109 [171; 173) '&a': &A
1110 [172; 173) 'a': A
1111 [179; 180) '1': u64
1112 [187; 188) 'a': A
1113 [187; 195) 'a.bar(1)': i64
1114 [193; 194) '1': u64
1115 "###
1116 );
1117}
1118
1119#[test]
1120fn infer_inherent_method_str() {
1121 assert_snapshot!(
1122 infer(r#"
1123#[lang = "str"]
1124impl str {
1125 fn foo(&self) -> i32 {}
1126}
1127
1128fn test() {
1129 "foo".foo();
1130}
1131"#),
1132 @r###"
1133 [40; 44) 'self': &str
1134 [53; 55) '{}': ()
1135 [69; 89) '{ ...o(); }': ()
1136 [75; 80) '"foo"': &str
1137 [75; 86) '"foo".foo()': i32
1138 "###
1139 );
1140}
1141
1142#[test]
1143fn infer_tuple() {
1144 assert_snapshot!(
1145 infer(r#"
1146fn test(x: &str, y: isize) {
1147 let a: (u32, &str) = (1, "a");
1148 let b = (a, x);
1149 let c = (y, x);
1150 let d = (c, x);
1151 let e = (1, "e");
1152 let f = (e, "d");
1153}
1154"#),
1155 @r###"
1156 [9; 10) 'x': &str
1157 [18; 19) 'y': isize
1158 [28; 170) '{ ...d"); }': ()
1159 [38; 39) 'a': (u32, &str)
1160 [55; 63) '(1, "a")': (u32, &str)
1161 [56; 57) '1': u32
1162 [59; 62) '"a"': &str
1163 [73; 74) 'b': ((u32, &str), &str)
1164 [77; 83) '(a, x)': ((u32, &str), &str)
1165 [78; 79) 'a': (u32, &str)
1166 [81; 82) 'x': &str
1167 [93; 94) 'c': (isize, &str)
1168 [97; 103) '(y, x)': (isize, &str)
1169 [98; 99) 'y': isize
1170 [101; 102) 'x': &str
1171 [113; 114) 'd': ((isize, &str), &str)
1172 [117; 123) '(c, x)': ((isize, &str), &str)
1173 [118; 119) 'c': (isize, &str)
1174 [121; 122) 'x': &str
1175 [133; 134) 'e': (i32, &str)
1176 [137; 145) '(1, "e")': (i32, &str)
1177 [138; 139) '1': i32
1178 [141; 144) '"e"': &str
1179 [155; 156) 'f': ((i32, &str), &str)
1180 [159; 167) '(e, "d")': ((i32, &str), &str)
1181 [160; 161) 'e': (i32, &str)
1182 [163; 166) '"d"': &str
1183 "###
1184 );
1185}
1186
1187#[test]
1188fn infer_array() {
1189 assert_snapshot!(
1190 infer(r#"
1191fn test(x: &str, y: isize) {
1192 let a = [x];
1193 let b = [a, a];
1194 let c = [b, b];
1195
1196 let d = [y, 1, 2, 3];
1197 let d = [1, y, 2, 3];
1198 let e = [y];
1199 let f = [d, d];
1200 let g = [e, e];
1201
1202 let h = [1, 2];
1203 let i = ["a", "b"];
1204
1205 let b = [a, ["b"]];
1206 let x: [u8; 0] = [];
1207}
1208"#),
1209 @r###"
1210 [9; 10) 'x': &str
1211 [18; 19) 'y': isize
1212 [28; 293) '{ ... []; }': ()
1213 [38; 39) 'a': [&str;_]
1214 [42; 45) '[x]': [&str;_]
1215 [43; 44) 'x': &str
1216 [55; 56) 'b': [[&str;_];_]
1217 [59; 65) '[a, a]': [[&str;_];_]
1218 [60; 61) 'a': [&str;_]
1219 [63; 64) 'a': [&str;_]
1220 [75; 76) 'c': [[[&str;_];_];_]
1221 [79; 85) '[b, b]': [[[&str;_];_];_]
1222 [80; 81) 'b': [[&str;_];_]
1223 [83; 84) 'b': [[&str;_];_]
1224 [96; 97) 'd': [isize;_]
1225 [100; 112) '[y, 1, 2, 3]': [isize;_]
1226 [101; 102) 'y': isize
1227 [104; 105) '1': isize
1228 [107; 108) '2': isize
1229 [110; 111) '3': isize
1230 [122; 123) 'd': [isize;_]
1231 [126; 138) '[1, y, 2, 3]': [isize;_]
1232 [127; 128) '1': isize
1233 [130; 131) 'y': isize
1234 [133; 134) '2': isize
1235 [136; 137) '3': isize
1236 [148; 149) 'e': [isize;_]
1237 [152; 155) '[y]': [isize;_]
1238 [153; 154) 'y': isize
1239 [165; 166) 'f': [[isize;_];_]
1240 [169; 175) '[d, d]': [[isize;_];_]
1241 [170; 171) 'd': [isize;_]
1242 [173; 174) 'd': [isize;_]
1243 [185; 186) 'g': [[isize;_];_]
1244 [189; 195) '[e, e]': [[isize;_];_]
1245 [190; 191) 'e': [isize;_]
1246 [193; 194) 'e': [isize;_]
1247 [206; 207) 'h': [i32;_]
1248 [210; 216) '[1, 2]': [i32;_]
1249 [211; 212) '1': i32
1250 [214; 215) '2': i32
1251 [226; 227) 'i': [&str;_]
1252 [230; 240) '["a", "b"]': [&str;_]
1253 [231; 234) '"a"': &str
1254 [236; 239) '"b"': &str
1255 [251; 252) 'b': [[&str;_];_]
1256 [255; 265) '[a, ["b"]]': [[&str;_];_]
1257 [256; 257) 'a': [&str;_]
1258 [259; 264) '["b"]': [&str;_]
1259 [260; 263) '"b"': &str
1260 [275; 276) 'x': [u8;_]
1261 [288; 290) '[]': [u8;_]
1262 "###
1263 );
1264}
1265
1266#[test]
1267fn infer_pattern() {
1268 assert_snapshot!(
1269 infer(r#"
1270fn test(x: &i32) {
1271 let y = x;
1272 let &z = x;
1273 let a = z;
1274 let (c, d) = (1, "hello");
1275
1276 for (e, f) in some_iter {
1277 let g = e;
1278 }
1279
1280 if let [val] = opt {
1281 let h = val;
1282 }
1283
1284 let lambda = |a: u64, b, c: i32| { a + b; c };
1285
1286 let ref ref_to_x = x;
1287 let mut mut_x = x;
1288 let ref mut mut_ref_to_x = x;
1289 let k = mut_ref_to_x;
1290}
1291"#),
1292 @r###"
1293 [9; 10) 'x': &i32
1294 [18; 369) '{ ...o_x; }': ()
1295 [28; 29) 'y': &i32
1296 [32; 33) 'x': &i32
1297 [43; 45) '&z': &i32
1298 [44; 45) 'z': i32
1299 [48; 49) 'x': &i32
1300 [59; 60) 'a': i32
1301 [63; 64) 'z': i32
1302 [74; 80) '(c, d)': (i32, &str)
1303 [75; 76) 'c': i32
1304 [78; 79) 'd': &str
1305 [83; 95) '(1, "hello")': (i32, &str)
1306 [84; 85) '1': i32
1307 [87; 94) '"hello"': &str
1308 [102; 152) 'for (e... }': ()
1309 [106; 112) '(e, f)': ({unknown}, {unknown})
1310 [107; 108) 'e': {unknown}
1311 [110; 111) 'f': {unknown}
1312 [116; 125) 'some_iter': {unknown}
1313 [126; 152) '{ ... }': ()
1314 [140; 141) 'g': {unknown}
1315 [144; 145) 'e': {unknown}
1316 [158; 205) 'if let... }': ()
1317 [165; 170) '[val]': {unknown}
1318 [173; 176) 'opt': {unknown}
1319 [177; 205) '{ ... }': ()
1320 [191; 192) 'h': {unknown}
1321 [195; 198) 'val': {unknown}
1322 [215; 221) 'lambda': |u64, u64, i32| -> i32
1323 [224; 256) '|a: u6...b; c }': |u64, u64, i32| -> i32
1324 [225; 226) 'a': u64
1325 [233; 234) 'b': u64
1326 [236; 237) 'c': i32
1327 [244; 256) '{ a + b; c }': i32
1328 [246; 247) 'a': u64
1329 [246; 251) 'a + b': u64
1330 [250; 251) 'b': u64
1331 [253; 254) 'c': i32
1332 [267; 279) 'ref ref_to_x': &&i32
1333 [282; 283) 'x': &i32
1334 [293; 302) 'mut mut_x': &i32
1335 [305; 306) 'x': &i32
1336 [316; 336) 'ref mu...f_to_x': &mut &i32
1337 [339; 340) 'x': &i32
1338 [350; 351) 'k': &mut &i32
1339 [354; 366) 'mut_ref_to_x': &mut &i32
1340 "###
1341 );
1342}
1343
1344#[test]
1345fn infer_pattern_match_ergonomics() {
1346 assert_snapshot!(
1347 infer(r#"
1348struct A<T>(T);
1349
1350fn test() {
1351 let A(n) = &A(1);
1352 let A(n) = &mut A(1);
1353}
1354"#),
1355 @r###"
1356 [28; 79) '{ ...(1); }': ()
1357 [38; 42) 'A(n)': A<i32>
1358 [40; 41) 'n': &i32
1359 [45; 50) '&A(1)': &A<i32>
1360 [46; 47) 'A': A<i32>(T) -> A<T>
1361 [46; 50) 'A(1)': A<i32>
1362 [48; 49) '1': i32
1363 [60; 64) 'A(n)': A<i32>
1364 [62; 63) 'n': &mut i32
1365 [67; 76) '&mut A(1)': &mut A<i32>
1366 [72; 73) 'A': A<i32>(T) -> A<T>
1367 [72; 76) 'A(1)': A<i32>
1368 [74; 75) '1': i32
1369 "###
1370 );
1371}
1372
1373#[test]
1374fn infer_pattern_match_ergonomics_ref() {
1375 covers!(match_ergonomics_ref);
1376 assert_snapshot!(
1377 infer(r#"
1378fn test() {
1379 let v = &(1, &2);
1380 let (_, &w) = v;
1381}
1382"#),
1383 @r###"
1384 [11; 57) '{ ...= v; }': ()
1385 [21; 22) 'v': &(i32, &i32)
1386 [25; 33) '&(1, &2)': &(i32, &i32)
1387 [26; 33) '(1, &2)': (i32, &i32)
1388 [27; 28) '1': i32
1389 [30; 32) '&2': &i32
1390 [31; 32) '2': i32
1391 [43; 50) '(_, &w)': (i32, &i32)
1392 [44; 45) '_': i32
1393 [47; 49) '&w': &i32
1394 [48; 49) 'w': i32
1395 [53; 54) 'v': &(i32, &i32)
1396 "###
1397 );
1398}
1399
1400#[test]
1401fn infer_adt_pattern() {
1402 assert_snapshot!(
1403 infer(r#"
1404enum E {
1405 A { x: usize },
1406 B
1407}
1408
1409struct S(u32, E);
1410
1411fn test() {
1412 let e = E::A { x: 3 };
1413
1414 let S(y, z) = foo;
1415 let E::A { x: new_var } = e;
1416
1417 match e {
1418 E::A { x } => x,
1419 E::B if foo => 1,
1420 E::B => 10,
1421 };
1422
1423 let ref d @ E::A { .. } = e;
1424 d;
1425}
1426"#),
1427 @r###"
1428 [68; 289) '{ ... d; }': ()
1429 [78; 79) 'e': E
1430 [82; 95) 'E::A { x: 3 }': E
1431 [92; 93) '3': usize
1432 [106; 113) 'S(y, z)': S
1433 [108; 109) 'y': u32
1434 [111; 112) 'z': E
1435 [116; 119) 'foo': S
1436 [129; 148) 'E::A {..._var }': E
1437 [139; 146) 'new_var': usize
1438 [151; 152) 'e': E
1439 [159; 245) 'match ... }': usize
1440 [165; 166) 'e': E
1441 [177; 187) 'E::A { x }': E
1442 [184; 185) 'x': usize
1443 [191; 192) 'x': usize
1444 [202; 206) 'E::B': E
1445 [210; 213) 'foo': bool
1446 [217; 218) '1': usize
1447 [228; 232) 'E::B': E
1448 [236; 238) '10': usize
1449 [256; 275) 'ref d ...{ .. }': &E
1450 [264; 275) 'E::A { .. }': E
1451 [278; 279) 'e': E
1452 [285; 286) 'd': &E
1453 "###
1454 );
1455}
1456
1457#[test]
1458fn infer_struct_generics() {
1459 assert_snapshot!(
1460 infer(r#"
1461struct A<T> {
1462 x: T,
1463}
1464
1465fn test(a1: A<u32>, i: i32) {
1466 a1.x;
1467 let a2 = A { x: i };
1468 a2.x;
1469 let a3 = A::<i128> { x: 1 };
1470 a3.x;
1471}
1472"#),
1473 @r###"
1474 [36; 38) 'a1': A<u32>
1475 [48; 49) 'i': i32
1476 [56; 147) '{ ...3.x; }': ()
1477 [62; 64) 'a1': A<u32>
1478 [62; 66) 'a1.x': u32
1479 [76; 78) 'a2': A<i32>
1480 [81; 91) 'A { x: i }': A<i32>
1481 [88; 89) 'i': i32
1482 [97; 99) 'a2': A<i32>
1483 [97; 101) 'a2.x': i32
1484 [111; 113) 'a3': A<i128>
1485 [116; 134) 'A::<i1...x: 1 }': A<i128>
1486 [131; 132) '1': i128
1487 [140; 142) 'a3': A<i128>
1488 [140; 144) 'a3.x': i128
1489 "###
1490 );
1491}
1492
1493#[test]
1494fn infer_tuple_struct_generics() {
1495 assert_snapshot!(
1496 infer(r#"
1497struct A<T>(T);
1498enum Option<T> { Some(T), None }
1499use Option::*;
1500
1501fn test() {
1502 A(42);
1503 A(42u128);
1504 Some("x");
1505 Option::Some("x");
1506 None;
1507 let x: Option<i64> = None;
1508}
1509"#),
1510 @r###"
1511 [76; 184) '{ ...one; }': ()
1512 [82; 83) 'A': A<i32>(T) -> A<T>
1513 [82; 87) 'A(42)': A<i32>
1514 [84; 86) '42': i32
1515 [93; 94) 'A': A<u128>(T) -> A<T>
1516 [93; 102) 'A(42u128)': A<u128>
1517 [95; 101) '42u128': u128
1518 [108; 112) 'Some': Some<&str>(T) -> Option<T>
1519 [108; 117) 'Some("x")': Option<&str>
1520 [113; 116) '"x"': &str
1521 [123; 135) 'Option::Some': Some<&str>(T) -> Option<T>
1522 [123; 140) 'Option...e("x")': Option<&str>
1523 [136; 139) '"x"': &str
1524 [146; 150) 'None': Option<{unknown}>
1525 [160; 161) 'x': Option<i64>
1526 [177; 181) 'None': Option<i64>
1527 "###
1528 );
1529}
1530
1531#[test]
1532fn infer_generics_in_patterns() {
1533 assert_snapshot!(
1534 infer(r#"
1535struct A<T> {
1536 x: T,
1537}
1538
1539enum Option<T> {
1540 Some(T),
1541 None,
1542}
1543
1544fn test(a1: A<u32>, o: Option<u64>) {
1545 let A { x: x2 } = a1;
1546 let A::<i64> { x: x3 } = A { x: 1 };
1547 match o {
1548 Option::Some(t) => t,
1549 _ => 1,
1550 };
1551}
1552"#),
1553 @r###"
1554 [79; 81) 'a1': A<u32>
1555 [91; 92) 'o': Option<u64>
1556 [107; 244) '{ ... }; }': ()
1557 [117; 128) 'A { x: x2 }': A<u32>
1558 [124; 126) 'x2': u32
1559 [131; 133) 'a1': A<u32>
1560 [143; 161) 'A::<i6...: x3 }': A<i64>
1561 [157; 159) 'x3': i64
1562 [164; 174) 'A { x: 1 }': A<i64>
1563 [171; 172) '1': i64
1564 [180; 241) 'match ... }': u64
1565 [186; 187) 'o': Option<u64>
1566 [198; 213) 'Option::Some(t)': Option<u64>
1567 [211; 212) 't': u64
1568 [217; 218) 't': u64
1569 [228; 229) '_': Option<u64>
1570 [233; 234) '1': u64
1571 "###
1572 );
1573}
1574
1575#[test]
1576fn infer_function_generics() {
1577 assert_snapshot!(
1578 infer(r#"
1579fn id<T>(t: T) -> T { t }
1580
1581fn test() {
1582 id(1u32);
1583 id::<i128>(1);
1584 let x: u64 = id(1);
1585}
1586"#),
1587 @r###"
1588 [10; 11) 't': T
1589 [21; 26) '{ t }': T
1590 [23; 24) 't': T
1591 [38; 98) '{ ...(1); }': ()
1592 [44; 46) 'id': fn id<u32>(T) -> T
1593 [44; 52) 'id(1u32)': u32
1594 [47; 51) '1u32': u32
1595 [58; 68) 'id::<i128>': fn id<i128>(T) -> T
1596 [58; 71) 'id::<i128>(1)': i128
1597 [69; 70) '1': i128
1598 [81; 82) 'x': u64
1599 [90; 92) 'id': fn id<u64>(T) -> T
1600 [90; 95) 'id(1)': u64
1601 [93; 94) '1': u64
1602 "###
1603 );
1604}
1605
1606#[test]
1607fn infer_impl_generics() {
1608 assert_snapshot!(
1609 infer(r#"
1610struct A<T1, T2> {
1611 x: T1,
1612 y: T2,
1613}
1614impl<Y, X> A<X, Y> {
1615 fn x(self) -> X {
1616 self.x
1617 }
1618 fn y(self) -> Y {
1619 self.y
1620 }
1621 fn z<T>(self, t: T) -> (X, Y, T) {
1622 (self.x, self.y, t)
1623 }
1624}
1625
1626fn test() -> i128 {
1627 let a = A { x: 1u64, y: 1i64 };
1628 a.x();
1629 a.y();
1630 a.z(1i128);
1631 a.z::<u128>(1);
1632}
1633"#),
1634 @r###"
1635 [74; 78) 'self': A<X, Y>
1636 [85; 107) '{ ... }': X
1637 [95; 99) 'self': A<X, Y>
1638 [95; 101) 'self.x': X
1639 [117; 121) 'self': A<X, Y>
1640 [128; 150) '{ ... }': Y
1641 [138; 142) 'self': A<X, Y>
1642 [138; 144) 'self.y': Y
1643 [163; 167) 'self': A<X, Y>
1644 [169; 170) 't': T
1645 [188; 223) '{ ... }': (X, Y, T)
1646 [198; 217) '(self.....y, t)': (X, Y, T)
1647 [199; 203) 'self': A<X, Y>
1648 [199; 205) 'self.x': X
1649 [207; 211) 'self': A<X, Y>
1650 [207; 213) 'self.y': Y
1651 [215; 216) 't': T
1652 [245; 342) '{ ...(1); }': ()
1653 [255; 256) 'a': A<u64, i64>
1654 [259; 281) 'A { x:...1i64 }': A<u64, i64>
1655 [266; 270) '1u64': u64
1656 [275; 279) '1i64': i64
1657 [287; 288) 'a': A<u64, i64>
1658 [287; 292) 'a.x()': u64
1659 [298; 299) 'a': A<u64, i64>
1660 [298; 303) 'a.y()': i64
1661 [309; 310) 'a': A<u64, i64>
1662 [309; 319) 'a.z(1i128)': (u64, i64, i128)
1663 [313; 318) '1i128': i128
1664 [325; 326) 'a': A<u64, i64>
1665 [325; 339) 'a.z::<u128>(1)': (u64, i64, u128)
1666 [337; 338) '1': u128
1667 "###
1668 );
1669}
1670
1671#[test]
1672fn infer_impl_generics_with_autoderef() {
1673 assert_snapshot!(
1674 infer(r#"
1675enum Option<T> {
1676 Some(T),
1677 None,
1678}
1679impl<T> Option<T> {
1680 fn as_ref(&self) -> Option<&T> {}
1681}
1682fn test(o: Option<u32>) {
1683 (&o).as_ref();
1684 o.as_ref();
1685}
1686"#),
1687 @r###"
1688 [78; 82) 'self': &Option<T>
1689 [98; 100) '{}': ()
1690 [111; 112) 'o': Option<u32>
1691 [127; 165) '{ ...f(); }': ()
1692 [133; 146) '(&o).as_ref()': Option<&u32>
1693 [134; 136) '&o': &Option<u32>
1694 [135; 136) 'o': Option<u32>
1695 [152; 153) 'o': Option<u32>
1696 [152; 162) 'o.as_ref()': Option<&u32>
1697 "###
1698 );
1699}
1700
1701#[test]
1702fn infer_generic_chain() {
1703 assert_snapshot!(
1704 infer(r#"
1705struct A<T> {
1706 x: T,
1707}
1708impl<T2> A<T2> {
1709 fn x(self) -> T2 {
1710 self.x
1711 }
1712}
1713fn id<T>(t: T) -> T { t }
1714
1715fn test() -> i128 {
1716 let x = 1;
1717 let y = id(x);
1718 let a = A { x: id(y) };
1719 let z = id(a.x);
1720 let b = A { x: z };
1721 b.x()
1722}
1723"#),
1724 @r###"
1725 [53; 57) 'self': A<T2>
1726 [65; 87) '{ ... }': T2
1727 [75; 79) 'self': A<T2>
1728 [75; 81) 'self.x': T2
1729 [99; 100) 't': T
1730 [110; 115) '{ t }': T
1731 [112; 113) 't': T
1732 [135; 261) '{ ....x() }': i128
1733 [146; 147) 'x': i128
1734 [150; 151) '1': i128
1735 [162; 163) 'y': i128
1736 [166; 168) 'id': fn id<i128>(T) -> T
1737 [166; 171) 'id(x)': i128
1738 [169; 170) 'x': i128
1739 [182; 183) 'a': A<i128>
1740 [186; 200) 'A { x: id(y) }': A<i128>
1741 [193; 195) 'id': fn id<i128>(T) -> T
1742 [193; 198) 'id(y)': i128
1743 [196; 197) 'y': i128
1744 [211; 212) 'z': i128
1745 [215; 217) 'id': fn id<i128>(T) -> T
1746 [215; 222) 'id(a.x)': i128
1747 [218; 219) 'a': A<i128>
1748 [218; 221) 'a.x': i128
1749 [233; 234) 'b': A<i128>
1750 [237; 247) 'A { x: z }': A<i128>
1751 [244; 245) 'z': i128
1752 [254; 255) 'b': A<i128>
1753 [254; 259) 'b.x()': i128
1754 "###
1755 );
1756}
1757
1758#[test]
1759fn infer_associated_const() {
1760 assert_snapshot!(
1761 infer(r#"
1762struct Struct;
1763
1764impl Struct {
1765 const FOO: u32 = 1;
1766}
1767
1768enum Enum {}
1769
1770impl Enum {
1771 const BAR: u32 = 2;
1772}
1773
1774trait Trait {
1775 const ID: u32;
1776}
1777
1778struct TraitTest;
1779
1780impl Trait for TraitTest {
1781 const ID: u32 = 5;
1782}
1783
1784fn test() {
1785 let x = Struct::FOO;
1786 let y = Enum::BAR;
1787 let z = TraitTest::ID;
1788}
1789"#),
1790 @r###"
1791 [52; 53) '1': u32
1792 [105; 106) '2': u32
1793 [213; 214) '5': u32
1794 [229; 307) '{ ...:ID; }': ()
1795 [239; 240) 'x': u32
1796 [243; 254) 'Struct::FOO': u32
1797 [264; 265) 'y': u32
1798 [268; 277) 'Enum::BAR': u32
1799 [287; 288) 'z': u32
1800 [291; 304) 'TraitTest::ID': u32
1801 "###
1802 );
1803}
1804
1805#[test]
1806fn infer_associated_method_struct() {
1807 assert_snapshot!(
1808 infer(r#"
1809struct A { x: u32 }
1810
1811impl A {
1812 fn new() -> A {
1813 A { x: 0 }
1814 }
1815}
1816fn test() {
1817 let a = A::new();
1818 a.x;
1819}
1820"#),
1821 @r###"
1822 [49; 75) '{ ... }': A
1823 [59; 69) 'A { x: 0 }': A
1824 [66; 67) '0': u32
1825 [88; 122) '{ ...a.x; }': ()
1826 [98; 99) 'a': A
1827 [102; 108) 'A::new': fn new() -> A
1828 [102; 110) 'A::new()': A
1829 [116; 117) 'a': A
1830 [116; 119) 'a.x': u32
1831 "###
1832 );
1833}
1834
1835#[test]
1836fn infer_associated_method_enum() {
1837 assert_snapshot!(
1838 infer(r#"
1839enum A { B, C }
1840
1841impl A {
1842 pub fn b() -> A {
1843 A::B
1844 }
1845 pub fn c() -> A {
1846 A::C
1847 }
1848}
1849fn test() {
1850 let a = A::b();
1851 a;
1852 let c = A::c();
1853 c;
1854}
1855"#),
1856 @r###"
1857 [47; 67) '{ ... }': A
1858 [57; 61) 'A::B': A
1859 [88; 108) '{ ... }': A
1860 [98; 102) 'A::C': A
1861 [121; 178) '{ ... c; }': ()
1862 [131; 132) 'a': A
1863 [135; 139) 'A::b': fn b() -> A
1864 [135; 141) 'A::b()': A
1865 [147; 148) 'a': A
1866 [158; 159) 'c': A
1867 [162; 166) 'A::c': fn c() -> A
1868 [162; 168) 'A::c()': A
1869 [174; 175) 'c': A
1870 "###
1871 );
1872}
1873
1874#[test]
1875fn infer_associated_method_with_modules() {
1876 assert_snapshot!(
1877 infer(r#"
1878mod a {
1879 struct A;
1880 impl A { pub fn thing() -> A { A {} }}
1881}
1882
1883mod b {
1884 struct B;
1885 impl B { pub fn thing() -> u32 { 99 }}
1886
1887 mod c {
1888 struct C;
1889 impl C { pub fn thing() -> C { C {} }}
1890 }
1891}
1892use b::c;
1893
1894fn test() {
1895 let x = a::A::thing();
1896 let y = b::B::thing();
1897 let z = c::C::thing();
1898}
1899"#),
1900 @r###"
1901 [56; 64) '{ A {} }': A
1902 [58; 62) 'A {}': A
1903 [126; 132) '{ 99 }': u32
1904 [128; 130) '99': u32
1905 [202; 210) '{ C {} }': C
1906 [204; 208) 'C {}': C
1907 [241; 325) '{ ...g(); }': ()
1908 [251; 252) 'x': A
1909 [255; 266) 'a::A::thing': fn thing() -> A
1910 [255; 268) 'a::A::thing()': A
1911 [278; 279) 'y': u32
1912 [282; 293) 'b::B::thing': fn thing() -> u32
1913 [282; 295) 'b::B::thing()': u32
1914 [305; 306) 'z': C
1915 [309; 320) 'c::C::thing': fn thing() -> C
1916 [309; 322) 'c::C::thing()': C
1917 "###
1918 );
1919}
1920
1921#[test]
1922fn infer_associated_method_generics() {
1923 assert_snapshot!(
1924 infer(r#"
1925struct Gen<T> {
1926 val: T
1927}
1928
1929impl<T> Gen<T> {
1930 pub fn make(val: T) -> Gen<T> {
1931 Gen { val }
1932 }
1933}
1934
1935fn test() {
1936 let a = Gen::make(0u32);
1937}
1938"#),
1939 @r###"
1940 [64; 67) 'val': T
1941 [82; 109) '{ ... }': Gen<T>
1942 [92; 103) 'Gen { val }': Gen<T>
1943 [98; 101) 'val': T
1944 [123; 155) '{ ...32); }': ()
1945 [133; 134) 'a': Gen<u32>
1946 [137; 146) 'Gen::make': fn make<u32>(T) -> Gen<T>
1947 [137; 152) 'Gen::make(0u32)': Gen<u32>
1948 [147; 151) '0u32': u32
1949 "###
1950 );
1951}
1952
1953#[test]
1954fn infer_associated_method_generics_with_default_param() {
1955 assert_snapshot!(
1956 infer(r#"
1957struct Gen<T=u32> {
1958 val: T
1959}
1960
1961impl<T> Gen<T> {
1962 pub fn make() -> Gen<T> {
1963 loop { }
1964 }
1965}
1966
1967fn test() {
1968 let a = Gen::make();
1969}
1970"#),
1971 @r###"
1972 [80; 104) '{ ... }': Gen<T>
1973 [90; 98) 'loop { }': !
1974 [95; 98) '{ }': ()
1975 [118; 146) '{ ...e(); }': ()
1976 [128; 129) 'a': Gen<u32>
1977 [132; 141) 'Gen::make': fn make<u32>() -> Gen<T>
1978 [132; 143) 'Gen::make()': Gen<u32>
1979 "###
1980 );
1981}
1982
1983#[test]
1984fn infer_associated_method_generics_with_default_tuple_param() {
1985 let t = type_at(
1986 r#"
1987//- /main.rs
1988struct Gen<T=()> {
1989 val: T
1990}
1991
1992impl<T> Gen<T> {
1993 pub fn make() -> Gen<T> {
1994 loop { }
1995 }
1996}
1997
1998fn test() {
1999 let a = Gen::make();
2000 a.val<|>;
2001}
2002"#,
2003 );
2004 assert_eq!(t, "()");
2005}
2006
2007#[test]
2008fn infer_associated_method_generics_without_args() {
2009 assert_snapshot!(
2010 infer(r#"
2011struct Gen<T> {
2012 val: T
2013}
2014
2015impl<T> Gen<T> {
2016 pub fn make() -> Gen<T> {
2017 loop { }
2018 }
2019}
2020
2021fn test() {
2022 let a = Gen::<u32>::make();
2023}
2024"#),
2025 @r###"
2026 [76; 100) '{ ... }': Gen<T>
2027 [86; 94) 'loop { }': !
2028 [91; 94) '{ }': ()
2029 [114; 149) '{ ...e(); }': ()
2030 [124; 125) 'a': Gen<u32>
2031 [128; 144) 'Gen::<...::make': fn make<u32>() -> Gen<T>
2032 [128; 146) 'Gen::<...make()': Gen<u32>
2033 "###
2034 );
2035}
2036
2037#[test]
2038fn infer_associated_method_generics_2_type_params_without_args() {
2039 assert_snapshot!(
2040 infer(r#"
2041struct Gen<T, U> {
2042 val: T,
2043 val2: U,
2044}
2045
2046impl<T> Gen<u32, T> {
2047 pub fn make() -> Gen<u32,T> {
2048 loop { }
2049 }
2050}
2051
2052fn test() {
2053 let a = Gen::<u32, u64>::make();
2054}
2055"#),
2056 @r###"
2057 [102; 126) '{ ... }': Gen<u32, T>
2058 [112; 120) 'loop { }': !
2059 [117; 120) '{ }': ()
2060 [140; 180) '{ ...e(); }': ()
2061 [150; 151) 'a': Gen<u32, u64>
2062 [154; 175) 'Gen::<...::make': fn make<u64>() -> Gen<u32, T>
2063 [154; 177) 'Gen::<...make()': Gen<u32, u64>
2064 "###
2065 );
2066}
2067
2068#[test]
2069fn infer_type_alias() {
2070 assert_snapshot!(
2071 infer(r#"
2072struct A<X, Y> { x: X, y: Y }
2073type Foo = A<u32, i128>;
2074type Bar<T> = A<T, u128>;
2075type Baz<U, V> = A<V, U>;
2076fn test(x: Foo, y: Bar<&str>, z: Baz<i8, u8>) {
2077 x.x;
2078 x.y;
2079 y.x;
2080 y.y;
2081 z.x;
2082 z.y;
2083}
2084"#),
2085 @r###"
2086 [116; 117) 'x': A<u32, i128>
2087 [124; 125) 'y': A<&str, u128>
2088 [138; 139) 'z': A<u8, i8>
2089 [154; 211) '{ ...z.y; }': ()
2090 [160; 161) 'x': A<u32, i128>
2091 [160; 163) 'x.x': u32
2092 [169; 170) 'x': A<u32, i128>
2093 [169; 172) 'x.y': i128
2094 [178; 179) 'y': A<&str, u128>
2095 [178; 181) 'y.x': &str
2096 [187; 188) 'y': A<&str, u128>
2097 [187; 190) 'y.y': u128
2098 [196; 197) 'z': A<u8, i8>
2099 [196; 199) 'z.x': u8
2100 [205; 206) 'z': A<u8, i8>
2101 [205; 208) 'z.y': i8
2102 "###
2103 )
2104}
2105
2106#[test]
2107#[should_panic] // we currently can't handle this
2108fn recursive_type_alias() {
2109 assert_snapshot!(
2110 infer(r#"
2111struct A<X> {}
2112type Foo = Foo;
2113type Bar = A<Bar>;
2114fn test(x: Foo) {}
2115"#),
2116 @""
2117 )
2118}
2119
2120#[test]
2121fn no_panic_on_field_of_enum() {
2122 assert_snapshot!(
2123 infer(r#"
2124enum X {}
2125
2126fn test(x: X) {
2127 x.some_field;
2128}
2129"#),
2130 @r###"
2131 [20; 21) 'x': X
2132 [26; 47) '{ ...eld; }': ()
2133 [32; 33) 'x': X
2134 [32; 44) 'x.some_field': {unknown}
2135 "###
2136 );
2137}
2138
2139#[test]
2140fn bug_585() {
2141 assert_snapshot!(
2142 infer(r#"
2143fn test() {
2144 X {};
2145 match x {
2146 A::B {} => (),
2147 A::Y() => (),
2148 }
2149}
2150"#),
2151 @r###"
2152 [11; 89) '{ ... } }': ()
2153 [17; 21) 'X {}': {unknown}
2154 [27; 87) 'match ... }': ()
2155 [33; 34) 'x': {unknown}
2156 [45; 52) 'A::B {}': {unknown}
2157 [56; 58) '()': ()
2158 [68; 74) 'A::Y()': {unknown}
2159 [78; 80) '()': ()
2160 "###
2161 );
2162}
2163
2164#[test]
2165fn bug_651() {
2166 assert_snapshot!(
2167 infer(r#"
2168fn quux() {
2169 let y = 92;
2170 1 + y;
2171}
2172"#),
2173 @r###"
2174 [11; 41) '{ ...+ y; }': ()
2175 [21; 22) 'y': i32
2176 [25; 27) '92': i32
2177 [33; 34) '1': i32
2178 [33; 38) '1 + y': i32
2179 [37; 38) 'y': i32
2180 "###
2181 );
2182}
2183
2184#[test]
2185fn recursive_vars() {
2186 covers!(type_var_cycles_resolve_completely);
2187 covers!(type_var_cycles_resolve_as_possible);
2188 assert_snapshot!(
2189 infer(r#"
2190fn test() {
2191 let y = unknown;
2192 [y, &y];
2193}
2194"#),
2195 @r###"
2196 [11; 48) '{ ...&y]; }': ()
2197 [21; 22) 'y': &{unknown}
2198 [25; 32) 'unknown': &{unknown}
2199 [38; 45) '[y, &y]': [&&{unknown};_]
2200 [39; 40) 'y': &{unknown}
2201 [42; 44) '&y': &&{unknown}
2202 [43; 44) 'y': &{unknown}
2203 "###
2204 );
2205}
2206
2207#[test]
2208fn recursive_vars_2() {
2209 covers!(type_var_cycles_resolve_completely);
2210 covers!(type_var_cycles_resolve_as_possible);
2211 assert_snapshot!(
2212 infer(r#"
2213fn test() {
2214 let x = unknown;
2215 let y = unknown;
2216 [(x, y), (&y, &x)];
2217}
2218"#),
2219 @r###"
2220 [11; 80) '{ ...x)]; }': ()
2221 [21; 22) 'x': &&{unknown}
2222 [25; 32) 'unknown': &&{unknown}
2223 [42; 43) 'y': &&{unknown}
2224 [46; 53) 'unknown': &&{unknown}
2225 [59; 77) '[(x, y..., &x)]': [(&&&{unknown}, &&&{unknown});_]
2226 [60; 66) '(x, y)': (&&&{unknown}, &&&{unknown})
2227 [61; 62) 'x': &&{unknown}
2228 [64; 65) 'y': &&{unknown}
2229 [68; 76) '(&y, &x)': (&&&{unknown}, &&&{unknown})
2230 [69; 71) '&y': &&&{unknown}
2231 [70; 71) 'y': &&{unknown}
2232 [73; 75) '&x': &&&{unknown}
2233 [74; 75) 'x': &&{unknown}
2234 "###
2235 );
2236}
2237
2238#[test]
2239fn infer_type_param() {
2240 assert_snapshot!(
2241 infer(r#"
2242fn id<T>(x: T) -> T {
2243 x
2244}
2245
2246fn clone<T>(x: &T) -> T {
2247 *x
2248}
2249
2250fn test() {
2251 let y = 10u32;
2252 id(y);
2253 let x: bool = clone(z);
2254 id::<i128>(1);
2255}
2256"#),
2257 @r###"
2258 [10; 11) 'x': T
2259 [21; 30) '{ x }': T
2260 [27; 28) 'x': T
2261 [44; 45) 'x': &T
2262 [56; 66) '{ *x }': T
2263 [62; 64) '*x': T
2264 [63; 64) 'x': &T
2265 [78; 158) '{ ...(1); }': ()
2266 [88; 89) 'y': u32
2267 [92; 97) '10u32': u32
2268 [103; 105) 'id': fn id<u32>(T) -> T
2269 [103; 108) 'id(y)': u32
2270 [106; 107) 'y': u32
2271 [118; 119) 'x': bool
2272 [128; 133) 'clone': fn clone<bool>(&T) -> T
2273 [128; 136) 'clone(z)': bool
2274 [134; 135) 'z': &bool
2275 [142; 152) 'id::<i128>': fn id<i128>(T) -> T
2276 [142; 155) 'id::<i128>(1)': i128
2277 [153; 154) '1': i128
2278 "###
2279 );
2280}
2281
2282#[test]
2283fn infer_std_crash_1() {
2284 // caused stack overflow, taken from std
2285 assert_snapshot!(
2286 infer(r#"
2287enum Maybe<T> {
2288 Real(T),
2289 Fake,
2290}
2291
2292fn write() {
2293 match something_unknown {
2294 Maybe::Real(ref mut something) => (),
2295 }
2296}
2297"#),
2298 @r###"
2299 [54; 139) '{ ... } }': ()
2300 [60; 137) 'match ... }': ()
2301 [66; 83) 'someth...nknown': Maybe<{unknown}>
2302 [94; 124) 'Maybe:...thing)': Maybe<{unknown}>
2303 [106; 123) 'ref mu...ething': &mut {unknown}
2304 [128; 130) '()': ()
2305 "###
2306 );
2307}
2308
2309#[test]
2310fn infer_std_crash_2() {
2311 covers!(type_var_resolves_to_int_var);
2312 // caused "equating two type variables, ...", taken from std
2313 assert_snapshot!(
2314 infer(r#"
2315fn test_line_buffer() {
2316 &[0, b'\n', 1, b'\n'];
2317}
2318"#),
2319 @r###"
2320 [23; 53) '{ ...n']; }': ()
2321 [29; 50) '&[0, b...b'\n']': &[u8;_]
2322 [30; 50) '[0, b'...b'\n']': [u8;_]
2323 [31; 32) '0': u8
2324 [34; 39) 'b'\n'': u8
2325 [41; 42) '1': u8
2326 [44; 49) 'b'\n'': u8
2327 "###
2328 );
2329}
2330
2331#[test]
2332fn infer_std_crash_3() {
2333 // taken from rustc
2334 assert_snapshot!(
2335 infer(r#"
2336pub fn compute() {
2337 match nope!() {
2338 SizeSkeleton::Pointer { non_zero: true, tail } => {}
2339 }
2340}
2341"#),
2342 @r###"
2343 [18; 108) '{ ... } }': ()
2344 [24; 106) 'match ... }': ()
2345 [30; 37) 'nope!()': {unknown}
2346 [48; 94) 'SizeSk...tail }': {unknown}
2347 [82; 86) 'true': {unknown}
2348 [88; 92) 'tail': {unknown}
2349 [98; 100) '{}': ()
2350 "###
2351 );
2352}
2353
2354#[test]
2355fn infer_std_crash_4() {
2356 // taken from rustc
2357 assert_snapshot!(
2358 infer(r#"
2359pub fn primitive_type() {
2360 match *self {
2361 BorrowedRef { type_: Primitive(p), ..} => {},
2362 }
2363}
2364"#),
2365 @r###"
2366 [25; 106) '{ ... } }': ()
2367 [31; 104) 'match ... }': ()
2368 [37; 42) '*self': {unknown}
2369 [38; 42) 'self': {unknown}
2370 [53; 91) 'Borrow...), ..}': {unknown}
2371 [74; 86) 'Primitive(p)': {unknown}
2372 [84; 85) 'p': {unknown}
2373 [95; 97) '{}': ()
2374 "###
2375 );
2376}
2377
2378#[test]
2379fn infer_std_crash_5() {
2380 // taken from rustc
2381 assert_snapshot!(
2382 infer(r#"
2383fn extra_compiler_flags() {
2384 for content in doesnt_matter {
2385 let name = if doesnt_matter {
2386 first
2387 } else {
2388 &content
2389 };
2390
2391 let content = if ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.contains(&name) {
2392 name
2393 } else {
2394 content
2395 };
2396 }
2397}
2398"#),
2399 @r###"
2400 [27; 323) '{ ... } }': ()
2401 [33; 321) 'for co... }': ()
2402 [37; 44) 'content': &{unknown}
2403 [48; 61) 'doesnt_matter': {unknown}
2404 [62; 321) '{ ... }': ()
2405 [76; 80) 'name': &&{unknown}
2406 [83; 167) 'if doe... }': &&{unknown}
2407 [86; 99) 'doesnt_matter': bool
2408 [100; 129) '{ ... }': &&{unknown}
2409 [114; 119) 'first': &&{unknown}
2410 [135; 167) '{ ... }': &&{unknown}
2411 [149; 157) '&content': &&{unknown}
2412 [150; 157) 'content': &{unknown}
2413 [182; 189) 'content': &{unknown}
2414 [192; 314) 'if ICE... }': &{unknown}
2415 [195; 232) 'ICE_RE..._VALUE': {unknown}
2416 [195; 248) 'ICE_RE...&name)': bool
2417 [242; 247) '&name': &&&{unknown}
2418 [243; 247) 'name': &&{unknown}
2419 [249; 277) '{ ... }': &&{unknown}
2420 [263; 267) 'name': &&{unknown}
2421 [283; 314) '{ ... }': &{unknown}
2422 [297; 304) 'content': &{unknown}
2423 "###
2424 );
2425}
2426
2427#[test]
2428fn infer_nested_generics_crash() {
2429 // another crash found typechecking rustc
2430 assert_snapshot!(
2431 infer(r#"
2432struct Canonical<V> {
2433 value: V,
2434}
2435struct QueryResponse<V> {
2436 value: V,
2437}
2438fn test<R>(query_response: Canonical<QueryResponse<R>>) {
2439 &query_response.value;
2440}
2441"#),
2442 @r###"
2443 [92; 106) 'query_response': Canonical<QueryResponse<R>>
2444 [137; 167) '{ ...lue; }': ()
2445 [143; 164) '&query....value': &QueryResponse<R>
2446 [144; 158) 'query_response': Canonical<QueryResponse<R>>
2447 [144; 164) 'query_....value': QueryResponse<R>
2448 "###
2449 );
2450}
2451
2452#[test]
2453fn bug_1030() {
2454 assert_snapshot!(infer(r#"
2455struct HashSet<T, H>;
2456struct FxHasher;
2457type FxHashSet<T> = HashSet<T, FxHasher>;
2458
2459impl<T, H> HashSet<T, H> {
2460 fn default() -> HashSet<T, H> {}
2461}
2462
2463pub fn main_loop() {
2464 FxHashSet::default();
2465}
2466"#),
2467 @r###"
2468 [144; 146) '{}': ()
2469 [169; 198) '{ ...t(); }': ()
2470 [175; 193) 'FxHash...efault': fn default<{unknown}, FxHasher>() -> HashSet<T, H>
2471 [175; 195) 'FxHash...ault()': HashSet<{unknown}, FxHasher>
2472 "###
2473 );
2474}
2475
2476#[test]
2477fn cross_crate_associated_method_call() {
2478 let (db, pos) = TestDB::with_position(
2479 r#"
2480//- /main.rs crate:main deps:other_crate
2481fn test() {
2482 let x = other_crate::foo::S::thing();
2483 x<|>;
2484}
2485
2486//- /lib.rs crate:other_crate
2487mod foo {
2488 struct S;
2489 impl S {
2490 fn thing() -> i128 {}
2491 }
2492}
2493"#,
2494 );
2495 assert_eq!("i128", type_at_pos(&db, pos));
2496}
2497
2498#[test]
2499fn infer_const() {
2500 assert_snapshot!(
2501 infer(r#"
2502struct Foo;
2503impl Foo { const ASSOC_CONST: u32 = 0; }
2504const GLOBAL_CONST: u32 = 101;
2505fn test() {
2506 const LOCAL_CONST: u32 = 99;
2507 let x = LOCAL_CONST;
2508 let z = GLOBAL_CONST;
2509 let id = Foo::ASSOC_CONST;
2510}
2511"#),
2512 @r###"
2513 [49; 50) '0': u32
2514 [80; 83) '101': u32
2515 [95; 213) '{ ...NST; }': ()
2516 [138; 139) 'x': {unknown}
2517 [142; 153) 'LOCAL_CONST': {unknown}
2518 [163; 164) 'z': u32
2519 [167; 179) 'GLOBAL_CONST': u32
2520 [189; 191) 'id': u32
2521 [194; 210) 'Foo::A..._CONST': u32
2522 "###
2523 );
2524}
2525
2526#[test]
2527fn infer_static() {
2528 assert_snapshot!(
2529 infer(r#"
2530static GLOBAL_STATIC: u32 = 101;
2531static mut GLOBAL_STATIC_MUT: u32 = 101;
2532fn test() {
2533 static LOCAL_STATIC: u32 = 99;
2534 static mut LOCAL_STATIC_MUT: u32 = 99;
2535 let x = LOCAL_STATIC;
2536 let y = LOCAL_STATIC_MUT;
2537 let z = GLOBAL_STATIC;
2538 let w = GLOBAL_STATIC_MUT;
2539}
2540"#),
2541 @r###"
2542 [29; 32) '101': u32
2543 [70; 73) '101': u32
2544 [85; 280) '{ ...MUT; }': ()
2545 [173; 174) 'x': {unknown}
2546 [177; 189) 'LOCAL_STATIC': {unknown}
2547 [199; 200) 'y': {unknown}
2548 [203; 219) 'LOCAL_...IC_MUT': {unknown}
2549 [229; 230) 'z': u32
2550 [233; 246) 'GLOBAL_STATIC': u32
2551 [256; 257) 'w': u32
2552 [260; 277) 'GLOBAL...IC_MUT': u32
2553 "###
2554 );
2555}
2556
2557#[test]
2558fn infer_trait_method_simple() {
2559 // the trait implementation is intentionally incomplete -- it shouldn't matter
2560 assert_snapshot!(
2561 infer(r#"
2562trait Trait1 {
2563 fn method(&self) -> u32;
2564}
2565struct S1;
2566impl Trait1 for S1 {}
2567trait Trait2 {
2568 fn method(&self) -> i128;
2569}
2570struct S2;
2571impl Trait2 for S2 {}
2572fn test() {
2573 S1.method(); // -> u32
2574 S2.method(); // -> i128
2575}
2576"#),
2577 @r###"
2578 [31; 35) 'self': &Self
2579 [110; 114) 'self': &Self
2580 [170; 228) '{ ...i128 }': ()
2581 [176; 178) 'S1': S1
2582 [176; 187) 'S1.method()': u32
2583 [203; 205) 'S2': S2
2584 [203; 214) 'S2.method()': i128
2585 "###
2586 );
2587}
2588
2589#[test]
2590fn infer_trait_method_scoped() {
2591 // the trait implementation is intentionally incomplete -- it shouldn't matter
2592 assert_snapshot!(
2593 infer(r#"
2594struct S;
2595mod foo {
2596 pub trait Trait1 {
2597 fn method(&self) -> u32;
2598 }
2599 impl Trait1 for super::S {}
2600}
2601mod bar {
2602 pub trait Trait2 {
2603 fn method(&self) -> i128;
2604 }
2605 impl Trait2 for super::S {}
2606}
2607
2608mod foo_test {
2609 use super::S;
2610 use super::foo::Trait1;
2611 fn test() {
2612 S.method(); // -> u32
2613 }
2614}
2615
2616mod bar_test {
2617 use super::S;
2618 use super::bar::Trait2;
2619 fn test() {
2620 S.method(); // -> i128
2621 }
2622}
2623"#),
2624 @r###"
2625 [63; 67) 'self': &Self
2626 [169; 173) 'self': &Self
2627 [300; 337) '{ ... }': ()
2628 [310; 311) 'S': S
2629 [310; 320) 'S.method()': u32
2630 [416; 454) '{ ... }': ()
2631 [426; 427) 'S': S
2632 [426; 436) 'S.method()': i128
2633 "###
2634 );
2635}
2636
2637#[test]
2638fn infer_trait_method_generic_1() {
2639 // the trait implementation is intentionally incomplete -- it shouldn't matter
2640 assert_snapshot!(
2641 infer(r#"
2642trait Trait<T> {
2643 fn method(&self) -> T;
2644}
2645struct S;
2646impl Trait<u32> for S {}
2647fn test() {
2648 S.method();
2649}
2650"#),
2651 @r###"
2652 [33; 37) 'self': &Self
2653 [92; 111) '{ ...d(); }': ()
2654 [98; 99) 'S': S
2655 [98; 108) 'S.method()': u32
2656 "###
2657 );
2658}
2659
2660#[test]
2661fn infer_trait_method_generic_more_params() {
2662 // the trait implementation is intentionally incomplete -- it shouldn't matter
2663 assert_snapshot!(
2664 infer(r#"
2665trait Trait<T1, T2, T3> {
2666 fn method1(&self) -> (T1, T2, T3);
2667 fn method2(&self) -> (T3, T2, T1);
2668}
2669struct S1;
2670impl Trait<u8, u16, u32> for S1 {}
2671struct S2;
2672impl<T> Trait<i8, i16, T> for S2 {}
2673fn test() {
2674 S1.method1(); // u8, u16, u32
2675 S1.method2(); // u32, u16, u8
2676 S2.method1(); // i8, i16, {unknown}
2677 S2.method2(); // {unknown}, i16, i8
2678}
2679"#),
2680 @r###"
2681 [43; 47) 'self': &Self
2682 [82; 86) 'self': &Self
2683 [210; 361) '{ ..., i8 }': ()
2684 [216; 218) 'S1': S1
2685 [216; 228) 'S1.method1()': (u8, u16, u32)
2686 [250; 252) 'S1': S1
2687 [250; 262) 'S1.method2()': (u32, u16, u8)
2688 [284; 286) 'S2': S2
2689 [284; 296) 'S2.method1()': (i8, i16, {unknown})
2690 [324; 326) 'S2': S2
2691 [324; 336) 'S2.method2()': ({unknown}, i16, i8)
2692 "###
2693 );
2694}
2695
2696#[test]
2697fn infer_trait_method_generic_2() {
2698 // the trait implementation is intentionally incomplete -- it shouldn't matter
2699 assert_snapshot!(
2700 infer(r#"
2701trait Trait<T> {
2702 fn method(&self) -> T;
2703}
2704struct S<T>(T);
2705impl<U> Trait<U> for S<U> {}
2706fn test() {
2707 S(1u32).method();
2708}
2709"#),
2710 @r###"
2711 [33; 37) 'self': &Self
2712 [102; 127) '{ ...d(); }': ()
2713 [108; 109) 'S': S<u32>(T) -> S<T>
2714 [108; 115) 'S(1u32)': S<u32>
2715 [108; 124) 'S(1u32...thod()': u32
2716 [110; 114) '1u32': u32
2717 "###
2718 );
2719}
2720
2721#[test]
2722fn infer_trait_assoc_method() {
2723 assert_snapshot!(
2724 infer(r#"
2725trait Default {
2726 fn default() -> Self;
2727}
2728struct S;
2729impl Default for S {}
2730fn test() {
2731 let s1: S = Default::default();
2732 let s2 = S::default();
2733 let s3 = <S as Default>::default();
2734}
2735"#),
2736 @r###"
2737 [87; 193) '{ ...t(); }': ()
2738 [97; 99) 's1': S
2739 [105; 121) 'Defaul...efault': fn default<S>() -> Self
2740 [105; 123) 'Defaul...ault()': S
2741 [133; 135) 's2': S
2742 [138; 148) 'S::default': fn default<S>() -> Self
2743 [138; 150) 'S::default()': S
2744 [160; 162) 's3': S
2745 [165; 188) '<S as ...efault': fn default<S>() -> Self
2746 [165; 190) '<S as ...ault()': S
2747 "###
2748 );
2749}
2750
2751#[test]
2752fn infer_trait_assoc_method_generics_1() {
2753 assert_snapshot!(
2754 infer(r#"
2755trait Trait<T> {
2756 fn make() -> T;
2757}
2758struct S;
2759impl Trait<u32> for S {}
2760struct G<T>;
2761impl<T> Trait<T> for G<T> {}
2762fn test() {
2763 let a = S::make();
2764 let b = G::<u64>::make();
2765 let c: f64 = G::make();
2766}
2767"#),
2768 @r###"
2769 [127; 211) '{ ...e(); }': ()
2770 [137; 138) 'a': u32
2771 [141; 148) 'S::make': fn make<S, u32>() -> T
2772 [141; 150) 'S::make()': u32
2773 [160; 161) 'b': u64
2774 [164; 178) 'G::<u64>::make': fn make<G<u64>, u64>() -> T
2775 [164; 180) 'G::<u6...make()': u64
2776 [190; 191) 'c': f64
2777 [199; 206) 'G::make': fn make<G<f64>, f64>() -> T
2778 [199; 208) 'G::make()': f64
2779 "###
2780 );
2781}
2782
2783#[test]
2784fn infer_trait_assoc_method_generics_2() {
2785 assert_snapshot!(
2786 infer(r#"
2787trait Trait<T> {
2788 fn make<U>() -> (T, U);
2789}
2790struct S;
2791impl Trait<u32> for S {}
2792struct G<T>;
2793impl<T> Trait<T> for G<T> {}
2794fn test() {
2795 let a = S::make::<i64>();
2796 let b: (_, i64) = S::make();
2797 let c = G::<u32>::make::<i64>();
2798 let d: (u32, _) = G::make::<i64>();
2799 let e: (u32, i64) = G::make();
2800}
2801"#),
2802 @r###"
2803 [135; 313) '{ ...e(); }': ()
2804 [145; 146) 'a': (u32, i64)
2805 [149; 163) 'S::make::<i64>': fn make<S, u32, i64>() -> (T, U)
2806 [149; 165) 'S::mak...i64>()': (u32, i64)
2807 [175; 176) 'b': (u32, i64)
2808 [189; 196) 'S::make': fn make<S, u32, i64>() -> (T, U)
2809 [189; 198) 'S::make()': (u32, i64)
2810 [208; 209) 'c': (u32, i64)
2811 [212; 233) 'G::<u3...:<i64>': fn make<G<u32>, u32, i64>() -> (T, U)
2812 [212; 235) 'G::<u3...i64>()': (u32, i64)
2813 [245; 246) 'd': (u32, i64)
2814 [259; 273) 'G::make::<i64>': fn make<G<u32>, u32, i64>() -> (T, U)
2815 [259; 275) 'G::mak...i64>()': (u32, i64)
2816 [285; 286) 'e': (u32, i64)
2817 [301; 308) 'G::make': fn make<G<u32>, u32, i64>() -> (T, U)
2818 [301; 310) 'G::make()': (u32, i64)
2819 "###
2820 );
2821}
2822
2823#[test]
2824fn infer_trait_assoc_method_generics_3() {
2825 assert_snapshot!(
2826 infer(r#"
2827trait Trait<T> {
2828 fn make() -> (Self, T);
2829}
2830struct S<T>;
2831impl Trait<i64> for S<i32> {}
2832fn test() {
2833 let a = S::make();
2834}
2835"#),
2836 @r###"
2837 [101; 127) '{ ...e(); }': ()
2838 [111; 112) 'a': (S<i32>, i64)
2839 [115; 122) 'S::make': fn make<S<i32>, i64>() -> (Self, T)
2840 [115; 124) 'S::make()': (S<i32>, i64)
2841 "###
2842 );
2843}
2844
2845#[test]
2846fn infer_trait_assoc_method_generics_4() {
2847 assert_snapshot!(
2848 infer(r#"
2849trait Trait<T> {
2850 fn make() -> (Self, T);
2851}
2852struct S<T>;
2853impl Trait<i64> for S<u64> {}
2854impl Trait<i32> for S<u32> {}
2855fn test() {
2856 let a: (S<u64>, _) = S::make();
2857 let b: (_, i32) = S::make();
2858}
2859"#),
2860 @r###"
2861 [131; 203) '{ ...e(); }': ()
2862 [141; 142) 'a': (S<u64>, i64)
2863 [158; 165) 'S::make': fn make<S<u64>, i64>() -> (Self, T)
2864 [158; 167) 'S::make()': (S<u64>, i64)
2865 [177; 178) 'b': (S<u32>, i32)
2866 [191; 198) 'S::make': fn make<S<u32>, i32>() -> (Self, T)
2867 [191; 200) 'S::make()': (S<u32>, i32)
2868 "###
2869 );
2870}
2871
2872#[test]
2873fn infer_trait_assoc_method_generics_5() {
2874 assert_snapshot!(
2875 infer(r#"
2876trait Trait<T> {
2877 fn make<U>() -> (Self, T, U);
2878}
2879struct S<T>;
2880impl Trait<i64> for S<u64> {}
2881fn test() {
2882 let a = <S as Trait<i64>>::make::<u8>();
2883 let b: (S<u64>, _, _) = Trait::<i64>::make::<u8>();
2884}
2885"#),
2886 @r###"
2887 [107; 211) '{ ...>(); }': ()
2888 [117; 118) 'a': (S<u64>, i64, u8)
2889 [121; 150) '<S as ...::<u8>': fn make<S<u64>, i64, u8>() -> (Self, T, U)
2890 [121; 152) '<S as ...<u8>()': (S<u64>, i64, u8)
2891 [162; 163) 'b': (S<u64>, i64, u8)
2892 [182; 206) 'Trait:...::<u8>': fn make<S<u64>, i64, u8>() -> (Self, T, U)
2893 [182; 208) 'Trait:...<u8>()': (S<u64>, i64, u8)
2894 "###
2895 );
2896}
2897
2898#[test]
2899fn infer_from_bound_1() {
2900 assert_snapshot!(
2901 infer(r#"
2902trait Trait<T> {}
2903struct S<T>(T);
2904impl<U> Trait<U> for S<U> {}
2905fn foo<T: Trait<u32>>(t: T) {}
2906fn test() {
2907 let s = S(unknown);
2908 foo(s);
2909}
2910"#),
2911 @r###"
2912 [86; 87) 't': T
2913 [92; 94) '{}': ()
2914 [105; 144) '{ ...(s); }': ()
2915 [115; 116) 's': S<u32>
2916 [119; 120) 'S': S<u32>(T) -> S<T>
2917 [119; 129) 'S(unknown)': S<u32>
2918 [121; 128) 'unknown': u32
2919 [135; 138) 'foo': fn foo<S<u32>>(T) -> ()
2920 [135; 141) 'foo(s)': ()
2921 [139; 140) 's': S<u32>
2922 "###
2923 );
2924}
2925
2926#[test]
2927fn infer_from_bound_2() {
2928 assert_snapshot!(
2929 infer(r#"
2930trait Trait<T> {}
2931struct S<T>(T);
2932impl<U> Trait<U> for S<U> {}
2933fn foo<U, T: Trait<U>>(t: T) -> U {}
2934fn test() {
2935 let s = S(unknown);
2936 let x: u32 = foo(s);
2937}
2938"#),
2939 @r###"
2940 [87; 88) 't': T
2941 [98; 100) '{}': ()
2942 [111; 163) '{ ...(s); }': ()
2943 [121; 122) 's': S<u32>
2944 [125; 126) 'S': S<u32>(T) -> S<T>
2945 [125; 135) 'S(unknown)': S<u32>
2946 [127; 134) 'unknown': u32
2947 [145; 146) 'x': u32
2948 [154; 157) 'foo': fn foo<u32, S<u32>>(T) -> U
2949 [154; 160) 'foo(s)': u32
2950 [158; 159) 's': S<u32>
2951 "###
2952 );
2953}
2954
2955#[test]
2956fn infer_call_trait_method_on_generic_param_1() {
2957 assert_snapshot!(
2958 infer(r#"
2959trait Trait {
2960 fn method(&self) -> u32;
2961}
2962fn test<T: Trait>(t: T) {
2963 t.method();
2964}
2965"#),
2966 @r###"
2967 [30; 34) 'self': &Self
2968 [64; 65) 't': T
2969 [70; 89) '{ ...d(); }': ()
2970 [76; 77) 't': T
2971 [76; 86) 't.method()': u32
2972 "###
2973 );
2974}
2975
2976#[test]
2977fn infer_call_trait_method_on_generic_param_2() {
2978 assert_snapshot!(
2979 infer(r#"
2980trait Trait<T> {
2981 fn method(&self) -> T;
2982}
2983fn test<U, T: Trait<U>>(t: T) {
2984 t.method();
2985}
2986"#),
2987 @r###"
2988 [33; 37) 'self': &Self
2989 [71; 72) 't': T
2990 [77; 96) '{ ...d(); }': ()
2991 [83; 84) 't': T
2992 [83; 93) 't.method()': [missing name]
2993 "###
2994 );
2995}
2996
2997#[test]
2998fn infer_with_multiple_trait_impls() {
2999 assert_snapshot!(
3000 infer(r#"
3001trait Into<T> {
3002 fn into(self) -> T;
3003}
3004struct S;
3005impl Into<u32> for S {}
3006impl Into<u64> for S {}
3007fn test() {
3008 let x: u32 = S.into();
3009 let y: u64 = S.into();
3010 let z = Into::<u64>::into(S);
3011}
3012"#),
3013 @r###"
3014 [29; 33) 'self': Self
3015 [111; 202) '{ ...(S); }': ()
3016 [121; 122) 'x': u32
3017 [130; 131) 'S': S
3018 [130; 138) 'S.into()': u32
3019 [148; 149) 'y': u64
3020 [157; 158) 'S': S
3021 [157; 165) 'S.into()': u64
3022 [175; 176) 'z': u64
3023 [179; 196) 'Into::...::into': fn into<S, u64>(Self) -> T
3024 [179; 199) 'Into::...nto(S)': u64
3025 [197; 198) 'S': S
3026 "###
3027 );
3028}
3029
3030#[test]
3031fn infer_project_associated_type() {
3032 // y, z, a don't yet work because of https://github.com/rust-lang/chalk/issues/234
3033 assert_snapshot!(
3034 infer(r#"
3035trait Iterable {
3036 type Item;
3037}
3038struct S;
3039impl Iterable for S { type Item = u32; }
3040fn test<T: Iterable>() {
3041 let x: <S as Iterable>::Item = 1;
3042 let y: <T as Iterable>::Item = no_matter;
3043 let z: T::Item = no_matter;
3044 let a: <T>::Item = no_matter;
3045}
3046"#),
3047 @r###"
3048 [108; 261) '{ ...ter; }': ()
3049 [118; 119) 'x': u32
3050 [145; 146) '1': u32
3051 [156; 157) 'y': {unknown}
3052 [183; 192) 'no_matter': {unknown}
3053 [202; 203) 'z': {unknown}
3054 [215; 224) 'no_matter': {unknown}
3055 [234; 235) 'a': {unknown}
3056 [249; 258) 'no_matter': {unknown}
3057 "###
3058 );
3059}
3060
3061#[test]
3062fn infer_return_associated_type() {
3063 assert_snapshot!(
3064 infer(r#"
3065trait Iterable {
3066 type Item;
3067}
3068struct S;
3069impl Iterable for S { type Item = u32; }
3070fn foo1<T: Iterable>(t: T) -> T::Item {}
3071fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item {}
3072fn foo3<T: Iterable>(t: T) -> <T>::Item {}
3073fn test() {
3074 let x = foo1(S);
3075 let y = foo2(S);
3076 let z = foo3(S);
3077}
3078"#),
3079 @r###"
3080 [106; 107) 't': T
3081 [123; 125) '{}': ()
3082 [147; 148) 't': T
3083 [178; 180) '{}': ()
3084 [202; 203) 't': T
3085 [221; 223) '{}': ()
3086 [234; 300) '{ ...(S); }': ()
3087 [244; 245) 'x': u32
3088 [248; 252) 'foo1': fn foo1<S>(T) -> <T as Iterable>::Item
3089 [248; 255) 'foo1(S)': u32
3090 [253; 254) 'S': S
3091 [265; 266) 'y': u32
3092 [269; 273) 'foo2': fn foo2<S>(T) -> <T as Iterable>::Item
3093 [269; 276) 'foo2(S)': u32
3094 [274; 275) 'S': S
3095 [286; 287) 'z': u32
3096 [290; 294) 'foo3': fn foo3<S>(T) -> <T as Iterable>::Item
3097 [290; 297) 'foo3(S)': u32
3098 [295; 296) 'S': S
3099 "###
3100 );
3101}
3102
3103#[test]
3104fn infer_associated_type_bound() {
3105 assert_snapshot!(
3106 infer(r#"
3107trait Iterable {
3108 type Item;
3109}
3110fn test<T: Iterable<Item=u32>>() {
3111 let y: T::Item = unknown;
3112}
3113"#),
3114 @r###"
3115 [67; 100) '{ ...own; }': ()
3116 [77; 78) 'y': {unknown}
3117 [90; 97) 'unknown': {unknown}
3118 "###
3119 );
3120}
3121
3122#[test]
3123fn infer_const_body() {
3124 assert_snapshot!(
3125 infer(r#"
3126const A: u32 = 1 + 1;
3127static B: u64 = { let x = 1; x };
3128"#),
3129 @r###"
3130 [16; 17) '1': u32
3131 [16; 21) '1 + 1': u32
3132 [20; 21) '1': u32
3133 [39; 55) '{ let ...1; x }': u64
3134 [45; 46) 'x': u64
3135 [49; 50) '1': u64
3136 [52; 53) 'x': u64
3137 "###
3138 );
3139}
3140
3141#[test]
3142fn tuple_struct_fields() {
3143 assert_snapshot!(
3144 infer(r#"
3145struct S(i32, u64);
3146fn test() -> u64 {
3147 let a = S(4, 6);
3148 let b = a.0;
3149 a.1
3150}
3151"#),
3152 @r###"
3153 [38; 87) '{ ... a.1 }': u64
3154 [48; 49) 'a': S
3155 [52; 53) 'S': S(i32, u64) -> S
3156 [52; 59) 'S(4, 6)': S
3157 [54; 55) '4': i32
3158 [57; 58) '6': u64
3159 [69; 70) 'b': i32
3160 [73; 74) 'a': S
3161 [73; 76) 'a.0': i32
3162 [82; 83) 'a': S
3163 [82; 85) 'a.1': u64
3164 "###
3165 );
3166}
3167
3168#[test]
3169fn tuple_struct_with_fn() {
3170 assert_snapshot!(
3171 infer(r#"
3172struct S(fn(u32) -> u64);
3173fn test() -> u64 {
3174 let a = S(|i| 2*i);
3175 let b = a.0(4);
3176 a.0(2)
3177}
3178"#),
3179 @r###"
3180 [44; 102) '{ ...0(2) }': u64
3181 [54; 55) 'a': S
3182 [58; 59) 'S': S(fn(u32) -> u64) -> S
3183 [58; 68) 'S(|i| 2*i)': S
3184 [60; 67) '|i| 2*i': |i32| -> i32
3185 [61; 62) 'i': i32
3186 [64; 65) '2': i32
3187 [64; 67) '2*i': i32
3188 [66; 67) 'i': i32
3189 [78; 79) 'b': u64
3190 [82; 83) 'a': S
3191 [82; 85) 'a.0': fn(u32) -> u64
3192 [82; 88) 'a.0(4)': u64
3193 [86; 87) '4': u32
3194 [94; 95) 'a': S
3195 [94; 97) 'a.0': fn(u32) -> u64
3196 [94; 100) 'a.0(2)': u64
3197 [98; 99) '2': u32
3198 "###
3199 );
3200}
3201
3202#[test]
3203fn indexing_arrays() {
3204 assert_snapshot!(
3205 infer("fn main() { &mut [9][2]; }"),
3206 @r###"
3207 [10; 26) '{ &mut...[2]; }': ()
3208 [12; 23) '&mut [9][2]': &mut {unknown}
3209 [17; 20) '[9]': [i32;_]
3210 [17; 23) '[9][2]': {unknown}
3211 [18; 19) '9': i32
3212 [21; 22) '2': i32
3213 "###
3214 )
3215}
3216
3217#[test]
3218fn infer_macros_expanded() {
3219 assert_snapshot!(
3220 infer(r#"
3221struct Foo(Vec<i32>);
3222
3223macro_rules! foo {
3224 ($($item:expr),*) => {
3225 {
3226 Foo(vec![$($item,)*])
3227 }
3228 };
3229}
3230
3231fn main() {
3232 let x = foo!(1,2);
3233}
3234"#),
3235 @r###"
3236 ![0; 17) '{Foo(v...,2,])}': Foo
3237 ![1; 4) 'Foo': Foo({unknown}) -> Foo
3238 ![1; 16) 'Foo(vec![1,2,])': Foo
3239 ![5; 15) 'vec![1,2,]': {unknown}
3240 [156; 182) '{ ...,2); }': ()
3241 [166; 167) 'x': Foo
3242 "###
3243 );
3244}
3245
3246#[test]
3247fn infer_legacy_textual_scoped_macros_expanded() {
3248 assert_snapshot!(
3249 infer(r#"
3250struct Foo(Vec<i32>);
3251
3252#[macro_use]
3253mod m {
3254 macro_rules! foo {
3255 ($($item:expr),*) => {
3256 {
3257 Foo(vec![$($item,)*])
3258 }
3259 };
3260 }
3261}
3262
3263fn main() {
3264 let x = foo!(1,2);
3265 let y = crate::foo!(1,2);
3266}
3267"#),
3268 @r###"
3269 ![0; 17) '{Foo(v...,2,])}': Foo
3270 ![1; 4) 'Foo': Foo({unknown}) -> Foo
3271 ![1; 16) 'Foo(vec![1,2,])': Foo
3272 ![5; 15) 'vec![1,2,]': {unknown}
3273 [195; 251) '{ ...,2); }': ()
3274 [205; 206) 'x': Foo
3275 [228; 229) 'y': {unknown}
3276 [232; 248) 'crate:...!(1,2)': {unknown}
3277 "###
3278 );
3279}
3280
3281#[test]
3282fn infer_path_qualified_macros_expanded() {
3283 assert_snapshot!(
3284 infer(r#"
3285#[macro_export]
3286macro_rules! foo {
3287 () => { 42i32 }
3288}
3289
3290mod m {
3291 pub use super::foo as bar;
3292}
3293
3294fn main() {
3295 let x = crate::foo!();
3296 let y = m::bar!();
3297}
3298"#),
3299 @r###"
3300 ![0; 5) '42i32': i32
3301 ![0; 5) '42i32': i32
3302 [111; 164) '{ ...!(); }': ()
3303 [121; 122) 'x': i32
3304 [148; 149) 'y': i32
3305 "###
3306 );
3307}
3308
3309#[test]
3310fn infer_type_value_macro_having_same_name() {
3311 assert_snapshot!(
3312 infer(r#"
3313#[macro_export]
3314macro_rules! foo {
3315 () => {
3316 mod foo {
3317 pub use super::foo;
3318 }
3319 };
3320 ($x:tt) => {
3321 $x
3322 };
3323}
3324
3325foo!();
3326
3327fn foo() {
3328 let foo = foo::foo!(42i32);
3329}
3330"#),
3331 @r###"
3332 ![0; 5) '42i32': i32
3333 [171; 206) '{ ...32); }': ()
3334 [181; 184) 'foo': i32
3335 "###
3336 );
3337}
3338
3339#[test]
3340fn processes_impls_generated_by_macros() {
3341 let t = type_at(
3342 r#"
3343//- /main.rs
3344macro_rules! m {
3345 ($ident:ident) => (impl Trait for $ident {})
3346}
3347trait Trait { fn foo(self) -> u128 {} }
3348struct S;
3349m!(S);
3350fn test() { S.foo()<|>; }
3351"#,
3352 );
3353 assert_eq!(t, "u128");
3354}
3355
3356#[test]
3357fn infer_macro_with_dollar_crate_is_correct_in_expr() {
3358 let (db, pos) = TestDB::with_position(
3359 r#"
3360//- /main.rs crate:main deps:foo
3361fn test() {
3362 let x = (foo::foo!(1), foo::foo!(2));
3363 x<|>;
3364}
3365
3366//- /lib.rs crate:foo
3367#[macro_export]
3368macro_rules! foo {
3369 (1) => { $crate::bar!() };
3370 (2) => { 1 + $crate::baz() };
3371}
3372
3373#[macro_export]
3374macro_rules! bar {
3375 () => { 42 }
3376}
3377
3378pub fn baz() -> usize { 31usize }
3379"#,
3380 );
3381 assert_eq!("(i32, usize)", type_at_pos(&db, pos));
3382}
3383
3384#[ignore]
3385#[test]
3386fn method_resolution_trait_before_autoref() {
3387 let t = type_at(
3388 r#"
3389//- /main.rs
3390trait Trait { fn foo(self) -> u128; }
3391struct S;
3392impl S { fn foo(&self) -> i8 { 0 } }
3393impl Trait for S { fn foo(self) -> u128 { 0 } }
3394fn test() { S.foo()<|>; }
3395"#,
3396 );
3397 assert_eq!(t, "u128");
3398}
3399
3400#[ignore]
3401#[test]
3402fn method_resolution_by_value_before_autoref() {
3403 let t = type_at(
3404 r#"
3405//- /main.rs
3406trait Clone { fn clone(&self) -> Self; }
3407struct S;
3408impl Clone for S {}
3409impl Clone for &S {}
3410fn test() { (S.clone(), (&S).clone(), (&&S).clone())<|>; }
3411"#,
3412 );
3413 assert_eq!(t, "(S, S, &S)");
3414}
3415
3416#[test]
3417fn method_resolution_trait_before_autoderef() {
3418 let t = type_at(
3419 r#"
3420//- /main.rs
3421trait Trait { fn foo(self) -> u128; }
3422struct S;
3423impl S { fn foo(self) -> i8 { 0 } }
3424impl Trait for &S { fn foo(self) -> u128 { 0 } }
3425fn test() { (&S).foo()<|>; }
3426"#,
3427 );
3428 assert_eq!(t, "u128");
3429}
3430
3431#[test]
3432fn method_resolution_impl_before_trait() {
3433 let t = type_at(
3434 r#"
3435//- /main.rs
3436trait Trait { fn foo(self) -> u128; }
3437struct S;
3438impl S { fn foo(self) -> i8 { 0 } }
3439impl Trait for S { fn foo(self) -> u128 { 0 } }
3440fn test() { S.foo()<|>; }
3441"#,
3442 );
3443 assert_eq!(t, "i8");
3444}
3445
3446#[test]
3447fn method_resolution_trait_autoderef() {
3448 let t = type_at(
3449 r#"
3450//- /main.rs
3451trait Trait { fn foo(self) -> u128; }
3452struct S;
3453impl Trait for S { fn foo(self) -> u128 { 0 } }
3454fn test() { (&S).foo()<|>; }
3455"#,
3456 );
3457 assert_eq!(t, "u128");
3458}
3459
3460#[test]
3461fn method_resolution_trait_from_prelude() {
3462 let (db, pos) = TestDB::with_position(
3463 r#"
3464//- /main.rs crate:main deps:other_crate
3465struct S;
3466impl Clone for S {}
3467
3468fn test() {
3469 S.clone()<|>;
3470}
3471
3472//- /lib.rs crate:other_crate
3473#[prelude_import] use foo::*;
3474
3475mod foo {
3476 trait Clone {
3477 fn clone(&self) -> Self;
3478 }
3479}
3480"#,
3481 );
3482 assert_eq!("S", type_at_pos(&db, pos));
3483}
3484
3485#[test]
3486fn method_resolution_where_clause_for_unknown_trait() {
3487 // The blanket impl shouldn't apply because we can't even resolve UnknownTrait
3488 let t = type_at(
3489 r#"
3490//- /main.rs
3491trait Trait { fn foo(self) -> u128; }
3492struct S;
3493impl<T> Trait for T where T: UnknownTrait {}
3494fn test() { (&S).foo()<|>; }
3495"#,
3496 );
3497 assert_eq!(t, "{unknown}");
3498}
3499
3500#[test]
3501fn method_resolution_where_clause_not_met() {
3502 // The blanket impl shouldn't apply because we can't prove S: Clone
3503 let t = type_at(
3504 r#"
3505//- /main.rs
3506trait Clone {}
3507trait Trait { fn foo(self) -> u128; }
3508struct S;
3509impl<T> Trait for T where T: Clone {}
3510fn test() { (&S).foo()<|>; }
3511"#,
3512 );
3513 // This is also to make sure that we don't resolve to the foo method just
3514 // because that's the only method named foo we can find, which would make
3515 // the below tests not work
3516 assert_eq!(t, "{unknown}");
3517}
3518
3519#[test]
3520fn method_resolution_where_clause_inline_not_met() {
3521 // The blanket impl shouldn't apply because we can't prove S: Clone
3522 let t = type_at(
3523 r#"
3524//- /main.rs
3525trait Clone {}
3526trait Trait { fn foo(self) -> u128; }
3527struct S;
3528impl<T: Clone> Trait for T {}
3529fn test() { (&S).foo()<|>; }
3530"#,
3531 );
3532 assert_eq!(t, "{unknown}");
3533}
3534
3535#[test]
3536fn method_resolution_where_clause_1() {
3537 let t = type_at(
3538 r#"
3539//- /main.rs
3540trait Clone {}
3541trait Trait { fn foo(self) -> u128; }
3542struct S;
3543impl Clone for S {}
3544impl<T> Trait for T where T: Clone {}
3545fn test() { S.foo()<|>; }
3546"#,
3547 );
3548 assert_eq!(t, "u128");
3549}
3550
3551#[test]
3552fn method_resolution_where_clause_2() {
3553 let t = type_at(
3554 r#"
3555//- /main.rs
3556trait Into<T> { fn into(self) -> T; }
3557trait From<T> { fn from(other: T) -> Self; }
3558struct S1;
3559struct S2;
3560impl From<S2> for S1 {}
3561impl<T, U> Into<U> for T where U: From<T> {}
3562fn test() { S2.into()<|>; }
3563"#,
3564 );
3565 assert_eq!(t, "{unknown}");
3566}
3567
3568#[test]
3569fn method_resolution_where_clause_inline() {
3570 let t = type_at(
3571 r#"
3572//- /main.rs
3573trait Into<T> { fn into(self) -> T; }
3574trait From<T> { fn from(other: T) -> Self; }
3575struct S1;
3576struct S2;
3577impl From<S2> for S1 {}
3578impl<T, U: From<T>> Into<U> for T {}
3579fn test() { S2.into()<|>; }
3580"#,
3581 );
3582 assert_eq!(t, "{unknown}");
3583}
3584
3585#[test]
3586fn method_resolution_encountering_fn_type() {
3587 type_at(
3588 r#"
3589//- /main.rs
3590fn foo() {}
3591trait FnOnce { fn call(self); }
3592fn test() { foo.call()<|>; }
3593"#,
3594 );
3595}
3596
3597#[test]
3598fn method_resolution_slow() {
3599 // this can get quite slow if we set the solver size limit too high
3600 let t = type_at(
3601 r#"
3602//- /main.rs
3603trait SendX {}
3604
3605struct S1; impl SendX for S1 {}
3606struct S2; impl SendX for S2 {}
3607struct U1;
3608
3609trait Trait { fn method(self); }
3610
3611struct X1<A, B> {}
3612impl<A, B> SendX for X1<A, B> where A: SendX, B: SendX {}
3613
3614struct S<B, C> {}
3615
3616trait FnX {}
3617
3618impl<B, C> Trait for S<B, C> where C: FnX, B: SendX {}
3619
3620fn test() { (S {}).method()<|>; }
3621"#,
3622 );
3623 assert_eq!(t, "()");
3624}
3625
3626#[test]
3627fn shadowing_primitive() {
3628 let t = type_at(
3629 r#"
3630//- /main.rs
3631struct i32;
3632struct Foo;
3633
3634impl i32 { fn foo(&self) -> Foo { Foo } }
3635
3636fn main() {
3637 let x: i32 = i32;
3638 x.foo()<|>;
3639}"#,
3640 );
3641 assert_eq!(t, "Foo");
3642}
3643
3644#[test]
3645fn deref_trait() {
3646 let t = type_at(
3647 r#"
3648//- /main.rs
3649#[lang = "deref"]
3650trait Deref {
3651 type Target;
3652 fn deref(&self) -> &Self::Target;
3653}
3654
3655struct Arc<T>;
3656impl<T> Deref for Arc<T> {
3657 type Target = T;
3658}
3659
3660struct S;
3661impl S {
3662 fn foo(&self) -> u128 {}
3663}
3664
3665fn test(s: Arc<S>) {
3666 (*s, s.foo())<|>;
3667}
3668"#,
3669 );
3670 assert_eq!(t, "(S, u128)");
3671}
3672
3673#[test]
3674fn deref_trait_with_inference_var() {
3675 let t = type_at(
3676 r#"
3677//- /main.rs
3678#[lang = "deref"]
3679trait Deref {
3680 type Target;
3681 fn deref(&self) -> &Self::Target;
3682}
3683
3684struct Arc<T>;
3685fn new_arc<T>() -> Arc<T> {}
3686impl<T> Deref for Arc<T> {
3687 type Target = T;
3688}
3689
3690struct S;
3691fn foo(a: Arc<S>) {}
3692
3693fn test() {
3694 let a = new_arc();
3695 let b = (*a)<|>;
3696 foo(a);
3697}
3698"#,
3699 );
3700 assert_eq!(t, "S");
3701}
3702
3703#[test]
3704fn deref_trait_infinite_recursion() {
3705 let t = type_at(
3706 r#"
3707//- /main.rs
3708#[lang = "deref"]
3709trait Deref {
3710 type Target;
3711 fn deref(&self) -> &Self::Target;
3712}
3713
3714struct S;
3715
3716impl Deref for S {
3717 type Target = S;
3718}
3719
3720fn test(s: S) {
3721 s.foo()<|>;
3722}
3723"#,
3724 );
3725 assert_eq!(t, "{unknown}");
3726}
3727
3728#[test]
3729fn deref_trait_with_question_mark_size() {
3730 let t = type_at(
3731 r#"
3732//- /main.rs
3733#[lang = "deref"]
3734trait Deref {
3735 type Target;
3736 fn deref(&self) -> &Self::Target;
3737}
3738
3739struct Arc<T>;
3740impl<T> Deref for Arc<T> {
3741 type Target = T;
3742}
3743
3744struct S;
3745impl S {
3746 fn foo(&self) -> u128 {}
3747}
3748
3749fn test(s: Arc<S>) {
3750 (*s, s.foo())<|>;
3751}
3752"#,
3753 );
3754 assert_eq!(t, "(S, u128)");
3755}
3756
3757#[test]
3758fn obligation_from_function_clause() {
3759 let t = type_at(
3760 r#"
3761//- /main.rs
3762struct S;
3763
3764trait Trait<T> {}
3765impl Trait<u32> for S {}
3766
3767fn foo<T: Trait<U>, U>(t: T) -> U {}
3768
3769fn test(s: S) {
3770 foo(s)<|>;
3771}
3772"#,
3773 );
3774 assert_eq!(t, "u32");
3775}
3776
3777#[test]
3778fn obligation_from_method_clause() {
3779 let t = type_at(
3780 r#"
3781//- /main.rs
3782struct S;
3783
3784trait Trait<T> {}
3785impl Trait<isize> for S {}
3786
3787struct O;
3788impl O {
3789 fn foo<T: Trait<U>, U>(&self, t: T) -> U {}
3790}
3791
3792fn test() {
3793 O.foo(S)<|>;
3794}
3795"#,
3796 );
3797 assert_eq!(t, "isize");
3798}
3799
3800#[test]
3801fn obligation_from_self_method_clause() {
3802 let t = type_at(
3803 r#"
3804//- /main.rs
3805struct S;
3806
3807trait Trait<T> {}
3808impl Trait<i64> for S {}
3809
3810impl S {
3811 fn foo<U>(&self) -> U where Self: Trait<U> {}
3812}
3813
3814fn test() {
3815 S.foo()<|>;
3816}
3817"#,
3818 );
3819 assert_eq!(t, "i64");
3820}
3821
3822#[test]
3823fn obligation_from_impl_clause() {
3824 let t = type_at(
3825 r#"
3826//- /main.rs
3827struct S;
3828
3829trait Trait<T> {}
3830impl Trait<&str> for S {}
3831
3832struct O<T>;
3833impl<U, T: Trait<U>> O<T> {
3834 fn foo(&self) -> U {}
3835}
3836
3837fn test(o: O<S>) {
3838 o.foo()<|>;
3839}
3840"#,
3841 );
3842 assert_eq!(t, "&str");
3843}
3844
3845#[test]
3846fn generic_param_env_1() {
3847 let t = type_at(
3848 r#"
3849//- /main.rs
3850trait Clone {}
3851trait Trait { fn foo(self) -> u128; }
3852struct S;
3853impl Clone for S {}
3854impl<T> Trait for T where T: Clone {}
3855fn test<T: Clone>(t: T) { t.foo()<|>; }
3856"#,
3857 );
3858 assert_eq!(t, "u128");
3859}
3860
3861#[test]
3862fn generic_param_env_1_not_met() {
3863 let t = type_at(
3864 r#"
3865//- /main.rs
3866trait Clone {}
3867trait Trait { fn foo(self) -> u128; }
3868struct S;
3869impl Clone for S {}
3870impl<T> Trait for T where T: Clone {}
3871fn test<T>(t: T) { t.foo()<|>; }
3872"#,
3873 );
3874 assert_eq!(t, "{unknown}");
3875}
3876
3877#[test]
3878fn generic_param_env_2() {
3879 let t = type_at(
3880 r#"
3881//- /main.rs
3882trait Trait { fn foo(self) -> u128; }
3883struct S;
3884impl Trait for S {}
3885fn test<T: Trait>(t: T) { t.foo()<|>; }
3886"#,
3887 );
3888 assert_eq!(t, "u128");
3889}
3890
3891#[test]
3892fn generic_param_env_2_not_met() {
3893 let t = type_at(
3894 r#"
3895//- /main.rs
3896trait Trait { fn foo(self) -> u128; }
3897struct S;
3898impl Trait for S {}
3899fn test<T>(t: T) { t.foo()<|>; }
3900"#,
3901 );
3902 assert_eq!(t, "{unknown}");
3903}
3904
3905#[test]
3906fn generic_param_env_deref() {
3907 let t = type_at(
3908 r#"
3909//- /main.rs
3910#[lang = "deref"]
3911trait Deref {
3912 type Target;
3913}
3914trait Trait {}
3915impl<T> Deref for T where T: Trait {
3916 type Target = i128;
3917}
3918fn test<T: Trait>(t: T) { (*t)<|>; }
3919"#,
3920 );
3921 assert_eq!(t, "i128");
3922}
3923
3924#[test]
3925fn associated_type_placeholder() {
3926 let t = type_at(
3927 r#"
3928//- /main.rs
3929pub trait ApplyL {
3930 type Out;
3931}
3932
3933pub struct RefMutL<T>;
3934
3935impl<T> ApplyL for RefMutL<T> {
3936 type Out = <T as ApplyL>::Out;
3937}
3938
3939fn test<T: ApplyL>() {
3940 let y: <RefMutL<T> as ApplyL>::Out = no_matter;
3941 y<|>;
3942}
3943"#,
3944 );
3945 // 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].
3946 // FIXME: fix type parameter names going missing when going through Chalk
3947 assert_eq!(t, "ApplyL::Out<[missing name]>");
3948}
3949
3950#[test]
3951fn associated_type_placeholder_2() {
3952 let t = type_at(
3953 r#"
3954//- /main.rs
3955pub trait ApplyL {
3956 type Out;
3957}
3958fn foo<T: ApplyL>(t: T) -> <T as ApplyL>::Out;
3959
3960fn test<T: ApplyL>(t: T) {
3961 let y = foo(t);
3962 y<|>;
3963}
3964"#,
3965 );
3966 // FIXME here Chalk doesn't normalize the type to a placeholder. I think we
3967 // need to add a rule like Normalize(<T as ApplyL>::Out -> ApplyL::Out<T>)
3968 // to the trait env ourselves here; probably Chalk can't do this by itself.
3969 // assert_eq!(t, "ApplyL::Out<[missing name]>");
3970 assert_eq!(t, "{unknown}");
3971}
3972
3973#[test]
3974fn impl_trait() {
3975 assert_snapshot!(
3976 infer(r#"
3977trait Trait<T> {
3978 fn foo(&self) -> T;
3979 fn foo2(&self) -> i64;
3980}
3981fn bar() -> impl Trait<u64> {}
3982
3983fn test(x: impl Trait<u64>, y: &impl Trait<u64>) {
3984 x;
3985 y;
3986 let z = bar();
3987 x.foo();
3988 y.foo();
3989 z.foo();
3990 x.foo2();
3991 y.foo2();
3992 z.foo2();
3993}
3994"#),
3995 @r###"
3996 [30; 34) 'self': &Self
3997 [55; 59) 'self': &Self
3998 [99; 101) '{}': ()
3999 [111; 112) 'x': impl Trait<u64>
4000 [131; 132) 'y': &impl Trait<u64>
4001 [152; 269) '{ ...2(); }': ()
4002 [158; 159) 'x': impl Trait<u64>
4003 [165; 166) 'y': &impl Trait<u64>
4004 [176; 177) 'z': impl Trait<u64>
4005 [180; 183) 'bar': fn bar() -> impl Trait<u64>
4006 [180; 185) 'bar()': impl Trait<u64>
4007 [191; 192) 'x': impl Trait<u64>
4008 [191; 198) 'x.foo()': u64
4009 [204; 205) 'y': &impl Trait<u64>
4010 [204; 211) 'y.foo()': u64
4011 [217; 218) 'z': impl Trait<u64>
4012 [217; 224) 'z.foo()': u64
4013 [230; 231) 'x': impl Trait<u64>
4014 [230; 238) 'x.foo2()': i64
4015 [244; 245) 'y': &impl Trait<u64>
4016 [244; 252) 'y.foo2()': i64
4017 [258; 259) 'z': impl Trait<u64>
4018 [258; 266) 'z.foo2()': i64
4019 "###
4020 );
4021}
4022
4023#[test]
4024fn dyn_trait() {
4025 assert_snapshot!(
4026 infer(r#"
4027trait Trait<T> {
4028 fn foo(&self) -> T;
4029 fn foo2(&self) -> i64;
4030}
4031fn bar() -> dyn Trait<u64> {}
4032
4033fn test(x: dyn Trait<u64>, y: &dyn Trait<u64>) {
4034 x;
4035 y;
4036 let z = bar();
4037 x.foo();
4038 y.foo();
4039 z.foo();
4040 x.foo2();
4041 y.foo2();
4042 z.foo2();
4043}
4044"#),
4045 @r###"
4046 [30; 34) 'self': &Self
4047 [55; 59) 'self': &Self
4048 [98; 100) '{}': ()
4049 [110; 111) 'x': dyn Trait<u64>
4050 [129; 130) 'y': &dyn Trait<u64>
4051 [149; 266) '{ ...2(); }': ()
4052 [155; 156) 'x': dyn Trait<u64>
4053 [162; 163) 'y': &dyn Trait<u64>
4054 [173; 174) 'z': dyn Trait<u64>
4055 [177; 180) 'bar': fn bar() -> dyn Trait<u64>
4056 [177; 182) 'bar()': dyn Trait<u64>
4057 [188; 189) 'x': dyn Trait<u64>
4058 [188; 195) 'x.foo()': u64
4059 [201; 202) 'y': &dyn Trait<u64>
4060 [201; 208) 'y.foo()': u64
4061 [214; 215) 'z': dyn Trait<u64>
4062 [214; 221) 'z.foo()': u64
4063 [227; 228) 'x': dyn Trait<u64>
4064 [227; 235) 'x.foo2()': i64
4065 [241; 242) 'y': &dyn Trait<u64>
4066 [241; 249) 'y.foo2()': i64
4067 [255; 256) 'z': dyn Trait<u64>
4068 [255; 263) 'z.foo2()': i64
4069 "###
4070 );
4071}
4072
4073#[test]
4074fn dyn_trait_bare() {
4075 assert_snapshot!(
4076 infer(r#"
4077trait Trait {
4078 fn foo(&self) -> u64;
4079}
4080fn bar() -> Trait {}
4081
4082fn test(x: Trait, y: &Trait) -> u64 {
4083 x;
4084 y;
4085 let z = bar();
4086 x.foo();
4087 y.foo();
4088 z.foo();
4089}
4090"#),
4091 @r###"
4092 [27; 31) 'self': &Self
4093 [61; 63) '{}': ()
4094 [73; 74) 'x': dyn Trait
4095 [83; 84) 'y': &dyn Trait
4096 [101; 176) '{ ...o(); }': ()
4097 [107; 108) 'x': dyn Trait
4098 [114; 115) 'y': &dyn Trait
4099 [125; 126) 'z': dyn Trait
4100 [129; 132) 'bar': fn bar() -> dyn Trait
4101 [129; 134) 'bar()': dyn Trait
4102 [140; 141) 'x': dyn Trait
4103 [140; 147) 'x.foo()': u64
4104 [153; 154) 'y': &dyn Trait
4105 [153; 160) 'y.foo()': u64
4106 [166; 167) 'z': dyn Trait
4107 [166; 173) 'z.foo()': u64
4108 "###
4109 );
4110}
4111
4112#[test]
4113fn weird_bounds() {
4114 assert_snapshot!(
4115 infer(r#"
4116trait Trait {}
4117fn test() {
4118 let a: impl Trait + 'lifetime = foo;
4119 let b: impl 'lifetime = foo;
4120 let b: impl (Trait) = foo;
4121 let b: impl ('lifetime) = foo;
4122 let d: impl ?Sized = foo;
4123 let e: impl Trait + ?Sized = foo;
4124}
4125"#),
4126 @r###"
4127 [26; 237) '{ ...foo; }': ()
4128 [36; 37) 'a': impl Trait + {error}
4129 [64; 67) 'foo': impl Trait + {error}
4130 [77; 78) 'b': impl {error}
4131 [97; 100) 'foo': impl {error}
4132 [110; 111) 'b': impl Trait
4133 [128; 131) 'foo': impl Trait
4134 [141; 142) 'b': impl {error}
4135 [163; 166) 'foo': impl {error}
4136 [176; 177) 'd': impl {error}
4137 [193; 196) 'foo': impl {error}
4138 [206; 207) 'e': impl Trait + {error}
4139 [231; 234) 'foo': impl Trait + {error}
4140 "###
4141 );
4142}
4143
4144#[test]
4145fn assoc_type_bindings() {
4146 assert_snapshot!(
4147 infer(r#"
4148trait Trait {
4149 type Type;
4150}
4151
4152fn get<T: Trait>(t: T) -> <T as Trait>::Type {}
4153fn get2<U, T: Trait<Type = U>>(t: T) -> U {}
4154fn set<T: Trait<Type = u64>>(t: T) -> T {t}
4155
4156struct S<T>;
4157impl<T> Trait for S<T> { type Type = T; }
4158
4159fn test<T: Trait<Type = u32>>(x: T, y: impl Trait<Type = i64>) {
4160 get(x);
4161 get2(x);
4162 get(y);
4163 get2(y);
4164 get(set(S));
4165 get2(set(S));
4166 get2(S::<str>);
4167}
4168"#),
4169 @r###"
4170 [50; 51) 't': T
4171 [78; 80) '{}': ()
4172 [112; 113) 't': T
4173 [123; 125) '{}': ()
4174 [155; 156) 't': T
4175 [166; 169) '{t}': T
4176 [167; 168) 't': T
4177 [257; 258) 'x': T
4178 [263; 264) 'y': impl Trait<Type = i64>
4179 [290; 398) '{ ...r>); }': ()
4180 [296; 299) 'get': fn get<T>(T) -> <T as Trait>::Type
4181 [296; 302) 'get(x)': {unknown}
4182 [300; 301) 'x': T
4183 [308; 312) 'get2': fn get2<{unknown}, T>(T) -> U
4184 [308; 315) 'get2(x)': {unknown}
4185 [313; 314) 'x': T
4186 [321; 324) 'get': fn get<impl Trait<Type = i64>>(T) -> <T as Trait>::Type
4187 [321; 327) 'get(y)': {unknown}
4188 [325; 326) 'y': impl Trait<Type = i64>
4189 [333; 337) 'get2': fn get2<{unknown}, impl Trait<Type = i64>>(T) -> U
4190 [333; 340) 'get2(y)': {unknown}
4191 [338; 339) 'y': impl Trait<Type = i64>
4192 [346; 349) 'get': fn get<S<u64>>(T) -> <T as Trait>::Type
4193 [346; 357) 'get(set(S))': u64
4194 [350; 353) 'set': fn set<S<u64>>(T) -> T
4195 [350; 356) 'set(S)': S<u64>
4196 [354; 355) 'S': S<u64>
4197 [363; 367) 'get2': fn get2<u64, S<u64>>(T) -> U
4198 [363; 375) 'get2(set(S))': u64
4199 [368; 371) 'set': fn set<S<u64>>(T) -> T
4200 [368; 374) 'set(S)': S<u64>
4201 [372; 373) 'S': S<u64>
4202 [381; 385) 'get2': fn get2<str, S<str>>(T) -> U
4203 [381; 395) 'get2(S::<str>)': str
4204 [386; 394) 'S::<str>': S<str>
4205 "###
4206 );
4207}
4208
4209#[test]
4210fn impl_trait_assoc_binding_projection_bug() {
4211 let (db, pos) = TestDB::with_position(
4212 r#"
4213//- /main.rs crate:main deps:std
4214pub trait Language {
4215 type Kind;
4216}
4217pub enum RustLanguage {}
4218impl Language for RustLanguage {
4219 type Kind = SyntaxKind;
4220}
4221struct SyntaxNode<L> {}
4222fn foo() -> impl Iterator<Item = SyntaxNode<RustLanguage>> {}
4223
4224trait Clone {
4225 fn clone(&self) -> Self;
4226}
4227
4228fn api_walkthrough() {
4229 for node in foo() {
4230 node.clone()<|>;
4231 }
4232}
4233
4234//- /std.rs crate:std
4235#[prelude_import] use iter::*;
4236mod iter {
4237 trait IntoIterator {
4238 type Item;
4239 }
4240 trait Iterator {
4241 type Item;
4242 }
4243 impl<T: Iterator> IntoIterator for T {
4244 type Item = <T as Iterator>::Item;
4245 }
4246}
4247"#,
4248 );
4249 assert_eq!("{unknown}", type_at_pos(&db, pos));
4250}
4251
4252#[test]
4253fn projection_eq_within_chalk() {
4254 // std::env::set_var("CHALK_DEBUG", "1");
4255 assert_snapshot!(
4256 infer(r#"
4257trait Trait1 {
4258 type Type;
4259}
4260trait Trait2<T> {
4261 fn foo(self) -> T;
4262}
4263impl<T, U> Trait2<T> for U where U: Trait1<Type = T> {}
4264
4265fn test<T: Trait1<Type = u32>>(x: T) {
4266 x.foo();
4267}
4268"#),
4269 @r###"
4270 [62; 66) 'self': Self
4271 [164; 165) 'x': T
4272 [170; 186) '{ ...o(); }': ()
4273 [176; 177) 'x': T
4274 [176; 183) 'x.foo()': {unknown}
4275 "###
4276 );
4277}
4278
4279#[test]
4280fn where_clause_trait_in_scope_for_method_resolution() {
4281 let t = type_at(
4282 r#"
4283//- /main.rs
4284mod foo {
4285 trait Trait {
4286 fn foo(&self) -> u32 {}
4287 }
4288}
4289
4290fn test<T: foo::Trait>(x: T) {
4291 x.foo()<|>;
4292}
4293"#,
4294 );
4295 assert_eq!(t, "u32");
4296}
4297
4298#[test]
4299fn super_trait_method_resolution() {
4300 assert_snapshot!(
4301 infer(r#"
4302mod foo {
4303 trait SuperTrait {
4304 fn foo(&self) -> u32 {}
4305 }
4306}
4307trait Trait1: foo::SuperTrait {}
4308trait Trait2 where Self: foo::SuperTrait {}
4309
4310fn test<T: Trait1, U: Trait2>(x: T, y: U) {
4311 x.foo();
4312 y.foo();
4313}
4314"#),
4315 @r###"
4316 [50; 54) 'self': &Self
4317 [63; 65) '{}': ()
4318 [182; 183) 'x': T
4319 [188; 189) 'y': U
4320 [194; 223) '{ ...o(); }': ()
4321 [200; 201) 'x': T
4322 [200; 207) 'x.foo()': u32
4323 [213; 214) 'y': U
4324 [213; 220) 'y.foo()': u32
4325 "###
4326 );
4327}
4328
4329#[test]
4330fn super_trait_cycle() {
4331 // This just needs to not crash
4332 assert_snapshot!(
4333 infer(r#"
4334trait A: B {}
4335trait B: A {}
4336
4337fn test<T: A>(x: T) {
4338 x.foo();
4339}
4340"#),
4341 @r###"
4342 [44; 45) 'x': T
4343 [50; 66) '{ ...o(); }': ()
4344 [56; 57) 'x': T
4345 [56; 63) 'x.foo()': {unknown}
4346 "###
4347 );
4348}
4349
4350#[test]
4351fn super_trait_assoc_type_bounds() {
4352 assert_snapshot!(
4353 infer(r#"
4354trait SuperTrait { type Type; }
4355trait Trait where Self: SuperTrait {}
4356
4357fn get2<U, T: Trait<Type = U>>(t: T) -> U {}
4358fn set<T: Trait<Type = u64>>(t: T) -> T {t}
4359
4360struct S<T>;
4361impl<T> SuperTrait for S<T> { type Type = T; }
4362impl<T> Trait for S<T> {}
4363
4364fn test() {
4365 get2(set(S));
4366}
4367"#),
4368 @r###"
4369 [103; 104) 't': T
4370 [114; 116) '{}': ()
4371 [146; 147) 't': T
4372 [157; 160) '{t}': T
4373 [158; 159) 't': T
4374 [259; 280) '{ ...S)); }': ()
4375 [265; 269) 'get2': fn get2<u64, S<u64>>(T) -> U
4376 [265; 277) 'get2(set(S))': u64
4377 [270; 273) 'set': fn set<S<u64>>(T) -> T
4378 [270; 276) 'set(S)': S<u64>
4379 [274; 275) 'S': S<u64>
4380 "###
4381 );
4382}
4383
4384#[test]
4385fn fn_trait() {
4386 assert_snapshot!(
4387 infer(r#"
4388trait FnOnce<Args> {
4389 type Output;
4390
4391 fn call_once(self, args: Args) -> <Self as FnOnce<Args>>::Output;
4392}
4393
4394fn test<F: FnOnce(u32, u64) -> u128>(f: F) {
4395 f.call_once((1, 2));
4396}
4397"#),
4398 @r###"
4399 [57; 61) 'self': Self
4400 [63; 67) 'args': Args
4401 [150; 151) 'f': F
4402 [156; 184) '{ ...2)); }': ()
4403 [162; 163) 'f': F
4404 [162; 181) 'f.call...1, 2))': {unknown}
4405 [174; 180) '(1, 2)': (u32, u64)
4406 [175; 176) '1': u32
4407 [178; 179) '2': u64
4408 "###
4409 );
4410}
4411
4412#[test]
4413fn closure_1() {
4414 assert_snapshot!(
4415 infer(r#"
4416#[lang = "fn_once"]
4417trait FnOnce<Args> {
4418 type Output;
4419}
4420
4421enum Option<T> { Some(T), None }
4422impl<T> Option<T> {
4423 fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> {}
4424}
4425
4426fn test() {
4427 let x = Option::Some(1u32);
4428 x.map(|v| v + 1);
4429 x.map(|_v| 1u64);
4430 let y: Option<i64> = x.map(|_v| 1);
4431}
4432"#),
4433 @r###"
4434 [148; 152) 'self': Option<T>
4435 [154; 155) 'f': F
4436 [173; 175) '{}': ()
4437 [189; 308) '{ ... 1); }': ()
4438 [199; 200) 'x': Option<u32>
4439 [203; 215) 'Option::Some': Some<u32>(T) -> Option<T>
4440 [203; 221) 'Option...(1u32)': Option<u32>
4441 [216; 220) '1u32': u32
4442 [227; 228) 'x': Option<u32>
4443 [227; 243) 'x.map(...v + 1)': Option<u32>
4444 [233; 242) '|v| v + 1': |u32| -> u32
4445 [234; 235) 'v': u32
4446 [237; 238) 'v': u32
4447 [237; 242) 'v + 1': u32
4448 [241; 242) '1': u32
4449 [249; 250) 'x': Option<u32>
4450 [249; 265) 'x.map(... 1u64)': Option<u64>
4451 [255; 264) '|_v| 1u64': |u32| -> u64
4452 [256; 258) '_v': u32
4453 [260; 264) '1u64': u64
4454 [275; 276) 'y': Option<i64>
4455 [292; 293) 'x': Option<u32>
4456 [292; 305) 'x.map(|_v| 1)': Option<i64>
4457 [298; 304) '|_v| 1': |u32| -> i64
4458 [299; 301) '_v': u32
4459 [303; 304) '1': i64
4460 "###
4461 );
4462}
4463
4464#[test]
4465fn closure_2() {
4466 assert_snapshot!(
4467 infer(r#"
4468trait FnOnce<Args> {
4469 type Output;
4470}
4471
4472fn test<F: FnOnce(u32) -> u64>(f: F) {
4473 f(1);
4474 let g = |v| v + 1;
4475 g(1u64);
4476 let h = |v| 1u128 + v;
4477}
4478"#),
4479 @r###"
4480 [73; 74) 'f': F
4481 [79; 155) '{ ...+ v; }': ()
4482 [85; 86) 'f': F
4483 [85; 89) 'f(1)': {unknown}
4484 [87; 88) '1': i32
4485 [99; 100) 'g': |u64| -> i32
4486 [103; 112) '|v| v + 1': |u64| -> i32
4487 [104; 105) 'v': u64
4488 [107; 108) 'v': u64
4489 [107; 112) 'v + 1': i32
4490 [111; 112) '1': i32
4491 [118; 119) 'g': |u64| -> i32
4492 [118; 125) 'g(1u64)': i32
4493 [120; 124) '1u64': u64
4494 [135; 136) 'h': |u128| -> u128
4495 [139; 152) '|v| 1u128 + v': |u128| -> u128
4496 [140; 141) 'v': u128
4497 [143; 148) '1u128': u128
4498 [143; 152) '1u128 + v': u128
4499 [151; 152) 'v': u128
4500 "###
4501 );
4502}
4503
4504#[test]
4505fn closure_as_argument_inference_order() {
4506 assert_snapshot!(
4507 infer(r#"
4508#[lang = "fn_once"]
4509trait FnOnce<Args> {
4510 type Output;
4511}
4512
4513fn foo1<T, U, F: FnOnce(T) -> U>(x: T, f: F) -> U {}
4514fn foo2<T, U, F: FnOnce(T) -> U>(f: F, x: T) -> U {}
4515
4516struct S;
4517impl S {
4518 fn method(self) -> u64;
4519
4520 fn foo1<T, U, F: FnOnce(T) -> U>(self, x: T, f: F) -> U {}
4521 fn foo2<T, U, F: FnOnce(T) -> U>(self, f: F, x: T) -> U {}
4522}
4523
4524fn test() {
4525 let x1 = foo1(S, |s| s.method());
4526 let x2 = foo2(|s| s.method(), S);
4527 let x3 = S.foo1(S, |s| s.method());
4528 let x4 = S.foo2(|s| s.method(), S);
4529}
4530"#),
4531 @r###"
4532 [95; 96) 'x': T
4533 [101; 102) 'f': F
4534 [112; 114) '{}': ()
4535 [148; 149) 'f': F
4536 [154; 155) 'x': T
4537 [165; 167) '{}': ()
4538 [202; 206) 'self': S
4539 [254; 258) 'self': S
4540 [260; 261) 'x': T
4541 [266; 267) 'f': F
4542 [277; 279) '{}': ()
4543 [317; 321) 'self': S
4544 [323; 324) 'f': F
4545 [329; 330) 'x': T
4546 [340; 342) '{}': ()
4547 [356; 515) '{ ... S); }': ()
4548 [366; 368) 'x1': u64
4549 [371; 375) 'foo1': fn foo1<S, u64, |S| -> u64>(T, F) -> U
4550 [371; 394) 'foo1(S...hod())': u64
4551 [376; 377) 'S': S
4552 [379; 393) '|s| s.method()': |S| -> u64
4553 [380; 381) 's': S
4554 [383; 384) 's': S
4555 [383; 393) 's.method()': u64
4556 [404; 406) 'x2': u64
4557 [409; 413) 'foo2': fn foo2<S, u64, |S| -> u64>(F, T) -> U
4558 [409; 432) 'foo2(|...(), S)': u64
4559 [414; 428) '|s| s.method()': |S| -> u64
4560 [415; 416) 's': S
4561 [418; 419) 's': S
4562 [418; 428) 's.method()': u64
4563 [430; 431) 'S': S
4564 [442; 444) 'x3': u64
4565 [447; 448) 'S': S
4566 [447; 472) 'S.foo1...hod())': u64
4567 [454; 455) 'S': S
4568 [457; 471) '|s| s.method()': |S| -> u64
4569 [458; 459) 's': S
4570 [461; 462) 's': S
4571 [461; 471) 's.method()': u64
4572 [482; 484) 'x4': u64
4573 [487; 488) 'S': S
4574 [487; 512) 'S.foo2...(), S)': u64
4575 [494; 508) '|s| s.method()': |S| -> u64
4576 [495; 496) 's': S
4577 [498; 499) 's': S
4578 [498; 508) 's.method()': u64
4579 [510; 511) 'S': S
4580 "###
4581 );
4582}
4583
4584#[test]
4585fn unselected_projection_in_trait_env_1() {
4586 let t = type_at(
4587 r#"
4588//- /main.rs
4589trait Trait {
4590 type Item;
4591}
4592
4593trait Trait2 {
4594 fn foo(&self) -> u32;
4595}
4596
4597fn test<T: Trait>() where T::Item: Trait2 {
4598 let x: T::Item = no_matter;
4599 x.foo()<|>;
4600}
4601"#,
4602 );
4603 assert_eq!(t, "u32");
4604}
4605
4606#[test]
4607fn unselected_projection_in_trait_env_2() {
4608 let t = type_at(
4609 r#"
4610//- /main.rs
4611trait Trait<T> {
4612 type Item;
4613}
4614
4615trait Trait2 {
4616 fn foo(&self) -> u32;
4617}
4618
4619fn test<T, U>() where T::Item: Trait2, T: Trait<U::Item>, U: Trait<()> {
4620 let x: T::Item = no_matter;
4621 x.foo()<|>;
4622}
4623"#,
4624 );
4625 assert_eq!(t, "u32");
4626}
4627
4628#[test]
4629// FIXME this is currently a Salsa panic; it would be nicer if it just returned
4630// in Unknown, and we should be able to do that once Salsa allows us to handle
4631// the cycle. But at least it doesn't overflow for now.
4632#[should_panic]
4633fn unselected_projection_in_trait_env_cycle_1() {
4634 let t = type_at(
4635 r#"
4636//- /main.rs
4637trait Trait {
4638 type Item;
4639}
4640
4641trait Trait2<T> {}
4642
4643fn test<T: Trait>() where T: Trait2<T::Item> {
4644 let x: T::Item = no_matter<|>;
4645}
4646"#,
4647 );
4648 // this is a legitimate cycle
4649 assert_eq!(t, "{unknown}");
4650}
4651
4652#[test]
4653// FIXME this is currently a Salsa panic; it would be nicer if it just returned
4654// in Unknown, and we should be able to do that once Salsa allows us to handle
4655// the cycle. But at least it doesn't overflow for now.
4656#[should_panic]
4657fn unselected_projection_in_trait_env_cycle_2() {
4658 let t = type_at(
4659 r#"
4660//- /main.rs
4661trait Trait<T> {
4662 type Item;
4663}
4664
4665fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> {
4666 let x: T::Item = no_matter<|>;
4667}
4668"#,
4669 );
4670 // this is a legitimate cycle
4671 assert_eq!(t, "{unknown}");
4672}
4673
4674fn type_at_pos(db: &TestDB, pos: FilePosition) -> String { 31fn type_at_pos(db: &TestDB, pos: FilePosition) -> String {
4675 let file = db.parse(pos.file_id).ok().unwrap(); 32 let file = db.parse(pos.file_id).ok().unwrap();
4676 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); 33 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap();
4677 34 let fn_def = expr.syntax().ancestors().find_map(ast::FnDef::cast).unwrap();
4678 let module = db.module_for_file(pos.file_id); 35 let module = db.module_for_file(pos.file_id);
4679 let crate_def_map = db.crate_def_map(module.krate); 36 let func = *module.child_by_source(db)[keys::FUNCTION]
4680 for decl in crate_def_map[module.local_id].scope.declarations() { 37 .get(&InFile::new(pos.file_id.into(), fn_def))
4681 if let ModuleDefId::FunctionId(func) = decl { 38 .unwrap();
4682 let (_body, source_map) = db.body_with_source_map(func.into()); 39
4683 if let Some(expr_id) = source_map.node_expr(Source::new(pos.file_id.into(), &expr)) { 40 let (_body, source_map) = db.body_with_source_map(func.into());
4684 let infer = db.infer(func.into()); 41 if let Some(expr_id) = source_map.node_expr(InFile::new(pos.file_id.into(), &expr)) {
4685 let ty = &infer[expr_id]; 42 let infer = db.infer(func.into());
4686 return ty.display(db).to_string(); 43 let ty = &infer[expr_id];
4687 } 44 return ty.display(db).to_string();
4688 }
4689 } 45 }
4690 panic!("Can't find expression") 46 panic!("Can't find expression")
4691} 47}
@@ -4696,6 +52,10 @@ fn type_at(content: &str) -> String {
4696} 52}
4697 53
4698fn infer(content: &str) -> String { 54fn infer(content: &str) -> String {
55 infer_with_mismatches(content, false)
56}
57
58fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
4699 let (db, file_id) = TestDB::with_single_file(content); 59 let (db, file_id) = TestDB::with_single_file(content);
4700 60
4701 let mut acc = String::new(); 61 let mut acc = String::new();
@@ -4703,6 +63,7 @@ fn infer(content: &str) -> String {
4703 let mut infer_def = |inference_result: Arc<InferenceResult>, 63 let mut infer_def = |inference_result: Arc<InferenceResult>,
4704 body_source_map: Arc<BodySourceMap>| { 64 body_source_map: Arc<BodySourceMap>| {
4705 let mut types = Vec::new(); 65 let mut types = Vec::new();
66 let mut mismatches = Vec::new();
4706 67
4707 for (pat, ty) in inference_result.type_of_pat.iter() { 68 for (pat, ty) in inference_result.type_of_pat.iter() {
4708 let syntax_ptr = match body_source_map.pat_syntax(pat) { 69 let syntax_ptr = match body_source_map.pat_syntax(pat) {
@@ -4722,6 +83,9 @@ fn infer(content: &str) -> String {
4722 None => continue, 83 None => continue,
4723 }; 84 };
4724 types.push((syntax_ptr, ty)); 85 types.push((syntax_ptr, ty));
86 if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr) {
87 mismatches.push((syntax_ptr, mismatch));
88 }
4725 } 89 }
4726 90
4727 // sort ranges for consistency 91 // sort ranges for consistency
@@ -4747,6 +111,24 @@ fn infer(content: &str) -> String {
4747 ) 111 )
4748 .unwrap(); 112 .unwrap();
4749 } 113 }
114 if include_mismatches {
115 mismatches.sort_by_key(|(src_ptr, _)| {
116 (src_ptr.value.range().start(), src_ptr.value.range().end())
117 });
118 for (src_ptr, mismatch) in &mismatches {
119 let range = src_ptr.value.range();
120 let macro_prefix = if src_ptr.file_id != file_id.into() { "!" } else { "" };
121 write!(
122 acc,
123 "{}{}: expected {}, got {}\n",
124 macro_prefix,
125 range,
126 mismatch.expected.display(&db),
127 mismatch.actual.display(&db),
128 )
129 .unwrap();
130 }
131 }
4750 }; 132 };
4751 133
4752 let module = db.module_for_file(file_id); 134 let module = db.module_for_file(file_id);
@@ -4800,7 +182,7 @@ fn visit_module(
4800 _ => (), 182 _ => (),
4801 } 183 }
4802 } 184 }
4803 for &impl_id in crate_def_map[module_id].impls.iter() { 185 for impl_id in crate_def_map[module_id].scope.impls() {
4804 let impl_data = db.impl_data(impl_id); 186 let impl_data = db.impl_data(impl_id);
4805 for &item in impl_data.items.iter() { 187 for &item in impl_data.items.iter() {
4806 match item { 188 match item {
@@ -4899,60 +281,3 @@ fn no_such_field_diagnostics() {
4899 "### 281 "###
4900 ); 282 );
4901} 283}
4902
4903#[test]
4904fn infer_builtin_macros_line() {
4905 assert_snapshot!(
4906 infer(r#"
4907#[rustc_builtin_macro]
4908macro_rules! line {() => {}}
4909
4910fn main() {
4911 let x = line!();
4912}
4913"#),
4914 @r###"
4915 ![0; 1) '6': i32
4916 [64; 88) '{ ...!(); }': ()
4917 [74; 75) 'x': i32
4918 "###
4919 );
4920}
4921
4922#[test]
4923fn infer_builtin_macros_file() {
4924 assert_snapshot!(
4925 infer(r#"
4926#[rustc_builtin_macro]
4927macro_rules! file {() => {}}
4928
4929fn main() {
4930 let x = file!();
4931}
4932"#),
4933 @r###"
4934 ![0; 2) '""': &str
4935 [64; 88) '{ ...!(); }': ()
4936 [74; 75) 'x': &str
4937 "###
4938 );
4939}
4940
4941#[test]
4942fn infer_builtin_macros_column() {
4943 assert_snapshot!(
4944 infer(r#"
4945#[rustc_builtin_macro]
4946macro_rules! column {() => {}}
4947
4948fn main() {
4949 let x = column!();
4950}
4951"#),
4952 @r###"
4953 ![0; 2) '13': i32
4954 [66; 92) '{ ...!(); }': ()
4955 [76; 77) 'x': i32
4956 "###
4957 );
4958}
diff --git a/crates/ra_hir_ty/src/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs
index 1530fcc63..7e99a42ed 100644
--- a/crates/ra_hir_ty/src/tests/coercion.rs
+++ b/crates/ra_hir_ty/src/tests/coercion.rs
@@ -1,3 +1,4 @@
1use super::infer_with_mismatches;
1use insta::assert_snapshot; 2use insta::assert_snapshot;
2use test_utils::covers; 3use test_utils::covers;
3 4
@@ -367,3 +368,161 @@ fn test() {
367 "### 368 "###
368 ); 369 );
369} 370}
371
372#[test]
373fn return_coerce_unknown() {
374 assert_snapshot!(
375 infer_with_mismatches(r#"
376fn foo() -> u32 {
377 return unknown;
378}
379"#, true),
380 @r###"
381 [17; 40) '{ ...own; }': !
382 [23; 37) 'return unknown': !
383 [30; 37) 'unknown': u32
384 "###
385 );
386}
387
388#[test]
389fn coerce_autoderef() {
390 assert_snapshot!(
391 infer_with_mismatches(r#"
392struct Foo;
393fn takes_ref_foo(x: &Foo) {}
394fn test() {
395 takes_ref_foo(&Foo);
396 takes_ref_foo(&&Foo);
397 takes_ref_foo(&&&Foo);
398}
399"#, true),
400 @r###"
401 [30; 31) 'x': &Foo
402 [39; 41) '{}': ()
403 [52; 133) '{ ...oo); }': ()
404 [58; 71) 'takes_ref_foo': fn takes_ref_foo(&Foo) -> ()
405 [58; 77) 'takes_...(&Foo)': ()
406 [72; 76) '&Foo': &Foo
407 [73; 76) 'Foo': Foo
408 [83; 96) 'takes_ref_foo': fn takes_ref_foo(&Foo) -> ()
409 [83; 103) 'takes_...&&Foo)': ()
410 [97; 102) '&&Foo': &&Foo
411 [98; 102) '&Foo': &Foo
412 [99; 102) 'Foo': Foo
413 [109; 122) 'takes_ref_foo': fn takes_ref_foo(&Foo) -> ()
414 [109; 130) 'takes_...&&Foo)': ()
415 [123; 129) '&&&Foo': &&&Foo
416 [124; 129) '&&Foo': &&Foo
417 [125; 129) '&Foo': &Foo
418 [126; 129) 'Foo': Foo
419 "###
420 );
421}
422
423#[test]
424fn coerce_autoderef_generic() {
425 assert_snapshot!(
426 infer_with_mismatches(r#"
427struct Foo;
428fn takes_ref<T>(x: &T) -> T { *x }
429fn test() {
430 takes_ref(&Foo);
431 takes_ref(&&Foo);
432 takes_ref(&&&Foo);
433}
434"#, true),
435 @r###"
436 [29; 30) 'x': &T
437 [41; 47) '{ *x }': T
438 [43; 45) '*x': T
439 [44; 45) 'x': &T
440 [58; 127) '{ ...oo); }': ()
441 [64; 73) 'takes_ref': fn takes_ref<Foo>(&T) -> T
442 [64; 79) 'takes_ref(&Foo)': Foo
443 [74; 78) '&Foo': &Foo
444 [75; 78) 'Foo': Foo
445 [85; 94) 'takes_ref': fn takes_ref<&Foo>(&T) -> T
446 [85; 101) 'takes_...&&Foo)': &Foo
447 [95; 100) '&&Foo': &&Foo
448 [96; 100) '&Foo': &Foo
449 [97; 100) 'Foo': Foo
450 [107; 116) 'takes_ref': fn takes_ref<&&Foo>(&T) -> T
451 [107; 124) 'takes_...&&Foo)': &&Foo
452 [117; 123) '&&&Foo': &&&Foo
453 [118; 123) '&&Foo': &&Foo
454 [119; 123) '&Foo': &Foo
455 [120; 123) 'Foo': Foo
456 "###
457 );
458}
459
460#[test]
461fn closure_return_coerce() {
462 assert_snapshot!(
463 infer_with_mismatches(r#"
464fn foo() {
465 let x = || {
466 if true {
467 return &1u32;
468 }
469 &&1u32
470 };
471}
472"#, true),
473 @r###"
474 [10; 106) '{ ... }; }': ()
475 [20; 21) 'x': || -> &u32
476 [24; 103) '|| { ... }': || -> &u32
477 [27; 103) '{ ... }': &u32
478 [37; 82) 'if tru... }': ()
479 [40; 44) 'true': bool
480 [45; 82) '{ ... }': !
481 [59; 71) 'return &1u32': !
482 [66; 71) '&1u32': &u32
483 [67; 71) '1u32': u32
484 [91; 97) '&&1u32': &&u32
485 [92; 97) '&1u32': &u32
486 [93; 97) '1u32': u32
487 "###
488 );
489}
490
491#[test]
492fn coerce_fn_item_to_fn_ptr() {
493 assert_snapshot!(
494 infer_with_mismatches(r#"
495fn foo(x: u32) -> isize { 1 }
496fn test() {
497 let f: fn(u32) -> isize = foo;
498}
499"#, true),
500 @r###"
501 [8; 9) 'x': u32
502 [25; 30) '{ 1 }': isize
503 [27; 28) '1': isize
504 [41; 79) '{ ...foo; }': ()
505 [51; 52) 'f': fn(u32) -> isize
506 [73; 76) 'foo': fn foo(u32) -> isize
507 "###
508 );
509}
510
511#[test]
512fn coerce_closure_to_fn_ptr() {
513 assert_snapshot!(
514 infer_with_mismatches(r#"
515fn test() {
516 let f: fn(u32) -> isize = |x| { 1 };
517}
518"#, true),
519 @r###"
520 [11; 55) '{ ...1 }; }': ()
521 [21; 22) 'f': fn(u32) -> isize
522 [43; 52) '|x| { 1 }': |u32| -> isize
523 [44; 45) 'x': u32
524 [47; 52) '{ 1 }': isize
525 [49; 50) '1': isize
526 "###
527 );
528}
diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs
new file mode 100644
index 000000000..69c695cc8
--- /dev/null
+++ b/crates/ra_hir_ty/src/tests/macros.rs
@@ -0,0 +1,390 @@
1use super::{infer, type_at, type_at_pos};
2use crate::test_db::TestDB;
3use insta::assert_snapshot;
4use ra_db::fixture::WithFixture;
5
6#[test]
7fn cfg_impl_block() {
8 let (db, pos) = TestDB::with_position(
9 r#"
10//- /main.rs crate:main deps:foo cfg:test
11use foo::S as T;
12struct S;
13
14#[cfg(test)]
15impl S {
16 fn foo1(&self) -> i32 { 0 }
17}
18
19#[cfg(not(test))]
20impl S {
21 fn foo2(&self) -> i32 { 0 }
22}
23
24fn test() {
25 let t = (S.foo1(), S.foo2(), T.foo3(), T.foo4());
26 t<|>;
27}
28
29//- /foo.rs crate:foo
30struct S;
31
32#[cfg(not(test))]
33impl S {
34 fn foo3(&self) -> i32 { 0 }
35}
36
37#[cfg(test)]
38impl S {
39 fn foo4(&self) -> i32 { 0 }
40}
41"#,
42 );
43 assert_eq!("(i32, {unknown}, i32, {unknown})", type_at_pos(&db, pos));
44}
45
46#[test]
47fn infer_macros_expanded() {
48 assert_snapshot!(
49 infer(r#"
50struct Foo(Vec<i32>);
51
52macro_rules! foo {
53 ($($item:expr),*) => {
54 {
55 Foo(vec![$($item,)*])
56 }
57 };
58}
59
60fn main() {
61 let x = foo!(1,2);
62}
63"#),
64 @r###"
65 ![0; 17) '{Foo(v...,2,])}': Foo
66 ![1; 4) 'Foo': Foo({unknown}) -> Foo
67 ![1; 16) 'Foo(vec![1,2,])': Foo
68 ![5; 15) 'vec![1,2,]': {unknown}
69 [156; 182) '{ ...,2); }': ()
70 [166; 167) 'x': Foo
71 "###
72 );
73}
74
75#[test]
76fn infer_legacy_textual_scoped_macros_expanded() {
77 assert_snapshot!(
78 infer(r#"
79struct Foo(Vec<i32>);
80
81#[macro_use]
82mod m {
83 macro_rules! foo {
84 ($($item:expr),*) => {
85 {
86 Foo(vec![$($item,)*])
87 }
88 };
89 }
90}
91
92fn main() {
93 let x = foo!(1,2);
94 let y = crate::foo!(1,2);
95}
96"#),
97 @r###"
98 ![0; 17) '{Foo(v...,2,])}': Foo
99 ![1; 4) 'Foo': Foo({unknown}) -> Foo
100 ![1; 16) 'Foo(vec![1,2,])': Foo
101 ![5; 15) 'vec![1,2,]': {unknown}
102 [195; 251) '{ ...,2); }': ()
103 [205; 206) 'x': Foo
104 [228; 229) 'y': {unknown}
105 [232; 248) 'crate:...!(1,2)': {unknown}
106 "###
107 );
108}
109
110#[test]
111fn infer_path_qualified_macros_expanded() {
112 assert_snapshot!(
113 infer(r#"
114#[macro_export]
115macro_rules! foo {
116 () => { 42i32 }
117}
118
119mod m {
120 pub use super::foo as bar;
121}
122
123fn main() {
124 let x = crate::foo!();
125 let y = m::bar!();
126}
127"#),
128 @r###"
129 ![0; 5) '42i32': i32
130 ![0; 5) '42i32': i32
131 [111; 164) '{ ...!(); }': ()
132 [121; 122) 'x': i32
133 [148; 149) 'y': i32
134 "###
135 );
136}
137
138#[test]
139fn infer_type_value_macro_having_same_name() {
140 assert_snapshot!(
141 infer(r#"
142#[macro_export]
143macro_rules! foo {
144 () => {
145 mod foo {
146 pub use super::foo;
147 }
148 };
149 ($x:tt) => {
150 $x
151 };
152}
153
154foo!();
155
156fn foo() {
157 let foo = foo::foo!(42i32);
158}
159"#),
160 @r###"
161 ![0; 5) '42i32': i32
162 [171; 206) '{ ...32); }': ()
163 [181; 184) 'foo': i32
164 "###
165 );
166}
167
168#[test]
169fn processes_impls_generated_by_macros() {
170 let t = type_at(
171 r#"
172//- /main.rs
173macro_rules! m {
174 ($ident:ident) => (impl Trait for $ident {})
175}
176trait Trait { fn foo(self) -> u128 {} }
177struct S;
178m!(S);
179fn test() { S.foo()<|>; }
180"#,
181 );
182 assert_eq!(t, "u128");
183}
184
185#[test]
186fn infer_impl_items_generated_by_macros() {
187 let t = type_at(
188 r#"
189//- /main.rs
190macro_rules! m {
191 () => (fn foo(&self) -> u128 {0})
192}
193struct S;
194impl S {
195 m!();
196}
197
198fn test() { S.foo()<|>; }
199"#,
200 );
201 assert_eq!(t, "u128");
202}
203
204#[test]
205fn infer_impl_items_generated_by_macros_chain() {
206 let t = type_at(
207 r#"
208//- /main.rs
209macro_rules! m_inner {
210 () => {fn foo(&self) -> u128 {0}}
211}
212macro_rules! m {
213 () => {m_inner!();}
214}
215
216struct S;
217impl S {
218 m!();
219}
220
221fn test() { S.foo()<|>; }
222"#,
223 );
224 assert_eq!(t, "u128");
225}
226
227#[test]
228fn infer_macro_with_dollar_crate_is_correct_in_expr() {
229 let (db, pos) = TestDB::with_position(
230 r#"
231//- /main.rs crate:main deps:foo
232fn test() {
233 let x = (foo::foo!(1), foo::foo!(2));
234 x<|>;
235}
236
237//- /lib.rs crate:foo
238#[macro_export]
239macro_rules! foo {
240 (1) => { $crate::bar!() };
241 (2) => { 1 + $crate::baz() };
242}
243
244#[macro_export]
245macro_rules! bar {
246 () => { 42 }
247}
248
249pub fn baz() -> usize { 31usize }
250"#,
251 );
252 assert_eq!("(i32, usize)", type_at_pos(&db, pos));
253}
254
255#[test]
256fn infer_type_value_non_legacy_macro_use_as() {
257 assert_snapshot!(
258 infer(r#"
259mod m {
260 macro_rules! _foo {
261 ($x:ident) => { type $x = u64; }
262 }
263 pub(crate) use _foo as foo;
264}
265
266m::foo!(foo);
267use foo as bar;
268fn f() -> bar { 0 }
269fn main() {
270 let _a = f();
271}
272"#),
273 @r###"
274 [159; 164) '{ 0 }': u64
275 [161; 162) '0': u64
276 [175; 199) '{ ...f(); }': ()
277 [187; 189) '_a': u64
278 [193; 194) 'f': fn f() -> u64
279 [193; 196) 'f()': u64
280 "###
281 );
282}
283
284#[test]
285fn infer_builtin_macros_line() {
286 assert_snapshot!(
287 infer(r#"
288#[rustc_builtin_macro]
289macro_rules! line {() => {}}
290
291fn main() {
292 let x = line!();
293}
294"#),
295 @r###"
296 ![0; 1) '6': i32
297 [64; 88) '{ ...!(); }': ()
298 [74; 75) 'x': i32
299 "###
300 );
301}
302
303#[test]
304fn infer_builtin_macros_file() {
305 assert_snapshot!(
306 infer(r#"
307#[rustc_builtin_macro]
308macro_rules! file {() => {}}
309
310fn main() {
311 let x = file!();
312}
313"#),
314 @r###"
315 ![0; 2) '""': &str
316 [64; 88) '{ ...!(); }': ()
317 [74; 75) 'x': &str
318 "###
319 );
320}
321
322#[test]
323fn infer_builtin_macros_column() {
324 assert_snapshot!(
325 infer(r#"
326#[rustc_builtin_macro]
327macro_rules! column {() => {}}
328
329fn main() {
330 let x = column!();
331}
332"#),
333 @r###"
334 ![0; 2) '13': i32
335 [66; 92) '{ ...!(); }': ()
336 [76; 77) 'x': i32
337 "###
338 );
339}
340
341#[test]
342fn infer_derive_clone_simple() {
343 let (db, pos) = TestDB::with_position(
344 r#"
345//- /main.rs crate:main deps:std
346#[derive(Clone)]
347struct S;
348fn test() {
349 S.clone()<|>;
350}
351
352//- /lib.rs crate:std
353#[prelude_import]
354use clone::*;
355mod clone {
356 trait Clone {
357 fn clone(&self) -> Self;
358 }
359}
360"#,
361 );
362 assert_eq!("S", type_at_pos(&db, pos));
363}
364
365#[test]
366fn infer_derive_clone_with_params() {
367 let (db, pos) = TestDB::with_position(
368 r#"
369//- /main.rs crate:main deps:std
370#[derive(Clone)]
371struct S;
372#[derive(Clone)]
373struct Wrapper<T>(T);
374struct NonClone;
375fn test() {
376 (Wrapper(S).clone(), Wrapper(NonClone).clone())<|>;
377}
378
379//- /lib.rs crate:std
380#[prelude_import]
381use clone::*;
382mod clone {
383 trait Clone {
384 fn clone(&self) -> Self;
385 }
386}
387"#,
388 );
389 assert_eq!("(Wrapper<S>, {unknown})", type_at_pos(&db, pos));
390}
diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs
new file mode 100644
index 000000000..ce9a06fde
--- /dev/null
+++ b/crates/ra_hir_ty/src/tests/method_resolution.rs
@@ -0,0 +1,1005 @@
1use super::{infer, type_at, type_at_pos};
2use crate::test_db::TestDB;
3use insta::assert_snapshot;
4use ra_db::fixture::WithFixture;
5
6#[test]
7fn infer_slice_method() {
8 assert_snapshot!(
9 infer(r#"
10#[lang = "slice"]
11impl<T> [T] {
12 fn foo(&self) -> T {
13 loop {}
14 }
15}
16
17#[lang = "slice_alloc"]
18impl<T> [T] {}
19
20fn test() {
21 <[_]>::foo(b"foo");
22}
23"#),
24 @r###"
25 [45; 49) 'self': &[T]
26 [56; 79) '{ ... }': T
27 [66; 73) 'loop {}': !
28 [71; 73) '{}': ()
29 [133; 160) '{ ...o"); }': ()
30 [139; 149) '<[_]>::foo': fn foo<u8>(&[T]) -> T
31 [139; 157) '<[_]>:..."foo")': u8
32 [150; 156) 'b"foo"': &[u8]
33 "###
34 );
35}
36
37#[test]
38fn infer_associated_method_struct() {
39 assert_snapshot!(
40 infer(r#"
41struct A { x: u32 }
42
43impl A {
44 fn new() -> A {
45 A { x: 0 }
46 }
47}
48fn test() {
49 let a = A::new();
50 a.x;
51}
52"#),
53 @r###"
54 [49; 75) '{ ... }': A
55 [59; 69) 'A { x: 0 }': A
56 [66; 67) '0': u32
57 [88; 122) '{ ...a.x; }': ()
58 [98; 99) 'a': A
59 [102; 108) 'A::new': fn new() -> A
60 [102; 110) 'A::new()': A
61 [116; 117) 'a': A
62 [116; 119) 'a.x': u32
63 "###
64 );
65}
66
67#[test]
68fn infer_associated_method_enum() {
69 assert_snapshot!(
70 infer(r#"
71enum A { B, C }
72
73impl A {
74 pub fn b() -> A {
75 A::B
76 }
77 pub fn c() -> A {
78 A::C
79 }
80}
81fn test() {
82 let a = A::b();
83 a;
84 let c = A::c();
85 c;
86}
87"#),
88 @r###"
89 [47; 67) '{ ... }': A
90 [57; 61) 'A::B': A
91 [88; 108) '{ ... }': A
92 [98; 102) 'A::C': A
93 [121; 178) '{ ... c; }': ()
94 [131; 132) 'a': A
95 [135; 139) 'A::b': fn b() -> A
96 [135; 141) 'A::b()': A
97 [147; 148) 'a': A
98 [158; 159) 'c': A
99 [162; 166) 'A::c': fn c() -> A
100 [162; 168) 'A::c()': A
101 [174; 175) 'c': A
102 "###
103 );
104}
105
106#[test]
107fn infer_associated_method_with_modules() {
108 assert_snapshot!(
109 infer(r#"
110mod a {
111 struct A;
112 impl A { pub fn thing() -> A { A {} }}
113}
114
115mod b {
116 struct B;
117 impl B { pub fn thing() -> u32 { 99 }}
118
119 mod c {
120 struct C;
121 impl C { pub fn thing() -> C { C {} }}
122 }
123}
124use b::c;
125
126fn test() {
127 let x = a::A::thing();
128 let y = b::B::thing();
129 let z = c::C::thing();
130}
131"#),
132 @r###"
133 [56; 64) '{ A {} }': A
134 [58; 62) 'A {}': A
135 [126; 132) '{ 99 }': u32
136 [128; 130) '99': u32
137 [202; 210) '{ C {} }': C
138 [204; 208) 'C {}': C
139 [241; 325) '{ ...g(); }': ()
140 [251; 252) 'x': A
141 [255; 266) 'a::A::thing': fn thing() -> A
142 [255; 268) 'a::A::thing()': A
143 [278; 279) 'y': u32
144 [282; 293) 'b::B::thing': fn thing() -> u32
145 [282; 295) 'b::B::thing()': u32
146 [305; 306) 'z': C
147 [309; 320) 'c::C::thing': fn thing() -> C
148 [309; 322) 'c::C::thing()': C
149 "###
150 );
151}
152
153#[test]
154fn infer_associated_method_generics() {
155 assert_snapshot!(
156 infer(r#"
157struct Gen<T> {
158 val: T
159}
160
161impl<T> Gen<T> {
162 pub fn make(val: T) -> Gen<T> {
163 Gen { val }
164 }
165}
166
167fn test() {
168 let a = Gen::make(0u32);
169}
170"#),
171 @r###"
172 [64; 67) 'val': T
173 [82; 109) '{ ... }': Gen<T>
174 [92; 103) 'Gen { val }': Gen<T>
175 [98; 101) 'val': T
176 [123; 155) '{ ...32); }': ()
177 [133; 134) 'a': Gen<u32>
178 [137; 146) 'Gen::make': fn make<u32>(T) -> Gen<T>
179 [137; 152) 'Gen::make(0u32)': Gen<u32>
180 [147; 151) '0u32': u32
181 "###
182 );
183}
184
185#[test]
186fn infer_associated_method_generics_with_default_param() {
187 assert_snapshot!(
188 infer(r#"
189struct Gen<T=u32> {
190 val: T
191}
192
193impl<T> Gen<T> {
194 pub fn make() -> Gen<T> {
195 loop { }
196 }
197}
198
199fn test() {
200 let a = Gen::make();
201}
202"#),
203 @r###"
204 [80; 104) '{ ... }': Gen<T>
205 [90; 98) 'loop { }': !
206 [95; 98) '{ }': ()
207 [118; 146) '{ ...e(); }': ()
208 [128; 129) 'a': Gen<u32>
209 [132; 141) 'Gen::make': fn make<u32>() -> Gen<T>
210 [132; 143) 'Gen::make()': Gen<u32>
211 "###
212 );
213}
214
215#[test]
216fn infer_associated_method_generics_with_default_tuple_param() {
217 let t = type_at(
218 r#"
219//- /main.rs
220struct Gen<T=()> {
221 val: T
222}
223
224impl<T> Gen<T> {
225 pub fn make() -> Gen<T> {
226 loop { }
227 }
228}
229
230fn test() {
231 let a = Gen::make();
232 a.val<|>;
233}
234"#,
235 );
236 assert_eq!(t, "()");
237}
238
239#[test]
240fn infer_associated_method_generics_without_args() {
241 assert_snapshot!(
242 infer(r#"
243struct Gen<T> {
244 val: T
245}
246
247impl<T> Gen<T> {
248 pub fn make() -> Gen<T> {
249 loop { }
250 }
251}
252
253fn test() {
254 let a = Gen::<u32>::make();
255}
256"#),
257 @r###"
258 [76; 100) '{ ... }': Gen<T>
259 [86; 94) 'loop { }': !
260 [91; 94) '{ }': ()
261 [114; 149) '{ ...e(); }': ()
262 [124; 125) 'a': Gen<u32>
263 [128; 144) 'Gen::<...::make': fn make<u32>() -> Gen<T>
264 [128; 146) 'Gen::<...make()': Gen<u32>
265 "###
266 );
267}
268
269#[test]
270fn infer_associated_method_generics_2_type_params_without_args() {
271 assert_snapshot!(
272 infer(r#"
273struct Gen<T, U> {
274 val: T,
275 val2: U,
276}
277
278impl<T> Gen<u32, T> {
279 pub fn make() -> Gen<u32,T> {
280 loop { }
281 }
282}
283
284fn test() {
285 let a = Gen::<u32, u64>::make();
286}
287"#),
288 @r###"
289 [102; 126) '{ ... }': Gen<u32, T>
290 [112; 120) 'loop { }': !
291 [117; 120) '{ }': ()
292 [140; 180) '{ ...e(); }': ()
293 [150; 151) 'a': Gen<u32, u64>
294 [154; 175) 'Gen::<...::make': fn make<u64>() -> Gen<u32, T>
295 [154; 177) 'Gen::<...make()': Gen<u32, u64>
296 "###
297 );
298}
299
300#[test]
301fn cross_crate_associated_method_call() {
302 let (db, pos) = TestDB::with_position(
303 r#"
304//- /main.rs crate:main deps:other_crate
305fn test() {
306 let x = other_crate::foo::S::thing();
307 x<|>;
308}
309
310//- /lib.rs crate:other_crate
311mod foo {
312 struct S;
313 impl S {
314 fn thing() -> i128 {}
315 }
316}
317"#,
318 );
319 assert_eq!("i128", type_at_pos(&db, pos));
320}
321
322#[test]
323fn infer_trait_method_simple() {
324 // the trait implementation is intentionally incomplete -- it shouldn't matter
325 assert_snapshot!(
326 infer(r#"
327trait Trait1 {
328 fn method(&self) -> u32;
329}
330struct S1;
331impl Trait1 for S1 {}
332trait Trait2 {
333 fn method(&self) -> i128;
334}
335struct S2;
336impl Trait2 for S2 {}
337fn test() {
338 S1.method(); // -> u32
339 S2.method(); // -> i128
340}
341"#),
342 @r###"
343 [31; 35) 'self': &Self
344 [110; 114) 'self': &Self
345 [170; 228) '{ ...i128 }': ()
346 [176; 178) 'S1': S1
347 [176; 187) 'S1.method()': u32
348 [203; 205) 'S2': S2
349 [203; 214) 'S2.method()': i128
350 "###
351 );
352}
353
354#[test]
355fn infer_trait_method_scoped() {
356 // the trait implementation is intentionally incomplete -- it shouldn't matter
357 assert_snapshot!(
358 infer(r#"
359struct S;
360mod foo {
361 pub trait Trait1 {
362 fn method(&self) -> u32;
363 }
364 impl Trait1 for super::S {}
365}
366mod bar {
367 pub trait Trait2 {
368 fn method(&self) -> i128;
369 }
370 impl Trait2 for super::S {}
371}
372
373mod foo_test {
374 use super::S;
375 use super::foo::Trait1;
376 fn test() {
377 S.method(); // -> u32
378 }
379}
380
381mod bar_test {
382 use super::S;
383 use super::bar::Trait2;
384 fn test() {
385 S.method(); // -> i128
386 }
387}
388"#),
389 @r###"
390 [63; 67) 'self': &Self
391 [169; 173) 'self': &Self
392 [300; 337) '{ ... }': ()
393 [310; 311) 'S': S
394 [310; 320) 'S.method()': u32
395 [416; 454) '{ ... }': ()
396 [426; 427) 'S': S
397 [426; 436) 'S.method()': i128
398 "###
399 );
400}
401
402#[test]
403fn infer_trait_method_generic_1() {
404 // the trait implementation is intentionally incomplete -- it shouldn't matter
405 assert_snapshot!(
406 infer(r#"
407trait Trait<T> {
408 fn method(&self) -> T;
409}
410struct S;
411impl Trait<u32> for S {}
412fn test() {
413 S.method();
414}
415"#),
416 @r###"
417 [33; 37) 'self': &Self
418 [92; 111) '{ ...d(); }': ()
419 [98; 99) 'S': S
420 [98; 108) 'S.method()': u32
421 "###
422 );
423}
424
425#[test]
426fn infer_trait_method_generic_more_params() {
427 // the trait implementation is intentionally incomplete -- it shouldn't matter
428 assert_snapshot!(
429 infer(r#"
430trait Trait<T1, T2, T3> {
431 fn method1(&self) -> (T1, T2, T3);
432 fn method2(&self) -> (T3, T2, T1);
433}
434struct S1;
435impl Trait<u8, u16, u32> for S1 {}
436struct S2;
437impl<T> Trait<i8, i16, T> for S2 {}
438fn test() {
439 S1.method1(); // u8, u16, u32
440 S1.method2(); // u32, u16, u8
441 S2.method1(); // i8, i16, {unknown}
442 S2.method2(); // {unknown}, i16, i8
443}
444"#),
445 @r###"
446 [43; 47) 'self': &Self
447 [82; 86) 'self': &Self
448 [210; 361) '{ ..., i8 }': ()
449 [216; 218) 'S1': S1
450 [216; 228) 'S1.method1()': (u8, u16, u32)
451 [250; 252) 'S1': S1
452 [250; 262) 'S1.method2()': (u32, u16, u8)
453 [284; 286) 'S2': S2
454 [284; 296) 'S2.method1()': (i8, i16, {unknown})
455 [324; 326) 'S2': S2
456 [324; 336) 'S2.method2()': ({unknown}, i16, i8)
457 "###
458 );
459}
460
461#[test]
462fn infer_trait_method_generic_2() {
463 // the trait implementation is intentionally incomplete -- it shouldn't matter
464 assert_snapshot!(
465 infer(r#"
466trait Trait<T> {
467 fn method(&self) -> T;
468}
469struct S<T>(T);
470impl<U> Trait<U> for S<U> {}
471fn test() {
472 S(1u32).method();
473}
474"#),
475 @r###"
476 [33; 37) 'self': &Self
477 [102; 127) '{ ...d(); }': ()
478 [108; 109) 'S': S<u32>(T) -> S<T>
479 [108; 115) 'S(1u32)': S<u32>
480 [108; 124) 'S(1u32...thod()': u32
481 [110; 114) '1u32': u32
482 "###
483 );
484}
485
486#[test]
487fn infer_trait_assoc_method() {
488 assert_snapshot!(
489 infer(r#"
490trait Default {
491 fn default() -> Self;
492}
493struct S;
494impl Default for S {}
495fn test() {
496 let s1: S = Default::default();
497 let s2 = S::default();
498 let s3 = <S as Default>::default();
499}
500"#),
501 @r###"
502 [87; 193) '{ ...t(); }': ()
503 [97; 99) 's1': S
504 [105; 121) 'Defaul...efault': fn default<S>() -> Self
505 [105; 123) 'Defaul...ault()': S
506 [133; 135) 's2': S
507 [138; 148) 'S::default': fn default<S>() -> Self
508 [138; 150) 'S::default()': S
509 [160; 162) 's3': S
510 [165; 188) '<S as ...efault': fn default<S>() -> Self
511 [165; 190) '<S as ...ault()': S
512 "###
513 );
514}
515
516#[test]
517fn infer_trait_assoc_method_generics_1() {
518 assert_snapshot!(
519 infer(r#"
520trait Trait<T> {
521 fn make() -> T;
522}
523struct S;
524impl Trait<u32> for S {}
525struct G<T>;
526impl<T> Trait<T> for G<T> {}
527fn test() {
528 let a = S::make();
529 let b = G::<u64>::make();
530 let c: f64 = G::make();
531}
532"#),
533 @r###"
534 [127; 211) '{ ...e(); }': ()
535 [137; 138) 'a': u32
536 [141; 148) 'S::make': fn make<S, u32>() -> T
537 [141; 150) 'S::make()': u32
538 [160; 161) 'b': u64
539 [164; 178) 'G::<u64>::make': fn make<G<u64>, u64>() -> T
540 [164; 180) 'G::<u6...make()': u64
541 [190; 191) 'c': f64
542 [199; 206) 'G::make': fn make<G<f64>, f64>() -> T
543 [199; 208) 'G::make()': f64
544 "###
545 );
546}
547
548#[test]
549fn infer_trait_assoc_method_generics_2() {
550 assert_snapshot!(
551 infer(r#"
552trait Trait<T> {
553 fn make<U>() -> (T, U);
554}
555struct S;
556impl Trait<u32> for S {}
557struct G<T>;
558impl<T> Trait<T> for G<T> {}
559fn test() {
560 let a = S::make::<i64>();
561 let b: (_, i64) = S::make();
562 let c = G::<u32>::make::<i64>();
563 let d: (u32, _) = G::make::<i64>();
564 let e: (u32, i64) = G::make();
565}
566"#),
567 @r###"
568 [135; 313) '{ ...e(); }': ()
569 [145; 146) 'a': (u32, i64)
570 [149; 163) 'S::make::<i64>': fn make<S, u32, i64>() -> (T, U)
571 [149; 165) 'S::mak...i64>()': (u32, i64)
572 [175; 176) 'b': (u32, i64)
573 [189; 196) 'S::make': fn make<S, u32, i64>() -> (T, U)
574 [189; 198) 'S::make()': (u32, i64)
575 [208; 209) 'c': (u32, i64)
576 [212; 233) 'G::<u3...:<i64>': fn make<G<u32>, u32, i64>() -> (T, U)
577 [212; 235) 'G::<u3...i64>()': (u32, i64)
578 [245; 246) 'd': (u32, i64)
579 [259; 273) 'G::make::<i64>': fn make<G<u32>, u32, i64>() -> (T, U)
580 [259; 275) 'G::mak...i64>()': (u32, i64)
581 [285; 286) 'e': (u32, i64)
582 [301; 308) 'G::make': fn make<G<u32>, u32, i64>() -> (T, U)
583 [301; 310) 'G::make()': (u32, i64)
584 "###
585 );
586}
587
588#[test]
589fn infer_trait_assoc_method_generics_3() {
590 assert_snapshot!(
591 infer(r#"
592trait Trait<T> {
593 fn make() -> (Self, T);
594}
595struct S<T>;
596impl Trait<i64> for S<i32> {}
597fn test() {
598 let a = S::make();
599}
600"#),
601 @r###"
602 [101; 127) '{ ...e(); }': ()
603 [111; 112) 'a': (S<i32>, i64)
604 [115; 122) 'S::make': fn make<S<i32>, i64>() -> (Self, T)
605 [115; 124) 'S::make()': (S<i32>, i64)
606 "###
607 );
608}
609
610#[test]
611fn infer_trait_assoc_method_generics_4() {
612 assert_snapshot!(
613 infer(r#"
614trait Trait<T> {
615 fn make() -> (Self, T);
616}
617struct S<T>;
618impl Trait<i64> for S<u64> {}
619impl Trait<i32> for S<u32> {}
620fn test() {
621 let a: (S<u64>, _) = S::make();
622 let b: (_, i32) = S::make();
623}
624"#),
625 @r###"
626 [131; 203) '{ ...e(); }': ()
627 [141; 142) 'a': (S<u64>, i64)
628 [158; 165) 'S::make': fn make<S<u64>, i64>() -> (Self, T)
629 [158; 167) 'S::make()': (S<u64>, i64)
630 [177; 178) 'b': (S<u32>, i32)
631 [191; 198) 'S::make': fn make<S<u32>, i32>() -> (Self, T)
632 [191; 200) 'S::make()': (S<u32>, i32)
633 "###
634 );
635}
636
637#[test]
638fn infer_trait_assoc_method_generics_5() {
639 assert_snapshot!(
640 infer(r#"
641trait Trait<T> {
642 fn make<U>() -> (Self, T, U);
643}
644struct S<T>;
645impl Trait<i64> for S<u64> {}
646fn test() {
647 let a = <S as Trait<i64>>::make::<u8>();
648 let b: (S<u64>, _, _) = Trait::<i64>::make::<u8>();
649}
650"#),
651 @r###"
652 [107; 211) '{ ...>(); }': ()
653 [117; 118) 'a': (S<u64>, i64, u8)
654 [121; 150) '<S as ...::<u8>': fn make<S<u64>, i64, u8>() -> (Self, T, U)
655 [121; 152) '<S as ...<u8>()': (S<u64>, i64, u8)
656 [162; 163) 'b': (S<u64>, i64, u8)
657 [182; 206) 'Trait:...::<u8>': fn make<S<u64>, i64, u8>() -> (Self, T, U)
658 [182; 208) 'Trait:...<u8>()': (S<u64>, i64, u8)
659 "###
660 );
661}
662
663#[test]
664fn infer_call_trait_method_on_generic_param_1() {
665 assert_snapshot!(
666 infer(r#"
667trait Trait {
668 fn method(&self) -> u32;
669}
670fn test<T: Trait>(t: T) {
671 t.method();
672}
673"#),
674 @r###"
675 [30; 34) 'self': &Self
676 [64; 65) 't': T
677 [70; 89) '{ ...d(); }': ()
678 [76; 77) 't': T
679 [76; 86) 't.method()': u32
680 "###
681 );
682}
683
684#[test]
685fn infer_call_trait_method_on_generic_param_2() {
686 assert_snapshot!(
687 infer(r#"
688trait Trait<T> {
689 fn method(&self) -> T;
690}
691fn test<U, T: Trait<U>>(t: T) {
692 t.method();
693}
694"#),
695 @r###"
696 [33; 37) 'self': &Self
697 [71; 72) 't': T
698 [77; 96) '{ ...d(); }': ()
699 [83; 84) 't': T
700 [83; 93) 't.method()': [missing name]
701 "###
702 );
703}
704
705#[test]
706fn infer_with_multiple_trait_impls() {
707 assert_snapshot!(
708 infer(r#"
709trait Into<T> {
710 fn into(self) -> T;
711}
712struct S;
713impl Into<u32> for S {}
714impl Into<u64> for S {}
715fn test() {
716 let x: u32 = S.into();
717 let y: u64 = S.into();
718 let z = Into::<u64>::into(S);
719}
720"#),
721 @r###"
722 [29; 33) 'self': Self
723 [111; 202) '{ ...(S); }': ()
724 [121; 122) 'x': u32
725 [130; 131) 'S': S
726 [130; 138) 'S.into()': u32
727 [148; 149) 'y': u64
728 [157; 158) 'S': S
729 [157; 165) 'S.into()': u64
730 [175; 176) 'z': u64
731 [179; 196) 'Into::...::into': fn into<S, u64>(Self) -> T
732 [179; 199) 'Into::...nto(S)': u64
733 [197; 198) 'S': S
734 "###
735 );
736}
737
738#[test]
739fn method_resolution_unify_impl_self_type() {
740 let t = type_at(
741 r#"
742//- /main.rs
743struct S<T>;
744impl S<u32> { fn foo(&self) -> u8 {} }
745impl S<i32> { fn foo(&self) -> i8 {} }
746fn test() { (S::<u32>.foo(), S::<i32>.foo())<|>; }
747"#,
748 );
749 assert_eq!(t, "(u8, i8)");
750}
751
752#[test]
753fn method_resolution_trait_before_autoref() {
754 let t = type_at(
755 r#"
756//- /main.rs
757trait Trait { fn foo(self) -> u128; }
758struct S;
759impl S { fn foo(&self) -> i8 { 0 } }
760impl Trait for S { fn foo(self) -> u128 { 0 } }
761fn test() { S.foo()<|>; }
762"#,
763 );
764 assert_eq!(t, "u128");
765}
766
767#[test]
768fn method_resolution_by_value_before_autoref() {
769 let t = type_at(
770 r#"
771//- /main.rs
772trait Clone { fn clone(&self) -> Self; }
773struct S;
774impl Clone for S {}
775impl Clone for &S {}
776fn test() { (S.clone(), (&S).clone(), (&&S).clone())<|>; }
777"#,
778 );
779 assert_eq!(t, "(S, S, &S)");
780}
781
782#[test]
783fn method_resolution_trait_before_autoderef() {
784 let t = type_at(
785 r#"
786//- /main.rs
787trait Trait { fn foo(self) -> u128; }
788struct S;
789impl S { fn foo(self) -> i8 { 0 } }
790impl Trait for &S { fn foo(self) -> u128 { 0 } }
791fn test() { (&S).foo()<|>; }
792"#,
793 );
794 assert_eq!(t, "u128");
795}
796
797#[test]
798fn method_resolution_impl_before_trait() {
799 let t = type_at(
800 r#"
801//- /main.rs
802trait Trait { fn foo(self) -> u128; }
803struct S;
804impl S { fn foo(self) -> i8 { 0 } }
805impl Trait for S { fn foo(self) -> u128 { 0 } }
806fn test() { S.foo()<|>; }
807"#,
808 );
809 assert_eq!(t, "i8");
810}
811
812#[test]
813fn method_resolution_impl_ref_before_trait() {
814 let t = type_at(
815 r#"
816//- /main.rs
817trait Trait { fn foo(self) -> u128; }
818struct S;
819impl S { fn foo(&self) -> i8 { 0 } }
820impl Trait for &S { fn foo(self) -> u128 { 0 } }
821fn test() { S.foo()<|>; }
822"#,
823 );
824 assert_eq!(t, "i8");
825}
826
827#[test]
828fn method_resolution_trait_autoderef() {
829 let t = type_at(
830 r#"
831//- /main.rs
832trait Trait { fn foo(self) -> u128; }
833struct S;
834impl Trait for S { fn foo(self) -> u128 { 0 } }
835fn test() { (&S).foo()<|>; }
836"#,
837 );
838 assert_eq!(t, "u128");
839}
840
841#[test]
842fn method_resolution_trait_from_prelude() {
843 let (db, pos) = TestDB::with_position(
844 r#"
845//- /main.rs crate:main deps:other_crate
846struct S;
847impl Clone for S {}
848
849fn test() {
850 S.clone()<|>;
851}
852
853//- /lib.rs crate:other_crate
854#[prelude_import] use foo::*;
855
856mod foo {
857 trait Clone {
858 fn clone(&self) -> Self;
859 }
860}
861"#,
862 );
863 assert_eq!("S", type_at_pos(&db, pos));
864}
865
866#[test]
867fn method_resolution_where_clause_for_unknown_trait() {
868 // The blanket impl currently applies because we ignore the unresolved where clause
869 let t = type_at(
870 r#"
871//- /main.rs
872trait Trait { fn foo(self) -> u128; }
873struct S;
874impl<T> Trait for T where T: UnknownTrait {}
875fn test() { (&S).foo()<|>; }
876"#,
877 );
878 assert_eq!(t, "u128");
879}
880
881#[test]
882fn method_resolution_where_clause_not_met() {
883 // The blanket impl shouldn't apply because we can't prove S: Clone
884 let t = type_at(
885 r#"
886//- /main.rs
887trait Clone {}
888trait Trait { fn foo(self) -> u128; }
889struct S;
890impl<T> Trait for T where T: Clone {}
891fn test() { (&S).foo()<|>; }
892"#,
893 );
894 // This is also to make sure that we don't resolve to the foo method just
895 // because that's the only method named foo we can find, which would make
896 // the below tests not work
897 assert_eq!(t, "{unknown}");
898}
899
900#[test]
901fn method_resolution_where_clause_inline_not_met() {
902 // The blanket impl shouldn't apply because we can't prove S: Clone
903 let t = type_at(
904 r#"
905//- /main.rs
906trait Clone {}
907trait Trait { fn foo(self) -> u128; }
908struct S;
909impl<T: Clone> Trait for T {}
910fn test() { (&S).foo()<|>; }
911"#,
912 );
913 assert_eq!(t, "{unknown}");
914}
915
916#[test]
917fn method_resolution_where_clause_1() {
918 let t = type_at(
919 r#"
920//- /main.rs
921trait Clone {}
922trait Trait { fn foo(self) -> u128; }
923struct S;
924impl Clone for S {}
925impl<T> Trait for T where T: Clone {}
926fn test() { S.foo()<|>; }
927"#,
928 );
929 assert_eq!(t, "u128");
930}
931
932#[test]
933fn method_resolution_where_clause_2() {
934 let t = type_at(
935 r#"
936//- /main.rs
937trait Into<T> { fn into(self) -> T; }
938trait From<T> { fn from(other: T) -> Self; }
939struct S1;
940struct S2;
941impl From<S2> for S1 {}
942impl<T, U> Into<U> for T where U: From<T> {}
943fn test() { S2.into()<|>; }
944"#,
945 );
946 assert_eq!(t, "{unknown}");
947}
948
949#[test]
950fn method_resolution_where_clause_inline() {
951 let t = type_at(
952 r#"
953//- /main.rs
954trait Into<T> { fn into(self) -> T; }
955trait From<T> { fn from(other: T) -> Self; }
956struct S1;
957struct S2;
958impl From<S2> for S1 {}
959impl<T, U: From<T>> Into<U> for T {}
960fn test() { S2.into()<|>; }
961"#,
962 );
963 assert_eq!(t, "{unknown}");
964}
965
966#[test]
967fn method_resolution_encountering_fn_type() {
968 type_at(
969 r#"
970//- /main.rs
971fn foo() {}
972trait FnOnce { fn call(self); }
973fn test() { foo.call()<|>; }
974"#,
975 );
976}
977
978#[test]
979fn method_resolution_slow() {
980 // this can get quite slow if we set the solver size limit too high
981 let t = type_at(
982 r#"
983//- /main.rs
984trait SendX {}
985
986struct S1; impl SendX for S1 {}
987struct S2; impl SendX for S2 {}
988struct U1;
989
990trait Trait { fn method(self); }
991
992struct X1<A, B> {}
993impl<A, B> SendX for X1<A, B> where A: SendX, B: SendX {}
994
995struct S<B, C> {}
996
997trait FnX {}
998
999impl<B, C> Trait for S<B, C> where C: FnX, B: SendX {}
1000
1001fn test() { (S {}).method()<|>; }
1002"#,
1003 );
1004 assert_eq!(t, "()");
1005}
diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs
new file mode 100644
index 000000000..cb3890b42
--- /dev/null
+++ b/crates/ra_hir_ty/src/tests/patterns.rs
@@ -0,0 +1,238 @@
1use super::infer;
2use insta::assert_snapshot;
3use test_utils::covers;
4
5#[test]
6fn infer_pattern() {
7 assert_snapshot!(
8 infer(r#"
9fn test(x: &i32) {
10 let y = x;
11 let &z = x;
12 let a = z;
13 let (c, d) = (1, "hello");
14
15 for (e, f) in some_iter {
16 let g = e;
17 }
18
19 if let [val] = opt {
20 let h = val;
21 }
22
23 let lambda = |a: u64, b, c: i32| { a + b; c };
24
25 let ref ref_to_x = x;
26 let mut mut_x = x;
27 let ref mut mut_ref_to_x = x;
28 let k = mut_ref_to_x;
29}
30"#),
31 @r###"
32 [9; 10) 'x': &i32
33 [18; 369) '{ ...o_x; }': ()
34 [28; 29) 'y': &i32
35 [32; 33) 'x': &i32
36 [43; 45) '&z': &i32
37 [44; 45) 'z': i32
38 [48; 49) 'x': &i32
39 [59; 60) 'a': i32
40 [63; 64) 'z': i32
41 [74; 80) '(c, d)': (i32, &str)
42 [75; 76) 'c': i32
43 [78; 79) 'd': &str
44 [83; 95) '(1, "hello")': (i32, &str)
45 [84; 85) '1': i32
46 [87; 94) '"hello"': &str
47 [102; 152) 'for (e... }': ()
48 [106; 112) '(e, f)': ({unknown}, {unknown})
49 [107; 108) 'e': {unknown}
50 [110; 111) 'f': {unknown}
51 [116; 125) 'some_iter': {unknown}
52 [126; 152) '{ ... }': ()
53 [140; 141) 'g': {unknown}
54 [144; 145) 'e': {unknown}
55 [158; 205) 'if let... }': ()
56 [165; 170) '[val]': {unknown}
57 [173; 176) 'opt': {unknown}
58 [177; 205) '{ ... }': ()
59 [191; 192) 'h': {unknown}
60 [195; 198) 'val': {unknown}
61 [215; 221) 'lambda': |u64, u64, i32| -> i32
62 [224; 256) '|a: u6...b; c }': |u64, u64, i32| -> i32
63 [225; 226) 'a': u64
64 [233; 234) 'b': u64
65 [236; 237) 'c': i32
66 [244; 256) '{ a + b; c }': i32
67 [246; 247) 'a': u64
68 [246; 251) 'a + b': u64
69 [250; 251) 'b': u64
70 [253; 254) 'c': i32
71 [267; 279) 'ref ref_to_x': &&i32
72 [282; 283) 'x': &i32
73 [293; 302) 'mut mut_x': &i32
74 [305; 306) 'x': &i32
75 [316; 336) 'ref mu...f_to_x': &mut &i32
76 [339; 340) 'x': &i32
77 [350; 351) 'k': &mut &i32
78 [354; 366) 'mut_ref_to_x': &mut &i32
79 "###
80 );
81}
82
83#[test]
84fn infer_pattern_match_ergonomics() {
85 assert_snapshot!(
86 infer(r#"
87struct A<T>(T);
88
89fn test() {
90 let A(n) = &A(1);
91 let A(n) = &mut A(1);
92}
93"#),
94 @r###"
95 [28; 79) '{ ...(1); }': ()
96 [38; 42) 'A(n)': A<i32>
97 [40; 41) 'n': &i32
98 [45; 50) '&A(1)': &A<i32>
99 [46; 47) 'A': A<i32>(T) -> A<T>
100 [46; 50) 'A(1)': A<i32>
101 [48; 49) '1': i32
102 [60; 64) 'A(n)': A<i32>
103 [62; 63) 'n': &mut i32
104 [67; 76) '&mut A(1)': &mut A<i32>
105 [72; 73) 'A': A<i32>(T) -> A<T>
106 [72; 76) 'A(1)': A<i32>
107 [74; 75) '1': i32
108 "###
109 );
110}
111
112#[test]
113fn infer_pattern_match_ergonomics_ref() {
114 covers!(match_ergonomics_ref);
115 assert_snapshot!(
116 infer(r#"
117fn test() {
118 let v = &(1, &2);
119 let (_, &w) = v;
120}
121"#),
122 @r###"
123 [11; 57) '{ ...= v; }': ()
124 [21; 22) 'v': &(i32, &i32)
125 [25; 33) '&(1, &2)': &(i32, &i32)
126 [26; 33) '(1, &2)': (i32, &i32)
127 [27; 28) '1': i32
128 [30; 32) '&2': &i32
129 [31; 32) '2': i32
130 [43; 50) '(_, &w)': (i32, &i32)
131 [44; 45) '_': i32
132 [47; 49) '&w': &i32
133 [48; 49) 'w': i32
134 [53; 54) 'v': &(i32, &i32)
135 "###
136 );
137}
138
139#[test]
140fn infer_adt_pattern() {
141 assert_snapshot!(
142 infer(r#"
143enum E {
144 A { x: usize },
145 B
146}
147
148struct S(u32, E);
149
150fn test() {
151 let e = E::A { x: 3 };
152
153 let S(y, z) = foo;
154 let E::A { x: new_var } = e;
155
156 match e {
157 E::A { x } => x,
158 E::B if foo => 1,
159 E::B => 10,
160 };
161
162 let ref d @ E::A { .. } = e;
163 d;
164}
165"#),
166 @r###"
167 [68; 289) '{ ... d; }': ()
168 [78; 79) 'e': E
169 [82; 95) 'E::A { x: 3 }': E
170 [92; 93) '3': usize
171 [106; 113) 'S(y, z)': S
172 [108; 109) 'y': u32
173 [111; 112) 'z': E
174 [116; 119) 'foo': S
175 [129; 148) 'E::A {..._var }': E
176 [139; 146) 'new_var': usize
177 [151; 152) 'e': E
178 [159; 245) 'match ... }': usize
179 [165; 166) 'e': E
180 [177; 187) 'E::A { x }': E
181 [184; 185) 'x': usize
182 [191; 192) 'x': usize
183 [202; 206) 'E::B': E
184 [210; 213) 'foo': bool
185 [217; 218) '1': usize
186 [228; 232) 'E::B': E
187 [236; 238) '10': usize
188 [256; 275) 'ref d ...{ .. }': &E
189 [264; 275) 'E::A { .. }': E
190 [278; 279) 'e': E
191 [285; 286) 'd': &E
192 "###
193 );
194}
195
196#[test]
197fn infer_generics_in_patterns() {
198 assert_snapshot!(
199 infer(r#"
200struct A<T> {
201 x: T,
202}
203
204enum Option<T> {
205 Some(T),
206 None,
207}
208
209fn test(a1: A<u32>, o: Option<u64>) {
210 let A { x: x2 } = a1;
211 let A::<i64> { x: x3 } = A { x: 1 };
212 match o {
213 Option::Some(t) => t,
214 _ => 1,
215 };
216}
217"#),
218 @r###"
219 [79; 81) 'a1': A<u32>
220 [91; 92) 'o': Option<u64>
221 [107; 244) '{ ... }; }': ()
222 [117; 128) 'A { x: x2 }': A<u32>
223 [124; 126) 'x2': u32
224 [131; 133) 'a1': A<u32>
225 [143; 161) 'A::<i6...: x3 }': A<i64>
226 [157; 159) 'x3': i64
227 [164; 174) 'A { x: 1 }': A<i64>
228 [171; 172) '1': i64
229 [180; 241) 'match ... }': u64
230 [186; 187) 'o': Option<u64>
231 [198; 213) 'Option::Some(t)': Option<u64>
232 [211; 212) 't': u64
233 [217; 218) 't': u64
234 [228; 229) '_': Option<u64>
235 [233; 234) '1': u64
236 "###
237 );
238}
diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs
new file mode 100644
index 000000000..09d684ac2
--- /dev/null
+++ b/crates/ra_hir_ty/src/tests/regression.rs
@@ -0,0 +1,333 @@
1use super::infer;
2use insta::assert_snapshot;
3use test_utils::covers;
4
5#[test]
6fn bug_484() {
7 assert_snapshot!(
8 infer(r#"
9fn test() {
10 let x = if true {};
11}
12"#),
13 @r###"
14 [11; 37) '{ l... {}; }': ()
15 [20; 21) 'x': ()
16 [24; 34) 'if true {}': ()
17 [27; 31) 'true': bool
18 [32; 34) '{}': ()
19 "###
20 );
21}
22
23#[test]
24fn no_panic_on_field_of_enum() {
25 assert_snapshot!(
26 infer(r#"
27enum X {}
28
29fn test(x: X) {
30 x.some_field;
31}
32"#),
33 @r###"
34 [20; 21) 'x': X
35 [26; 47) '{ ...eld; }': ()
36 [32; 33) 'x': X
37 [32; 44) 'x.some_field': {unknown}
38 "###
39 );
40}
41
42#[test]
43fn bug_585() {
44 assert_snapshot!(
45 infer(r#"
46fn test() {
47 X {};
48 match x {
49 A::B {} => (),
50 A::Y() => (),
51 }
52}
53"#),
54 @r###"
55 [11; 89) '{ ... } }': ()
56 [17; 21) 'X {}': {unknown}
57 [27; 87) 'match ... }': ()
58 [33; 34) 'x': {unknown}
59 [45; 52) 'A::B {}': {unknown}
60 [56; 58) '()': ()
61 [68; 74) 'A::Y()': {unknown}
62 [78; 80) '()': ()
63 "###
64 );
65}
66
67#[test]
68fn bug_651() {
69 assert_snapshot!(
70 infer(r#"
71fn quux() {
72 let y = 92;
73 1 + y;
74}
75"#),
76 @r###"
77 [11; 41) '{ ...+ y; }': ()
78 [21; 22) 'y': i32
79 [25; 27) '92': i32
80 [33; 34) '1': i32
81 [33; 38) '1 + y': i32
82 [37; 38) 'y': i32
83 "###
84 );
85}
86
87#[test]
88fn recursive_vars() {
89 covers!(type_var_cycles_resolve_completely);
90 covers!(type_var_cycles_resolve_as_possible);
91 assert_snapshot!(
92 infer(r#"
93fn test() {
94 let y = unknown;
95 [y, &y];
96}
97"#),
98 @r###"
99 [11; 48) '{ ...&y]; }': ()
100 [21; 22) 'y': &{unknown}
101 [25; 32) 'unknown': &{unknown}
102 [38; 45) '[y, &y]': [&&{unknown};_]
103 [39; 40) 'y': &{unknown}
104 [42; 44) '&y': &&{unknown}
105 [43; 44) 'y': &{unknown}
106 "###
107 );
108}
109
110#[test]
111fn recursive_vars_2() {
112 covers!(type_var_cycles_resolve_completely);
113 covers!(type_var_cycles_resolve_as_possible);
114 assert_snapshot!(
115 infer(r#"
116fn test() {
117 let x = unknown;
118 let y = unknown;
119 [(x, y), (&y, &x)];
120}
121"#),
122 @r###"
123 [11; 80) '{ ...x)]; }': ()
124 [21; 22) 'x': &&{unknown}
125 [25; 32) 'unknown': &&{unknown}
126 [42; 43) 'y': &&{unknown}
127 [46; 53) 'unknown': &&{unknown}
128 [59; 77) '[(x, y..., &x)]': [(&&&{unknown}, &&&{unknown});_]
129 [60; 66) '(x, y)': (&&&{unknown}, &&&{unknown})
130 [61; 62) 'x': &&{unknown}
131 [64; 65) 'y': &&{unknown}
132 [68; 76) '(&y, &x)': (&&&{unknown}, &&&{unknown})
133 [69; 71) '&y': &&&{unknown}
134 [70; 71) 'y': &&{unknown}
135 [73; 75) '&x': &&&{unknown}
136 [74; 75) 'x': &&{unknown}
137 "###
138 );
139}
140
141#[test]
142fn infer_std_crash_1() {
143 // caused stack overflow, taken from std
144 assert_snapshot!(
145 infer(r#"
146enum Maybe<T> {
147 Real(T),
148 Fake,
149}
150
151fn write() {
152 match something_unknown {
153 Maybe::Real(ref mut something) => (),
154 }
155}
156"#),
157 @r###"
158 [54; 139) '{ ... } }': ()
159 [60; 137) 'match ... }': ()
160 [66; 83) 'someth...nknown': Maybe<{unknown}>
161 [94; 124) 'Maybe:...thing)': Maybe<{unknown}>
162 [106; 123) 'ref mu...ething': &mut {unknown}
163 [128; 130) '()': ()
164 "###
165 );
166}
167
168#[test]
169fn infer_std_crash_2() {
170 covers!(type_var_resolves_to_int_var);
171 // caused "equating two type variables, ...", taken from std
172 assert_snapshot!(
173 infer(r#"
174fn test_line_buffer() {
175 &[0, b'\n', 1, b'\n'];
176}
177"#),
178 @r###"
179 [23; 53) '{ ...n']; }': ()
180 [29; 50) '&[0, b...b'\n']': &[u8;_]
181 [30; 50) '[0, b'...b'\n']': [u8;_]
182 [31; 32) '0': u8
183 [34; 39) 'b'\n'': u8
184 [41; 42) '1': u8
185 [44; 49) 'b'\n'': u8
186 "###
187 );
188}
189
190#[test]
191fn infer_std_crash_3() {
192 // taken from rustc
193 assert_snapshot!(
194 infer(r#"
195pub fn compute() {
196 match nope!() {
197 SizeSkeleton::Pointer { non_zero: true, tail } => {}
198 }
199}
200"#),
201 @r###"
202 [18; 108) '{ ... } }': ()
203 [24; 106) 'match ... }': ()
204 [30; 37) 'nope!()': {unknown}
205 [48; 94) 'SizeSk...tail }': {unknown}
206 [82; 86) 'true': {unknown}
207 [88; 92) 'tail': {unknown}
208 [98; 100) '{}': ()
209 "###
210 );
211}
212
213#[test]
214fn infer_std_crash_4() {
215 // taken from rustc
216 assert_snapshot!(
217 infer(r#"
218pub fn primitive_type() {
219 match *self {
220 BorrowedRef { type_: Primitive(p), ..} => {},
221 }
222}
223"#),
224 @r###"
225 [25; 106) '{ ... } }': ()
226 [31; 104) 'match ... }': ()
227 [37; 42) '*self': {unknown}
228 [38; 42) 'self': {unknown}
229 [53; 91) 'Borrow...), ..}': {unknown}
230 [74; 86) 'Primitive(p)': {unknown}
231 [84; 85) 'p': {unknown}
232 [95; 97) '{}': ()
233 "###
234 );
235}
236
237#[test]
238fn infer_std_crash_5() {
239 // taken from rustc
240 assert_snapshot!(
241 infer(r#"
242fn extra_compiler_flags() {
243 for content in doesnt_matter {
244 let name = if doesnt_matter {
245 first
246 } else {
247 &content
248 };
249
250 let content = if ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.contains(&name) {
251 name
252 } else {
253 content
254 };
255 }
256}
257"#),
258 @r###"
259 [27; 323) '{ ... } }': ()
260 [33; 321) 'for co... }': ()
261 [37; 44) 'content': &{unknown}
262 [48; 61) 'doesnt_matter': {unknown}
263 [62; 321) '{ ... }': ()
264 [76; 80) 'name': &&{unknown}
265 [83; 167) 'if doe... }': &&{unknown}
266 [86; 99) 'doesnt_matter': bool
267 [100; 129) '{ ... }': &&{unknown}
268 [114; 119) 'first': &&{unknown}
269 [135; 167) '{ ... }': &&{unknown}
270 [149; 157) '&content': &&{unknown}
271 [150; 157) 'content': &{unknown}
272 [182; 189) 'content': &{unknown}
273 [192; 314) 'if ICE... }': &{unknown}
274 [195; 232) 'ICE_RE..._VALUE': {unknown}
275 [195; 248) 'ICE_RE...&name)': bool
276 [242; 247) '&name': &&&{unknown}
277 [243; 247) 'name': &&{unknown}
278 [249; 277) '{ ... }': &&{unknown}
279 [263; 267) 'name': &&{unknown}
280 [283; 314) '{ ... }': &{unknown}
281 [297; 304) 'content': &{unknown}
282 "###
283 );
284}
285
286#[test]
287fn infer_nested_generics_crash() {
288 // another crash found typechecking rustc
289 assert_snapshot!(
290 infer(r#"
291struct Canonical<V> {
292 value: V,
293}
294struct QueryResponse<V> {
295 value: V,
296}
297fn test<R>(query_response: Canonical<QueryResponse<R>>) {
298 &query_response.value;
299}
300"#),
301 @r###"
302 [92; 106) 'query_response': Canonical<QueryResponse<R>>
303 [137; 167) '{ ...lue; }': ()
304 [143; 164) '&query....value': &QueryResponse<R>
305 [144; 158) 'query_response': Canonical<QueryResponse<R>>
306 [144; 164) 'query_....value': QueryResponse<R>
307 "###
308 );
309}
310
311#[test]
312fn bug_1030() {
313 assert_snapshot!(infer(r#"
314struct HashSet<T, H>;
315struct FxHasher;
316type FxHashSet<T> = HashSet<T, FxHasher>;
317
318impl<T, H> HashSet<T, H> {
319 fn default() -> HashSet<T, H> {}
320}
321
322pub fn main_loop() {
323 FxHashSet::default();
324}
325"#),
326 @r###"
327 [144; 146) '{}': ()
328 [169; 198) '{ ...t(); }': ()
329 [175; 193) 'FxHash...efault': fn default<{unknown}, FxHasher>() -> HashSet<T, H>
330 [175; 195) 'FxHash...ault()': HashSet<{unknown}, FxHasher>
331 "###
332 );
333}
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs
new file mode 100644
index 000000000..3e5e163e3
--- /dev/null
+++ b/crates/ra_hir_ty/src/tests/simple.rs
@@ -0,0 +1,1663 @@
1use super::{infer, type_at, type_at_pos};
2use crate::test_db::TestDB;
3use insta::assert_snapshot;
4use ra_db::fixture::WithFixture;
5
6#[test]
7fn infer_box() {
8 let (db, pos) = TestDB::with_position(
9 r#"
10//- /main.rs crate:main deps:std
11
12fn test() {
13 let x = box 1;
14 let t = (x, box x, box &1, box [1]);
15 t<|>;
16}
17
18//- /std.rs crate:std
19#[prelude_import] use prelude::*;
20mod prelude {}
21
22mod boxed {
23 pub struct Box<T: ?Sized> {
24 inner: *mut T,
25 }
26}
27
28"#,
29 );
30 assert_eq!("(Box<i32>, Box<Box<i32>>, Box<&i32>, Box<[i32;_]>)", type_at_pos(&db, pos));
31}
32
33#[test]
34fn infer_adt_self() {
35 let (db, pos) = TestDB::with_position(
36 r#"
37//- /main.rs
38enum Nat { Succ(Self), Demo(Nat), Zero }
39
40fn test() {
41 let foo: Nat = Nat::Zero;
42 if let Nat::Succ(x) = foo {
43 x<|>
44 }
45}
46
47"#,
48 );
49 assert_eq!("Nat", type_at_pos(&db, pos));
50}
51
52#[test]
53fn infer_ranges() {
54 let (db, pos) = TestDB::with_position(
55 r#"
56//- /main.rs crate:main deps:std
57fn test() {
58 let a = ..;
59 let b = 1..;
60 let c = ..2u32;
61 let d = 1..2usize;
62 let e = ..=10;
63 let f = 'a'..='z';
64
65 let t = (a, b, c, d, e, f);
66 t<|>;
67}
68
69//- /std.rs crate:std
70#[prelude_import] use prelude::*;
71mod prelude {}
72
73pub mod ops {
74 pub struct Range<Idx> {
75 pub start: Idx,
76 pub end: Idx,
77 }
78 pub struct RangeFrom<Idx> {
79 pub start: Idx,
80 }
81 struct RangeFull;
82 pub struct RangeInclusive<Idx> {
83 start: Idx,
84 end: Idx,
85 is_empty: u8,
86 }
87 pub struct RangeTo<Idx> {
88 pub end: Idx,
89 }
90 pub struct RangeToInclusive<Idx> {
91 pub end: Idx,
92 }
93}
94"#,
95 );
96 assert_eq!(
97 "(RangeFull, RangeFrom<i32>, RangeTo<u32>, Range<usize>, RangeToInclusive<i32>, RangeInclusive<char>)",
98 type_at_pos(&db, pos),
99 );
100}
101
102#[test]
103fn infer_while_let() {
104 let (db, pos) = TestDB::with_position(
105 r#"
106//- /main.rs
107enum Option<T> { Some(T), None }
108
109fn test() {
110 let foo: Option<f32> = None;
111 while let Option::Some(x) = foo {
112 <|>x
113 }
114}
115
116"#,
117 );
118 assert_eq!("f32", type_at_pos(&db, pos));
119}
120
121#[test]
122fn infer_basics() {
123 assert_snapshot!(
124 infer(r#"
125fn test(a: u32, b: isize, c: !, d: &str) {
126 a;
127 b;
128 c;
129 d;
130 1usize;
131 1isize;
132 "test";
133 1.0f32;
134}"#),
135 @r###"
136 [9; 10) 'a': u32
137 [17; 18) 'b': isize
138 [27; 28) 'c': !
139 [33; 34) 'd': &str
140 [42; 121) '{ ...f32; }': !
141 [48; 49) 'a': u32
142 [55; 56) 'b': isize
143 [62; 63) 'c': !
144 [69; 70) 'd': &str
145 [76; 82) '1usize': usize
146 [88; 94) '1isize': isize
147 [100; 106) '"test"': &str
148 [112; 118) '1.0f32': f32
149 "###
150 );
151}
152
153#[test]
154fn infer_let() {
155 assert_snapshot!(
156 infer(r#"
157fn test() {
158 let a = 1isize;
159 let b: usize = 1;
160 let c = b;
161 let d: u32;
162 let e;
163 let f: i32 = e;
164}
165"#),
166 @r###"
167 [11; 118) '{ ...= e; }': ()
168 [21; 22) 'a': isize
169 [25; 31) '1isize': isize
170 [41; 42) 'b': usize
171 [52; 53) '1': usize
172 [63; 64) 'c': usize
173 [67; 68) 'b': usize
174 [78; 79) 'd': u32
175 [94; 95) 'e': i32
176 [105; 106) 'f': i32
177 [114; 115) 'e': i32
178 "###
179 );
180}
181
182#[test]
183fn infer_paths() {
184 assert_snapshot!(
185 infer(r#"
186fn a() -> u32 { 1 }
187
188mod b {
189 fn c() -> u32 { 1 }
190}
191
192fn test() {
193 a();
194 b::c();
195}
196"#),
197 @r###"
198 [15; 20) '{ 1 }': u32
199 [17; 18) '1': u32
200 [48; 53) '{ 1 }': u32
201 [50; 51) '1': u32
202 [67; 91) '{ ...c(); }': ()
203 [73; 74) 'a': fn a() -> u32
204 [73; 76) 'a()': u32
205 [82; 86) 'b::c': fn c() -> u32
206 [82; 88) 'b::c()': u32
207 "###
208 );
209}
210
211#[test]
212fn infer_path_type() {
213 assert_snapshot!(
214 infer(r#"
215struct S;
216
217impl S {
218 fn foo() -> i32 { 1 }
219}
220
221fn test() {
222 S::foo();
223 <S>::foo();
224}
225"#),
226 @r###"
227 [41; 46) '{ 1 }': i32
228 [43; 44) '1': i32
229 [60; 93) '{ ...o(); }': ()
230 [66; 72) 'S::foo': fn foo() -> i32
231 [66; 74) 'S::foo()': i32
232 [80; 88) '<S>::foo': fn foo() -> i32
233 [80; 90) '<S>::foo()': i32
234 "###
235 );
236}
237
238#[test]
239fn infer_struct() {
240 assert_snapshot!(
241 infer(r#"
242struct A {
243 b: B,
244 c: C,
245}
246struct B;
247struct C(usize);
248
249fn test() {
250 let c = C(1);
251 B;
252 let a: A = A { b: B, c: C(1) };
253 a.b;
254 a.c;
255}
256"#),
257 @r###"
258 [72; 154) '{ ...a.c; }': ()
259 [82; 83) 'c': C
260 [86; 87) 'C': C(usize) -> C
261 [86; 90) 'C(1)': C
262 [88; 89) '1': usize
263 [96; 97) 'B': B
264 [107; 108) 'a': A
265 [114; 133) 'A { b:...C(1) }': A
266 [121; 122) 'B': B
267 [127; 128) 'C': C(usize) -> C
268 [127; 131) 'C(1)': C
269 [129; 130) '1': usize
270 [139; 140) 'a': A
271 [139; 142) 'a.b': B
272 [148; 149) 'a': A
273 [148; 151) 'a.c': C
274 "###
275 );
276}
277
278#[test]
279fn infer_enum() {
280 assert_snapshot!(
281 infer(r#"
282enum E {
283 V1 { field: u32 },
284 V2
285}
286fn test() {
287 E::V1 { field: 1 };
288 E::V2;
289}"#),
290 @r###"
291 [48; 82) '{ E:...:V2; }': ()
292 [52; 70) 'E::V1 ...d: 1 }': E
293 [67; 68) '1': u32
294 [74; 79) 'E::V2': E
295 "###
296 );
297}
298
299#[test]
300fn infer_refs() {
301 assert_snapshot!(
302 infer(r#"
303fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) {
304 a;
305 *a;
306 &a;
307 &mut a;
308 b;
309 *b;
310 &b;
311 c;
312 *c;
313 d;
314 *d;
315}
316"#),
317 @r###"
318 [9; 10) 'a': &u32
319 [18; 19) 'b': &mut u32
320 [31; 32) 'c': *const u32
321 [46; 47) 'd': *mut u32
322 [59; 150) '{ ... *d; }': ()
323 [65; 66) 'a': &u32
324 [72; 74) '*a': u32
325 [73; 74) 'a': &u32
326 [80; 82) '&a': &&u32
327 [81; 82) 'a': &u32
328 [88; 94) '&mut a': &mut &u32
329 [93; 94) 'a': &u32
330 [100; 101) 'b': &mut u32
331 [107; 109) '*b': u32
332 [108; 109) 'b': &mut u32
333 [115; 117) '&b': &&mut u32
334 [116; 117) 'b': &mut u32
335 [123; 124) 'c': *const u32
336 [130; 132) '*c': u32
337 [131; 132) 'c': *const u32
338 [138; 139) 'd': *mut u32
339 [145; 147) '*d': u32
340 [146; 147) 'd': *mut u32
341 "###
342 );
343}
344
345#[test]
346fn infer_literals() {
347 assert_snapshot!(
348 infer(r##"
349fn test() {
350 5i32;
351 5f32;
352 5f64;
353 "hello";
354 b"bytes";
355 'c';
356 b'b';
357 3.14;
358 5000;
359 false;
360 true;
361 r#"
362 //! doc
363 // non-doc
364 mod foo {}
365 "#;
366 br#"yolo"#;
367}
368"##),
369 @r###"
370 [11; 221) '{ ...o"#; }': ()
371 [17; 21) '5i32': i32
372 [27; 31) '5f32': f32
373 [37; 41) '5f64': f64
374 [47; 54) '"hello"': &str
375 [60; 68) 'b"bytes"': &[u8]
376 [74; 77) ''c'': char
377 [83; 87) 'b'b'': u8
378 [93; 97) '3.14': f64
379 [103; 107) '5000': i32
380 [113; 118) 'false': bool
381 [124; 128) 'true': bool
382 [134; 202) 'r#" ... "#': &str
383 [208; 218) 'br#"yolo"#': &[u8]
384 "###
385 );
386}
387
388#[test]
389fn infer_unary_op() {
390 assert_snapshot!(
391 infer(r#"
392enum SomeType {}
393
394fn test(x: SomeType) {
395 let b = false;
396 let c = !b;
397 let a = 100;
398 let d: i128 = -a;
399 let e = -100;
400 let f = !!!true;
401 let g = !42;
402 let h = !10u32;
403 let j = !a;
404 -3.14;
405 !3;
406 -x;
407 !x;
408 -"hello";
409 !"hello";
410}
411"#),
412 @r###"
413 [27; 28) 'x': SomeType
414 [40; 272) '{ ...lo"; }': ()
415 [50; 51) 'b': bool
416 [54; 59) 'false': bool
417 [69; 70) 'c': bool
418 [73; 75) '!b': bool
419 [74; 75) 'b': bool
420 [85; 86) 'a': i128
421 [89; 92) '100': i128
422 [102; 103) 'd': i128
423 [112; 114) '-a': i128
424 [113; 114) 'a': i128
425 [124; 125) 'e': i32
426 [128; 132) '-100': i32
427 [129; 132) '100': i32
428 [142; 143) 'f': bool
429 [146; 153) '!!!true': bool
430 [147; 153) '!!true': bool
431 [148; 153) '!true': bool
432 [149; 153) 'true': bool
433 [163; 164) 'g': i32
434 [167; 170) '!42': i32
435 [168; 170) '42': i32
436 [180; 181) 'h': u32
437 [184; 190) '!10u32': u32
438 [185; 190) '10u32': u32
439 [200; 201) 'j': i128
440 [204; 206) '!a': i128
441 [205; 206) 'a': i128
442 [212; 217) '-3.14': f64
443 [213; 217) '3.14': f64
444 [223; 225) '!3': i32
445 [224; 225) '3': i32
446 [231; 233) '-x': {unknown}
447 [232; 233) 'x': SomeType
448 [239; 241) '!x': {unknown}
449 [240; 241) 'x': SomeType
450 [247; 255) '-"hello"': {unknown}
451 [248; 255) '"hello"': &str
452 [261; 269) '!"hello"': {unknown}
453 [262; 269) '"hello"': &str
454 "###
455 );
456}
457
458#[test]
459fn infer_backwards() {
460 assert_snapshot!(
461 infer(r#"
462fn takes_u32(x: u32) {}
463
464struct S { i32_field: i32 }
465
466fn test() -> &mut &f64 {
467 let a = unknown_function();
468 takes_u32(a);
469 let b = unknown_function();
470 S { i32_field: b };
471 let c = unknown_function();
472 &mut &c
473}
474"#),
475 @r###"
476 [14; 15) 'x': u32
477 [22; 24) '{}': ()
478 [78; 231) '{ ...t &c }': &mut &f64
479 [88; 89) 'a': u32
480 [92; 108) 'unknow...nction': {unknown}
481 [92; 110) 'unknow...tion()': u32
482 [116; 125) 'takes_u32': fn takes_u32(u32) -> ()
483 [116; 128) 'takes_u32(a)': ()
484 [126; 127) 'a': u32
485 [138; 139) 'b': i32
486 [142; 158) 'unknow...nction': {unknown}
487 [142; 160) 'unknow...tion()': i32
488 [166; 184) 'S { i3...d: b }': S
489 [181; 182) 'b': i32
490 [194; 195) 'c': f64
491 [198; 214) 'unknow...nction': {unknown}
492 [198; 216) 'unknow...tion()': f64
493 [222; 229) '&mut &c': &mut &f64
494 [227; 229) '&c': &f64
495 [228; 229) 'c': f64
496 "###
497 );
498}
499
500#[test]
501fn infer_self() {
502 assert_snapshot!(
503 infer(r#"
504struct S;
505
506impl S {
507 fn test(&self) {
508 self;
509 }
510 fn test2(self: &Self) {
511 self;
512 }
513 fn test3() -> Self {
514 S {}
515 }
516 fn test4() -> Self {
517 Self {}
518 }
519}
520"#),
521 @r###"
522 [34; 38) 'self': &S
523 [40; 61) '{ ... }': ()
524 [50; 54) 'self': &S
525 [75; 79) 'self': &S
526 [88; 109) '{ ... }': ()
527 [98; 102) 'self': &S
528 [133; 153) '{ ... }': S
529 [143; 147) 'S {}': S
530 [177; 200) '{ ... }': S
531 [187; 194) 'Self {}': S
532 "###
533 );
534}
535
536#[test]
537fn infer_binary_op() {
538 assert_snapshot!(
539 infer(r#"
540fn f(x: bool) -> i32 {
541 0i32
542}
543
544fn test() -> bool {
545 let x = a && b;
546 let y = true || false;
547 let z = x == y;
548 let t = x != y;
549 let minus_forty: isize = -40isize;
550 let h = minus_forty <= CONST_2;
551 let c = f(z || y) + 5;
552 let d = b;
553 let g = minus_forty ^= i;
554 let ten: usize = 10;
555 let ten_is_eleven = ten == some_num;
556
557 ten < 3
558}
559"#),
560 @r###"
561 [6; 7) 'x': bool
562 [22; 34) '{ 0i32 }': i32
563 [28; 32) '0i32': i32
564 [54; 370) '{ ... < 3 }': bool
565 [64; 65) 'x': bool
566 [68; 69) 'a': bool
567 [68; 74) 'a && b': bool
568 [73; 74) 'b': bool
569 [84; 85) 'y': bool
570 [88; 92) 'true': bool
571 [88; 101) 'true || false': bool
572 [96; 101) 'false': bool
573 [111; 112) 'z': bool
574 [115; 116) 'x': bool
575 [115; 121) 'x == y': bool
576 [120; 121) 'y': bool
577 [131; 132) 't': bool
578 [135; 136) 'x': bool
579 [135; 141) 'x != y': bool
580 [140; 141) 'y': bool
581 [151; 162) 'minus_forty': isize
582 [172; 180) '-40isize': isize
583 [173; 180) '40isize': isize
584 [190; 191) 'h': bool
585 [194; 205) 'minus_forty': isize
586 [194; 216) 'minus_...ONST_2': bool
587 [209; 216) 'CONST_2': isize
588 [226; 227) 'c': i32
589 [230; 231) 'f': fn f(bool) -> i32
590 [230; 239) 'f(z || y)': i32
591 [230; 243) 'f(z || y) + 5': i32
592 [232; 233) 'z': bool
593 [232; 238) 'z || y': bool
594 [237; 238) 'y': bool
595 [242; 243) '5': i32
596 [253; 254) 'd': {unknown}
597 [257; 258) 'b': {unknown}
598 [268; 269) 'g': ()
599 [272; 283) 'minus_forty': isize
600 [272; 288) 'minus_...y ^= i': ()
601 [287; 288) 'i': isize
602 [298; 301) 'ten': usize
603 [311; 313) '10': usize
604 [323; 336) 'ten_is_eleven': bool
605 [339; 342) 'ten': usize
606 [339; 354) 'ten == some_num': bool
607 [346; 354) 'some_num': usize
608 [361; 364) 'ten': usize
609 [361; 368) 'ten < 3': bool
610 [367; 368) '3': usize
611 "###
612 );
613}
614
615#[test]
616fn infer_field_autoderef() {
617 assert_snapshot!(
618 infer(r#"
619struct A {
620 b: B,
621}
622struct B;
623
624fn test1(a: A) {
625 let a1 = a;
626 a1.b;
627 let a2 = &a;
628 a2.b;
629 let a3 = &mut a;
630 a3.b;
631 let a4 = &&&&&&&a;
632 a4.b;
633 let a5 = &mut &&mut &&mut a;
634 a5.b;
635}
636
637fn test2(a1: *const A, a2: *mut A) {
638 a1.b;
639 a2.b;
640}
641"#),
642 @r###"
643 [44; 45) 'a': A
644 [50; 213) '{ ...5.b; }': ()
645 [60; 62) 'a1': A
646 [65; 66) 'a': A
647 [72; 74) 'a1': A
648 [72; 76) 'a1.b': B
649 [86; 88) 'a2': &A
650 [91; 93) '&a': &A
651 [92; 93) 'a': A
652 [99; 101) 'a2': &A
653 [99; 103) 'a2.b': B
654 [113; 115) 'a3': &mut A
655 [118; 124) '&mut a': &mut A
656 [123; 124) 'a': A
657 [130; 132) 'a3': &mut A
658 [130; 134) 'a3.b': B
659 [144; 146) 'a4': &&&&&&&A
660 [149; 157) '&&&&&&&a': &&&&&&&A
661 [150; 157) '&&&&&&a': &&&&&&A
662 [151; 157) '&&&&&a': &&&&&A
663 [152; 157) '&&&&a': &&&&A
664 [153; 157) '&&&a': &&&A
665 [154; 157) '&&a': &&A
666 [155; 157) '&a': &A
667 [156; 157) 'a': A
668 [163; 165) 'a4': &&&&&&&A
669 [163; 167) 'a4.b': B
670 [177; 179) 'a5': &mut &&mut &&mut A
671 [182; 200) '&mut &...&mut a': &mut &&mut &&mut A
672 [187; 200) '&&mut &&mut a': &&mut &&mut A
673 [188; 200) '&mut &&mut a': &mut &&mut A
674 [193; 200) '&&mut a': &&mut A
675 [194; 200) '&mut a': &mut A
676 [199; 200) 'a': A
677 [206; 208) 'a5': &mut &&mut &&mut A
678 [206; 210) 'a5.b': B
679 [224; 226) 'a1': *const A
680 [238; 240) 'a2': *mut A
681 [250; 273) '{ ...2.b; }': ()
682 [256; 258) 'a1': *const A
683 [256; 260) 'a1.b': B
684 [266; 268) 'a2': *mut A
685 [266; 270) 'a2.b': B
686 "###
687 );
688}
689
690#[test]
691fn infer_argument_autoderef() {
692 assert_snapshot!(
693 infer(r#"
694#[lang = "deref"]
695pub trait Deref {
696 type Target;
697 fn deref(&self) -> &Self::Target;
698}
699
700struct A<T>(T);
701
702impl<T> A<T> {
703 fn foo(&self) -> &T {
704 &self.0
705 }
706}
707
708struct B<T>(T);
709
710impl<T> Deref for B<T> {
711 type Target = T;
712 fn deref(&self) -> &Self::Target {
713 &self.0
714 }
715}
716
717fn test() {
718 let t = A::foo(&&B(B(A(42))));
719}
720"#),
721 @r###"
722 [68; 72) 'self': &Self
723 [139; 143) 'self': &A<T>
724 [151; 174) '{ ... }': &T
725 [161; 168) '&self.0': &T
726 [162; 166) 'self': &A<T>
727 [162; 168) 'self.0': T
728 [255; 259) 'self': &B<T>
729 [278; 301) '{ ... }': &T
730 [288; 295) '&self.0': &T
731 [289; 293) 'self': &B<T>
732 [289; 295) 'self.0': T
733 [315; 353) '{ ...))); }': ()
734 [325; 326) 't': &i32
735 [329; 335) 'A::foo': fn foo<i32>(&A<T>) -> &T
736 [329; 350) 'A::foo...42))))': &i32
737 [336; 349) '&&B(B(A(42)))': &&B<B<A<i32>>>
738 [337; 349) '&B(B(A(42)))': &B<B<A<i32>>>
739 [338; 339) 'B': B<B<A<i32>>>(T) -> B<T>
740 [338; 349) 'B(B(A(42)))': B<B<A<i32>>>
741 [340; 341) 'B': B<A<i32>>(T) -> B<T>
742 [340; 348) 'B(A(42))': B<A<i32>>
743 [342; 343) 'A': A<i32>(T) -> A<T>
744 [342; 347) 'A(42)': A<i32>
745 [344; 346) '42': i32
746 "###
747 );
748}
749
750#[test]
751fn infer_method_argument_autoderef() {
752 assert_snapshot!(
753 infer(r#"
754#[lang = "deref"]
755pub trait Deref {
756 type Target;
757 fn deref(&self) -> &Self::Target;
758}
759
760struct A<T>(*mut T);
761
762impl<T> A<T> {
763 fn foo(&self, x: &A<T>) -> &T {
764 &*x.0
765 }
766}
767
768struct B<T>(T);
769
770impl<T> Deref for B<T> {
771 type Target = T;
772 fn deref(&self) -> &Self::Target {
773 &self.0
774 }
775}
776
777fn test(a: A<i32>) {
778 let t = A(0 as *mut _).foo(&&B(B(a)));
779}
780"#),
781 @r###"
782 [68; 72) 'self': &Self
783 [144; 148) 'self': &A<T>
784 [150; 151) 'x': &A<T>
785 [166; 187) '{ ... }': &T
786 [176; 181) '&*x.0': &T
787 [177; 181) '*x.0': T
788 [178; 179) 'x': &A<T>
789 [178; 181) 'x.0': *mut T
790 [268; 272) 'self': &B<T>
791 [291; 314) '{ ... }': &T
792 [301; 308) '&self.0': &T
793 [302; 306) 'self': &B<T>
794 [302; 308) 'self.0': T
795 [326; 327) 'a': A<i32>
796 [337; 383) '{ ...))); }': ()
797 [347; 348) 't': &i32
798 [351; 352) 'A': A<i32>(*mut T) -> A<T>
799 [351; 365) 'A(0 as *mut _)': A<i32>
800 [351; 380) 'A(0 as...B(a)))': &i32
801 [353; 354) '0': i32
802 [353; 364) '0 as *mut _': *mut i32
803 [370; 379) '&&B(B(a))': &&B<B<A<i32>>>
804 [371; 379) '&B(B(a))': &B<B<A<i32>>>
805 [372; 373) 'B': B<B<A<i32>>>(T) -> B<T>
806 [372; 379) 'B(B(a))': B<B<A<i32>>>
807 [374; 375) 'B': B<A<i32>>(T) -> B<T>
808 [374; 378) 'B(a)': B<A<i32>>
809 [376; 377) 'a': A<i32>
810 "###
811 );
812}
813
814#[test]
815fn infer_in_elseif() {
816 assert_snapshot!(
817 infer(r#"
818struct Foo { field: i32 }
819fn main(foo: Foo) {
820 if true {
821
822 } else if false {
823 foo.field
824 }
825}
826"#),
827 @r###"
828 [35; 38) 'foo': Foo
829 [45; 109) '{ ... } }': ()
830 [51; 107) 'if tru... }': ()
831 [54; 58) 'true': bool
832 [59; 67) '{ }': ()
833 [73; 107) 'if fal... }': ()
834 [76; 81) 'false': bool
835 [82; 107) '{ ... }': i32
836 [92; 95) 'foo': Foo
837 [92; 101) 'foo.field': i32
838 "###
839 )
840}
841
842#[test]
843fn infer_if_match_with_return() {
844 assert_snapshot!(
845 infer(r#"
846fn foo() {
847 let _x1 = if true {
848 1
849 } else {
850 return;
851 };
852 let _x2 = if true {
853 2
854 } else {
855 return
856 };
857 let _x3 = match true {
858 true => 3,
859 _ => {
860 return;
861 }
862 };
863 let _x4 = match true {
864 true => 4,
865 _ => return
866 };
867}"#),
868 @r###"
869 [10; 323) '{ ... }; }': ()
870 [20; 23) '_x1': i32
871 [26; 80) 'if tru... }': i32
872 [29; 33) 'true': bool
873 [34; 51) '{ ... }': i32
874 [44; 45) '1': i32
875 [57; 80) '{ ... }': !
876 [67; 73) 'return': !
877 [90; 93) '_x2': i32
878 [96; 149) 'if tru... }': i32
879 [99; 103) 'true': bool
880 [104; 121) '{ ... }': i32
881 [114; 115) '2': i32
882 [127; 149) '{ ... }': !
883 [137; 143) 'return': !
884 [159; 162) '_x3': i32
885 [165; 247) 'match ... }': i32
886 [171; 175) 'true': bool
887 [186; 190) 'true': bool
888 [194; 195) '3': i32
889 [205; 206) '_': bool
890 [210; 241) '{ ... }': !
891 [224; 230) 'return': !
892 [257; 260) '_x4': i32
893 [263; 320) 'match ... }': i32
894 [269; 273) 'true': bool
895 [284; 288) 'true': bool
896 [292; 293) '4': i32
897 [303; 304) '_': bool
898 [308; 314) 'return': !
899 "###
900 )
901}
902
903#[test]
904fn infer_inherent_method() {
905 assert_snapshot!(
906 infer(r#"
907struct A;
908
909impl A {
910 fn foo(self, x: u32) -> i32 {}
911}
912
913mod b {
914 impl super::A {
915 fn bar(&self, x: u64) -> i64 {}
916 }
917}
918
919fn test(a: A) {
920 a.foo(1);
921 (&a).bar(1);
922 a.bar(1);
923}
924"#),
925 @r###"
926 [32; 36) 'self': A
927 [38; 39) 'x': u32
928 [53; 55) '{}': ()
929 [103; 107) 'self': &A
930 [109; 110) 'x': u64
931 [124; 126) '{}': ()
932 [144; 145) 'a': A
933 [150; 198) '{ ...(1); }': ()
934 [156; 157) 'a': A
935 [156; 164) 'a.foo(1)': i32
936 [162; 163) '1': u32
937 [170; 181) '(&a).bar(1)': i64
938 [171; 173) '&a': &A
939 [172; 173) 'a': A
940 [179; 180) '1': u64
941 [187; 188) 'a': A
942 [187; 195) 'a.bar(1)': i64
943 [193; 194) '1': u64
944 "###
945 );
946}
947
948#[test]
949fn infer_inherent_method_str() {
950 assert_snapshot!(
951 infer(r#"
952#[lang = "str"]
953impl str {
954 fn foo(&self) -> i32 {}
955}
956
957fn test() {
958 "foo".foo();
959}
960"#),
961 @r###"
962 [40; 44) 'self': &str
963 [53; 55) '{}': ()
964 [69; 89) '{ ...o(); }': ()
965 [75; 80) '"foo"': &str
966 [75; 86) '"foo".foo()': i32
967 "###
968 );
969}
970
971#[test]
972fn infer_tuple() {
973 assert_snapshot!(
974 infer(r#"
975fn test(x: &str, y: isize) {
976 let a: (u32, &str) = (1, "a");
977 let b = (a, x);
978 let c = (y, x);
979 let d = (c, x);
980 let e = (1, "e");
981 let f = (e, "d");
982}
983"#),
984 @r###"
985 [9; 10) 'x': &str
986 [18; 19) 'y': isize
987 [28; 170) '{ ...d"); }': ()
988 [38; 39) 'a': (u32, &str)
989 [55; 63) '(1, "a")': (u32, &str)
990 [56; 57) '1': u32
991 [59; 62) '"a"': &str
992 [73; 74) 'b': ((u32, &str), &str)
993 [77; 83) '(a, x)': ((u32, &str), &str)
994 [78; 79) 'a': (u32, &str)
995 [81; 82) 'x': &str
996 [93; 94) 'c': (isize, &str)
997 [97; 103) '(y, x)': (isize, &str)
998 [98; 99) 'y': isize
999 [101; 102) 'x': &str
1000 [113; 114) 'd': ((isize, &str), &str)
1001 [117; 123) '(c, x)': ((isize, &str), &str)
1002 [118; 119) 'c': (isize, &str)
1003 [121; 122) 'x': &str
1004 [133; 134) 'e': (i32, &str)
1005 [137; 145) '(1, "e")': (i32, &str)
1006 [138; 139) '1': i32
1007 [141; 144) '"e"': &str
1008 [155; 156) 'f': ((i32, &str), &str)
1009 [159; 167) '(e, "d")': ((i32, &str), &str)
1010 [160; 161) 'e': (i32, &str)
1011 [163; 166) '"d"': &str
1012 "###
1013 );
1014}
1015
1016#[test]
1017fn infer_array() {
1018 assert_snapshot!(
1019 infer(r#"
1020fn test(x: &str, y: isize) {
1021 let a = [x];
1022 let b = [a, a];
1023 let c = [b, b];
1024
1025 let d = [y, 1, 2, 3];
1026 let d = [1, y, 2, 3];
1027 let e = [y];
1028 let f = [d, d];
1029 let g = [e, e];
1030
1031 let h = [1, 2];
1032 let i = ["a", "b"];
1033
1034 let b = [a, ["b"]];
1035 let x: [u8; 0] = [];
1036}
1037"#),
1038 @r###"
1039 [9; 10) 'x': &str
1040 [18; 19) 'y': isize
1041 [28; 293) '{ ... []; }': ()
1042 [38; 39) 'a': [&str;_]
1043 [42; 45) '[x]': [&str;_]
1044 [43; 44) 'x': &str
1045 [55; 56) 'b': [[&str;_];_]
1046 [59; 65) '[a, a]': [[&str;_];_]
1047 [60; 61) 'a': [&str;_]
1048 [63; 64) 'a': [&str;_]
1049 [75; 76) 'c': [[[&str;_];_];_]
1050 [79; 85) '[b, b]': [[[&str;_];_];_]
1051 [80; 81) 'b': [[&str;_];_]
1052 [83; 84) 'b': [[&str;_];_]
1053 [96; 97) 'd': [isize;_]
1054 [100; 112) '[y, 1, 2, 3]': [isize;_]
1055 [101; 102) 'y': isize
1056 [104; 105) '1': isize
1057 [107; 108) '2': isize
1058 [110; 111) '3': isize
1059 [122; 123) 'd': [isize;_]
1060 [126; 138) '[1, y, 2, 3]': [isize;_]
1061 [127; 128) '1': isize
1062 [130; 131) 'y': isize
1063 [133; 134) '2': isize
1064 [136; 137) '3': isize
1065 [148; 149) 'e': [isize;_]
1066 [152; 155) '[y]': [isize;_]
1067 [153; 154) 'y': isize
1068 [165; 166) 'f': [[isize;_];_]
1069 [169; 175) '[d, d]': [[isize;_];_]
1070 [170; 171) 'd': [isize;_]
1071 [173; 174) 'd': [isize;_]
1072 [185; 186) 'g': [[isize;_];_]
1073 [189; 195) '[e, e]': [[isize;_];_]
1074 [190; 191) 'e': [isize;_]
1075 [193; 194) 'e': [isize;_]
1076 [206; 207) 'h': [i32;_]
1077 [210; 216) '[1, 2]': [i32;_]
1078 [211; 212) '1': i32
1079 [214; 215) '2': i32
1080 [226; 227) 'i': [&str;_]
1081 [230; 240) '["a", "b"]': [&str;_]
1082 [231; 234) '"a"': &str
1083 [236; 239) '"b"': &str
1084 [251; 252) 'b': [[&str;_];_]
1085 [255; 265) '[a, ["b"]]': [[&str;_];_]
1086 [256; 257) 'a': [&str;_]
1087 [259; 264) '["b"]': [&str;_]
1088 [260; 263) '"b"': &str
1089 [275; 276) 'x': [u8;_]
1090 [288; 290) '[]': [u8;_]
1091 "###
1092 );
1093}
1094
1095#[test]
1096fn infer_struct_generics() {
1097 assert_snapshot!(
1098 infer(r#"
1099struct A<T> {
1100 x: T,
1101}
1102
1103fn test(a1: A<u32>, i: i32) {
1104 a1.x;
1105 let a2 = A { x: i };
1106 a2.x;
1107 let a3 = A::<i128> { x: 1 };
1108 a3.x;
1109}
1110"#),
1111 @r###"
1112 [36; 38) 'a1': A<u32>
1113 [48; 49) 'i': i32
1114 [56; 147) '{ ...3.x; }': ()
1115 [62; 64) 'a1': A<u32>
1116 [62; 66) 'a1.x': u32
1117 [76; 78) 'a2': A<i32>
1118 [81; 91) 'A { x: i }': A<i32>
1119 [88; 89) 'i': i32
1120 [97; 99) 'a2': A<i32>
1121 [97; 101) 'a2.x': i32
1122 [111; 113) 'a3': A<i128>
1123 [116; 134) 'A::<i1...x: 1 }': A<i128>
1124 [131; 132) '1': i128
1125 [140; 142) 'a3': A<i128>
1126 [140; 144) 'a3.x': i128
1127 "###
1128 );
1129}
1130
1131#[test]
1132fn infer_tuple_struct_generics() {
1133 assert_snapshot!(
1134 infer(r#"
1135struct A<T>(T);
1136enum Option<T> { Some(T), None }
1137use Option::*;
1138
1139fn test() {
1140 A(42);
1141 A(42u128);
1142 Some("x");
1143 Option::Some("x");
1144 None;
1145 let x: Option<i64> = None;
1146}
1147"#),
1148 @r###"
1149 [76; 184) '{ ...one; }': ()
1150 [82; 83) 'A': A<i32>(T) -> A<T>
1151 [82; 87) 'A(42)': A<i32>
1152 [84; 86) '42': i32
1153 [93; 94) 'A': A<u128>(T) -> A<T>
1154 [93; 102) 'A(42u128)': A<u128>
1155 [95; 101) '42u128': u128
1156 [108; 112) 'Some': Some<&str>(T) -> Option<T>
1157 [108; 117) 'Some("x")': Option<&str>
1158 [113; 116) '"x"': &str
1159 [123; 135) 'Option::Some': Some<&str>(T) -> Option<T>
1160 [123; 140) 'Option...e("x")': Option<&str>
1161 [136; 139) '"x"': &str
1162 [146; 150) 'None': Option<{unknown}>
1163 [160; 161) 'x': Option<i64>
1164 [177; 181) 'None': Option<i64>
1165 "###
1166 );
1167}
1168
1169#[test]
1170fn infer_function_generics() {
1171 assert_snapshot!(
1172 infer(r#"
1173fn id<T>(t: T) -> T { t }
1174
1175fn test() {
1176 id(1u32);
1177 id::<i128>(1);
1178 let x: u64 = id(1);
1179}
1180"#),
1181 @r###"
1182 [10; 11) 't': T
1183 [21; 26) '{ t }': T
1184 [23; 24) 't': T
1185 [38; 98) '{ ...(1); }': ()
1186 [44; 46) 'id': fn id<u32>(T) -> T
1187 [44; 52) 'id(1u32)': u32
1188 [47; 51) '1u32': u32
1189 [58; 68) 'id::<i128>': fn id<i128>(T) -> T
1190 [58; 71) 'id::<i128>(1)': i128
1191 [69; 70) '1': i128
1192 [81; 82) 'x': u64
1193 [90; 92) 'id': fn id<u64>(T) -> T
1194 [90; 95) 'id(1)': u64
1195 [93; 94) '1': u64
1196 "###
1197 );
1198}
1199
1200#[test]
1201fn infer_impl_generics() {
1202 assert_snapshot!(
1203 infer(r#"
1204struct A<T1, T2> {
1205 x: T1,
1206 y: T2,
1207}
1208impl<Y, X> A<X, Y> {
1209 fn x(self) -> X {
1210 self.x
1211 }
1212 fn y(self) -> Y {
1213 self.y
1214 }
1215 fn z<T>(self, t: T) -> (X, Y, T) {
1216 (self.x, self.y, t)
1217 }
1218}
1219
1220fn test() -> i128 {
1221 let a = A { x: 1u64, y: 1i64 };
1222 a.x();
1223 a.y();
1224 a.z(1i128);
1225 a.z::<u128>(1);
1226}
1227"#),
1228 @r###"
1229 [74; 78) 'self': A<X, Y>
1230 [85; 107) '{ ... }': X
1231 [95; 99) 'self': A<X, Y>
1232 [95; 101) 'self.x': X
1233 [117; 121) 'self': A<X, Y>
1234 [128; 150) '{ ... }': Y
1235 [138; 142) 'self': A<X, Y>
1236 [138; 144) 'self.y': Y
1237 [163; 167) 'self': A<X, Y>
1238 [169; 170) 't': T
1239 [188; 223) '{ ... }': (X, Y, T)
1240 [198; 217) '(self.....y, t)': (X, Y, T)
1241 [199; 203) 'self': A<X, Y>
1242 [199; 205) 'self.x': X
1243 [207; 211) 'self': A<X, Y>
1244 [207; 213) 'self.y': Y
1245 [215; 216) 't': T
1246 [245; 342) '{ ...(1); }': ()
1247 [255; 256) 'a': A<u64, i64>
1248 [259; 281) 'A { x:...1i64 }': A<u64, i64>
1249 [266; 270) '1u64': u64
1250 [275; 279) '1i64': i64
1251 [287; 288) 'a': A<u64, i64>
1252 [287; 292) 'a.x()': u64
1253 [298; 299) 'a': A<u64, i64>
1254 [298; 303) 'a.y()': i64
1255 [309; 310) 'a': A<u64, i64>
1256 [309; 319) 'a.z(1i128)': (u64, i64, i128)
1257 [313; 318) '1i128': i128
1258 [325; 326) 'a': A<u64, i64>
1259 [325; 339) 'a.z::<u128>(1)': (u64, i64, u128)
1260 [337; 338) '1': u128
1261 "###
1262 );
1263}
1264
1265#[test]
1266fn infer_impl_generics_with_autoderef() {
1267 assert_snapshot!(
1268 infer(r#"
1269enum Option<T> {
1270 Some(T),
1271 None,
1272}
1273impl<T> Option<T> {
1274 fn as_ref(&self) -> Option<&T> {}
1275}
1276fn test(o: Option<u32>) {
1277 (&o).as_ref();
1278 o.as_ref();
1279}
1280"#),
1281 @r###"
1282 [78; 82) 'self': &Option<T>
1283 [98; 100) '{}': ()
1284 [111; 112) 'o': Option<u32>
1285 [127; 165) '{ ...f(); }': ()
1286 [133; 146) '(&o).as_ref()': Option<&u32>
1287 [134; 136) '&o': &Option<u32>
1288 [135; 136) 'o': Option<u32>
1289 [152; 153) 'o': Option<u32>
1290 [152; 162) 'o.as_ref()': Option<&u32>
1291 "###
1292 );
1293}
1294
1295#[test]
1296fn infer_generic_chain() {
1297 assert_snapshot!(
1298 infer(r#"
1299struct A<T> {
1300 x: T,
1301}
1302impl<T2> A<T2> {
1303 fn x(self) -> T2 {
1304 self.x
1305 }
1306}
1307fn id<T>(t: T) -> T { t }
1308
1309fn test() -> i128 {
1310 let x = 1;
1311 let y = id(x);
1312 let a = A { x: id(y) };
1313 let z = id(a.x);
1314 let b = A { x: z };
1315 b.x()
1316}
1317"#),
1318 @r###"
1319 [53; 57) 'self': A<T2>
1320 [65; 87) '{ ... }': T2
1321 [75; 79) 'self': A<T2>
1322 [75; 81) 'self.x': T2
1323 [99; 100) 't': T
1324 [110; 115) '{ t }': T
1325 [112; 113) 't': T
1326 [135; 261) '{ ....x() }': i128
1327 [146; 147) 'x': i128
1328 [150; 151) '1': i128
1329 [162; 163) 'y': i128
1330 [166; 168) 'id': fn id<i128>(T) -> T
1331 [166; 171) 'id(x)': i128
1332 [169; 170) 'x': i128
1333 [182; 183) 'a': A<i128>
1334 [186; 200) 'A { x: id(y) }': A<i128>
1335 [193; 195) 'id': fn id<i128>(T) -> T
1336 [193; 198) 'id(y)': i128
1337 [196; 197) 'y': i128
1338 [211; 212) 'z': i128
1339 [215; 217) 'id': fn id<i128>(T) -> T
1340 [215; 222) 'id(a.x)': i128
1341 [218; 219) 'a': A<i128>
1342 [218; 221) 'a.x': i128
1343 [233; 234) 'b': A<i128>
1344 [237; 247) 'A { x: z }': A<i128>
1345 [244; 245) 'z': i128
1346 [254; 255) 'b': A<i128>
1347 [254; 259) 'b.x()': i128
1348 "###
1349 );
1350}
1351
1352#[test]
1353fn infer_associated_const() {
1354 assert_snapshot!(
1355 infer(r#"
1356struct Struct;
1357
1358impl Struct {
1359 const FOO: u32 = 1;
1360}
1361
1362enum Enum {}
1363
1364impl Enum {
1365 const BAR: u32 = 2;
1366}
1367
1368trait Trait {
1369 const ID: u32;
1370}
1371
1372struct TraitTest;
1373
1374impl Trait for TraitTest {
1375 const ID: u32 = 5;
1376}
1377
1378fn test() {
1379 let x = Struct::FOO;
1380 let y = Enum::BAR;
1381 let z = TraitTest::ID;
1382}
1383"#),
1384 @r###"
1385 [52; 53) '1': u32
1386 [105; 106) '2': u32
1387 [213; 214) '5': u32
1388 [229; 307) '{ ...:ID; }': ()
1389 [239; 240) 'x': u32
1390 [243; 254) 'Struct::FOO': u32
1391 [264; 265) 'y': u32
1392 [268; 277) 'Enum::BAR': u32
1393 [287; 288) 'z': u32
1394 [291; 304) 'TraitTest::ID': u32
1395 "###
1396 );
1397}
1398
1399#[test]
1400fn infer_type_alias() {
1401 assert_snapshot!(
1402 infer(r#"
1403struct A<X, Y> { x: X, y: Y }
1404type Foo = A<u32, i128>;
1405type Bar<T> = A<T, u128>;
1406type Baz<U, V> = A<V, U>;
1407fn test(x: Foo, y: Bar<&str>, z: Baz<i8, u8>) {
1408 x.x;
1409 x.y;
1410 y.x;
1411 y.y;
1412 z.x;
1413 z.y;
1414}
1415"#),
1416 @r###"
1417 [116; 117) 'x': A<u32, i128>
1418 [124; 125) 'y': A<&str, u128>
1419 [138; 139) 'z': A<u8, i8>
1420 [154; 211) '{ ...z.y; }': ()
1421 [160; 161) 'x': A<u32, i128>
1422 [160; 163) 'x.x': u32
1423 [169; 170) 'x': A<u32, i128>
1424 [169; 172) 'x.y': i128
1425 [178; 179) 'y': A<&str, u128>
1426 [178; 181) 'y.x': &str
1427 [187; 188) 'y': A<&str, u128>
1428 [187; 190) 'y.y': u128
1429 [196; 197) 'z': A<u8, i8>
1430 [196; 199) 'z.x': u8
1431 [205; 206) 'z': A<u8, i8>
1432 [205; 208) 'z.y': i8
1433 "###
1434 )
1435}
1436
1437#[test]
1438fn recursive_type_alias() {
1439 assert_snapshot!(
1440 infer(r#"
1441struct A<X> {}
1442type Foo = Foo;
1443type Bar = A<Bar>;
1444fn test(x: Foo) {}
1445"#),
1446 @r###"
1447 [59; 60) 'x': {unknown}
1448 [67; 69) '{}': ()
1449 "###
1450 )
1451}
1452
1453#[test]
1454fn infer_type_param() {
1455 assert_snapshot!(
1456 infer(r#"
1457fn id<T>(x: T) -> T {
1458 x
1459}
1460
1461fn clone<T>(x: &T) -> T {
1462 *x
1463}
1464
1465fn test() {
1466 let y = 10u32;
1467 id(y);
1468 let x: bool = clone(z);
1469 id::<i128>(1);
1470}
1471"#),
1472 @r###"
1473 [10; 11) 'x': T
1474 [21; 30) '{ x }': T
1475 [27; 28) 'x': T
1476 [44; 45) 'x': &T
1477 [56; 66) '{ *x }': T
1478 [62; 64) '*x': T
1479 [63; 64) 'x': &T
1480 [78; 158) '{ ...(1); }': ()
1481 [88; 89) 'y': u32
1482 [92; 97) '10u32': u32
1483 [103; 105) 'id': fn id<u32>(T) -> T
1484 [103; 108) 'id(y)': u32
1485 [106; 107) 'y': u32
1486 [118; 119) 'x': bool
1487 [128; 133) 'clone': fn clone<bool>(&T) -> T
1488 [128; 136) 'clone(z)': bool
1489 [134; 135) 'z': &bool
1490 [142; 152) 'id::<i128>': fn id<i128>(T) -> T
1491 [142; 155) 'id::<i128>(1)': i128
1492 [153; 154) '1': i128
1493 "###
1494 );
1495}
1496
1497#[test]
1498fn infer_const() {
1499 assert_snapshot!(
1500 infer(r#"
1501struct Foo;
1502impl Foo { const ASSOC_CONST: u32 = 0; }
1503const GLOBAL_CONST: u32 = 101;
1504fn test() {
1505 const LOCAL_CONST: u32 = 99;
1506 let x = LOCAL_CONST;
1507 let z = GLOBAL_CONST;
1508 let id = Foo::ASSOC_CONST;
1509}
1510"#),
1511 @r###"
1512 [49; 50) '0': u32
1513 [80; 83) '101': u32
1514 [95; 213) '{ ...NST; }': ()
1515 [138; 139) 'x': u32
1516 [142; 153) 'LOCAL_CONST': u32
1517 [163; 164) 'z': u32
1518 [167; 179) 'GLOBAL_CONST': u32
1519 [189; 191) 'id': u32
1520 [194; 210) 'Foo::A..._CONST': u32
1521 "###
1522 );
1523}
1524
1525#[test]
1526fn infer_static() {
1527 assert_snapshot!(
1528 infer(r#"
1529static GLOBAL_STATIC: u32 = 101;
1530static mut GLOBAL_STATIC_MUT: u32 = 101;
1531fn test() {
1532 static LOCAL_STATIC: u32 = 99;
1533 static mut LOCAL_STATIC_MUT: u32 = 99;
1534 let x = LOCAL_STATIC;
1535 let y = LOCAL_STATIC_MUT;
1536 let z = GLOBAL_STATIC;
1537 let w = GLOBAL_STATIC_MUT;
1538}
1539"#),
1540 @r###"
1541 [29; 32) '101': u32
1542 [70; 73) '101': u32
1543 [85; 280) '{ ...MUT; }': ()
1544 [173; 174) 'x': u32
1545 [177; 189) 'LOCAL_STATIC': u32
1546 [199; 200) 'y': u32
1547 [203; 219) 'LOCAL_...IC_MUT': u32
1548 [229; 230) 'z': u32
1549 [233; 246) 'GLOBAL_STATIC': u32
1550 [256; 257) 'w': u32
1551 [260; 277) 'GLOBAL...IC_MUT': u32
1552 "###
1553 );
1554}
1555
1556#[test]
1557fn shadowing_primitive() {
1558 let t = type_at(
1559 r#"
1560//- /main.rs
1561struct i32;
1562struct Foo;
1563
1564impl i32 { fn foo(&self) -> Foo { Foo } }
1565
1566fn main() {
1567 let x: i32 = i32;
1568 x.foo()<|>;
1569}"#,
1570 );
1571 assert_eq!(t, "Foo");
1572}
1573
1574#[test]
1575fn not_shadowing_primitive_by_module() {
1576 let t = type_at(
1577 r#"
1578//- /str.rs
1579fn foo() {}
1580
1581//- /main.rs
1582mod str;
1583fn foo() -> &'static str { "" }
1584
1585fn main() {
1586 foo()<|>;
1587}"#,
1588 );
1589 assert_eq!(t, "&str");
1590}
1591
1592#[test]
1593fn not_shadowing_module_by_primitive() {
1594 let t = type_at(
1595 r#"
1596//- /str.rs
1597fn foo() -> u32 {0}
1598
1599//- /main.rs
1600mod str;
1601fn foo() -> &'static str { "" }
1602
1603fn main() {
1604 str::foo()<|>;
1605}"#,
1606 );
1607 assert_eq!(t, "u32");
1608}
1609
1610#[test]
1611fn closure_return() {
1612 assert_snapshot!(
1613 infer(r#"
1614fn foo() -> u32 {
1615 let x = || -> usize { return 1; };
1616}
1617"#),
1618 @r###"
1619 [17; 59) '{ ...; }; }': ()
1620 [27; 28) 'x': || -> usize
1621 [31; 56) '|| -> ...n 1; }': || -> usize
1622 [43; 56) '{ return 1; }': !
1623 [45; 53) 'return 1': !
1624 [52; 53) '1': usize
1625 "###
1626 );
1627}
1628
1629#[test]
1630fn closure_return_unit() {
1631 assert_snapshot!(
1632 infer(r#"
1633fn foo() -> u32 {
1634 let x = || { return; };
1635}
1636"#),
1637 @r###"
1638 [17; 48) '{ ...; }; }': ()
1639 [27; 28) 'x': || -> ()
1640 [31; 45) '|| { return; }': || -> ()
1641 [34; 45) '{ return; }': !
1642 [36; 42) 'return': !
1643 "###
1644 );
1645}
1646
1647#[test]
1648fn closure_return_inferred() {
1649 assert_snapshot!(
1650 infer(r#"
1651fn foo() -> u32 {
1652 let x = || { "test" };
1653}
1654"#),
1655 @r###"
1656 [17; 47) '{ ..." }; }': ()
1657 [27; 28) 'x': || -> &str
1658 [31; 44) '|| { "test" }': || -> &str
1659 [34; 44) '{ "test" }': &str
1660 [36; 42) '"test"': &str
1661 "###
1662 );
1663}
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
new file mode 100644
index 000000000..ae316922b
--- /dev/null
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -0,0 +1,1598 @@
1use insta::assert_snapshot;
2
3use ra_db::fixture::WithFixture;
4use test_utils::covers;
5
6use super::{infer, infer_with_mismatches, type_at, type_at_pos};
7use crate::test_db::TestDB;
8
9#[test]
10fn infer_await() {
11 let (db, pos) = TestDB::with_position(
12 r#"
13//- /main.rs crate:main deps:std
14
15struct IntFuture;
16
17impl Future for IntFuture {
18 type Output = u64;
19}
20
21fn test() {
22 let r = IntFuture;
23 let v = r.await;
24 v<|>;
25}
26
27//- /std.rs crate:std
28#[prelude_import] use future::*;
29mod future {
30 trait Future {
31 type Output;
32 }
33}
34
35"#,
36 );
37 assert_eq!("u64", type_at_pos(&db, pos));
38}
39
40#[test]
41fn infer_try() {
42 let (db, pos) = TestDB::with_position(
43 r#"
44//- /main.rs crate:main deps:std
45
46fn test() {
47 let r: Result<i32, u64> = Result::Ok(1);
48 let v = r?;
49 v<|>;
50}
51
52//- /std.rs crate:std
53
54#[prelude_import] use ops::*;
55mod ops {
56 trait Try {
57 type Ok;
58 type Error;
59 }
60}
61
62#[prelude_import] use result::*;
63mod result {
64 enum Result<O, E> {
65 Ok(O),
66 Err(E)
67 }
68
69 impl<O, E> crate::ops::Try for Result<O, E> {
70 type Ok = O;
71 type Error = E;
72 }
73}
74
75"#,
76 );
77 assert_eq!("i32", type_at_pos(&db, pos));
78}
79
80#[test]
81fn infer_for_loop() {
82 let (db, pos) = TestDB::with_position(
83 r#"
84//- /main.rs crate:main deps:std
85
86use std::collections::Vec;
87
88fn test() {
89 let v = Vec::new();
90 v.push("foo");
91 for x in v {
92 x<|>;
93 }
94}
95
96//- /std.rs crate:std
97
98#[prelude_import] use iter::*;
99mod iter {
100 trait IntoIterator {
101 type Item;
102 }
103}
104
105mod collections {
106 struct Vec<T> {}
107 impl<T> Vec<T> {
108 fn new() -> Self { Vec {} }
109 fn push(&mut self, t: T) { }
110 }
111
112 impl<T> crate::iter::IntoIterator for Vec<T> {
113 type Item=T;
114 }
115}
116"#,
117 );
118 assert_eq!("&str", type_at_pos(&db, pos));
119}
120
121#[test]
122fn infer_ops_neg() {
123 let (db, pos) = TestDB::with_position(
124 r#"
125//- /main.rs crate:main deps:std
126
127struct Bar;
128struct Foo;
129
130impl std::ops::Neg for Bar {
131 type Output = Foo;
132}
133
134fn test() {
135 let a = Bar;
136 let b = -a;
137 b<|>;
138}
139
140//- /std.rs crate:std
141
142#[prelude_import] use ops::*;
143mod ops {
144 pub trait Neg {
145 type Output;
146 }
147}
148"#,
149 );
150 assert_eq!("Foo", type_at_pos(&db, pos));
151}
152
153#[test]
154fn infer_ops_not() {
155 let (db, pos) = TestDB::with_position(
156 r#"
157//- /main.rs crate:main deps:std
158
159struct Bar;
160struct Foo;
161
162impl std::ops::Not for Bar {
163 type Output = Foo;
164}
165
166fn test() {
167 let a = Bar;
168 let b = !a;
169 b<|>;
170}
171
172//- /std.rs crate:std
173
174#[prelude_import] use ops::*;
175mod ops {
176 pub trait Not {
177 type Output;
178 }
179}
180"#,
181 );
182 assert_eq!("Foo", type_at_pos(&db, pos));
183}
184
185#[test]
186fn infer_from_bound_1() {
187 assert_snapshot!(
188 infer(r#"
189trait Trait<T> {}
190struct S<T>(T);
191impl<U> Trait<U> for S<U> {}
192fn foo<T: Trait<u32>>(t: T) {}
193fn test() {
194 let s = S(unknown);
195 foo(s);
196}
197"#),
198 @r###"
199 [86; 87) 't': T
200 [92; 94) '{}': ()
201 [105; 144) '{ ...(s); }': ()
202 [115; 116) 's': S<u32>
203 [119; 120) 'S': S<u32>(T) -> S<T>
204 [119; 129) 'S(unknown)': S<u32>
205 [121; 128) 'unknown': u32
206 [135; 138) 'foo': fn foo<S<u32>>(T) -> ()
207 [135; 141) 'foo(s)': ()
208 [139; 140) 's': S<u32>
209 "###
210 );
211}
212
213#[test]
214fn infer_from_bound_2() {
215 assert_snapshot!(
216 infer(r#"
217trait Trait<T> {}
218struct S<T>(T);
219impl<U> Trait<U> for S<U> {}
220fn foo<U, T: Trait<U>>(t: T) -> U {}
221fn test() {
222 let s = S(unknown);
223 let x: u32 = foo(s);
224}
225"#),
226 @r###"
227 [87; 88) 't': T
228 [98; 100) '{}': ()
229 [111; 163) '{ ...(s); }': ()
230 [121; 122) 's': S<u32>
231 [125; 126) 'S': S<u32>(T) -> S<T>
232 [125; 135) 'S(unknown)': S<u32>
233 [127; 134) 'unknown': u32
234 [145; 146) 'x': u32
235 [154; 157) 'foo': fn foo<u32, S<u32>>(T) -> U
236 [154; 160) 'foo(s)': u32
237 [158; 159) 's': S<u32>
238 "###
239 );
240}
241
242#[test]
243fn infer_project_associated_type() {
244 // y, z, a don't yet work because of https://github.com/rust-lang/chalk/issues/234
245 assert_snapshot!(
246 infer(r#"
247trait Iterable {
248 type Item;
249}
250struct S;
251impl Iterable for S { type Item = u32; }
252fn test<T: Iterable>() {
253 let x: <S as Iterable>::Item = 1;
254 let y: <T as Iterable>::Item = no_matter;
255 let z: T::Item = no_matter;
256 let a: <T>::Item = no_matter;
257}
258"#),
259 @r###"
260 [108; 261) '{ ...ter; }': ()
261 [118; 119) 'x': u32
262 [145; 146) '1': u32
263 [156; 157) 'y': {unknown}
264 [183; 192) 'no_matter': {unknown}
265 [202; 203) 'z': {unknown}
266 [215; 224) 'no_matter': {unknown}
267 [234; 235) 'a': {unknown}
268 [249; 258) 'no_matter': {unknown}
269 "###
270 );
271}
272
273#[test]
274fn infer_return_associated_type() {
275 assert_snapshot!(
276 infer(r#"
277trait Iterable {
278 type Item;
279}
280struct S;
281impl Iterable for S { type Item = u32; }
282fn foo1<T: Iterable>(t: T) -> T::Item {}
283fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item {}
284fn foo3<T: Iterable>(t: T) -> <T>::Item {}
285fn test() {
286 let x = foo1(S);
287 let y = foo2(S);
288 let z = foo3(S);
289}
290"#),
291 @r###"
292 [106; 107) 't': T
293 [123; 125) '{}': ()
294 [147; 148) 't': T
295 [178; 180) '{}': ()
296 [202; 203) 't': T
297 [221; 223) '{}': ()
298 [234; 300) '{ ...(S); }': ()
299 [244; 245) 'x': u32
300 [248; 252) 'foo1': fn foo1<S>(T) -> <T as Iterable>::Item
301 [248; 255) 'foo1(S)': u32
302 [253; 254) 'S': S
303 [265; 266) 'y': u32
304 [269; 273) 'foo2': fn foo2<S>(T) -> <T as Iterable>::Item
305 [269; 276) 'foo2(S)': u32
306 [274; 275) 'S': S
307 [286; 287) 'z': u32
308 [290; 294) 'foo3': fn foo3<S>(T) -> <T as Iterable>::Item
309 [290; 297) 'foo3(S)': u32
310 [295; 296) 'S': S
311 "###
312 );
313}
314
315#[test]
316fn infer_associated_type_bound() {
317 assert_snapshot!(
318 infer(r#"
319trait Iterable {
320 type Item;
321}
322fn test<T: Iterable<Item=u32>>() {
323 let y: T::Item = unknown;
324}
325"#),
326 @r###"
327 [67; 100) '{ ...own; }': ()
328 [77; 78) 'y': {unknown}
329 [90; 97) 'unknown': {unknown}
330 "###
331 );
332}
333
334#[test]
335fn infer_const_body() {
336 assert_snapshot!(
337 infer(r#"
338const A: u32 = 1 + 1;
339static B: u64 = { let x = 1; x };
340"#),
341 @r###"
342 [16; 17) '1': u32
343 [16; 21) '1 + 1': u32
344 [20; 21) '1': u32
345 [39; 55) '{ let ...1; x }': u64
346 [45; 46) 'x': u64
347 [49; 50) '1': u64
348 [52; 53) 'x': u64
349 "###
350 );
351}
352
353#[test]
354fn tuple_struct_fields() {
355 assert_snapshot!(
356 infer(r#"
357struct S(i32, u64);
358fn test() -> u64 {
359 let a = S(4, 6);
360 let b = a.0;
361 a.1
362}
363"#),
364 @r###"
365 [38; 87) '{ ... a.1 }': u64
366 [48; 49) 'a': S
367 [52; 53) 'S': S(i32, u64) -> S
368 [52; 59) 'S(4, 6)': S
369 [54; 55) '4': i32
370 [57; 58) '6': u64
371 [69; 70) 'b': i32
372 [73; 74) 'a': S
373 [73; 76) 'a.0': i32
374 [82; 83) 'a': S
375 [82; 85) 'a.1': u64
376 "###
377 );
378}
379
380#[test]
381fn tuple_struct_with_fn() {
382 assert_snapshot!(
383 infer(r#"
384struct S(fn(u32) -> u64);
385fn test() -> u64 {
386 let a = S(|i| 2*i);
387 let b = a.0(4);
388 a.0(2)
389}
390"#),
391 @r###"
392 [44; 102) '{ ...0(2) }': u64
393 [54; 55) 'a': S
394 [58; 59) 'S': S(fn(u32) -> u64) -> S
395 [58; 68) 'S(|i| 2*i)': S
396 [60; 67) '|i| 2*i': |u32| -> u64
397 [61; 62) 'i': u32
398 [64; 65) '2': u32
399 [64; 67) '2*i': u32
400 [66; 67) 'i': u32
401 [78; 79) 'b': u64
402 [82; 83) 'a': S
403 [82; 85) 'a.0': fn(u32) -> u64
404 [82; 88) 'a.0(4)': u64
405 [86; 87) '4': u32
406 [94; 95) 'a': S
407 [94; 97) 'a.0': fn(u32) -> u64
408 [94; 100) 'a.0(2)': u64
409 [98; 99) '2': u32
410 "###
411 );
412}
413
414#[test]
415fn indexing_arrays() {
416 assert_snapshot!(
417 infer("fn main() { &mut [9][2]; }"),
418 @r###"
419 [10; 26) '{ &mut...[2]; }': ()
420 [12; 23) '&mut [9][2]': &mut {unknown}
421 [17; 20) '[9]': [i32;_]
422 [17; 23) '[9][2]': {unknown}
423 [18; 19) '9': i32
424 [21; 22) '2': i32
425 "###
426 )
427}
428
429#[test]
430fn infer_ops_index() {
431 let (db, pos) = TestDB::with_position(
432 r#"
433//- /main.rs crate:main deps:std
434
435struct Bar;
436struct Foo;
437
438impl std::ops::Index<u32> for Bar {
439 type Output = Foo;
440}
441
442fn test() {
443 let a = Bar;
444 let b = a[1];
445 b<|>;
446}
447
448//- /std.rs crate:std
449
450#[prelude_import] use ops::*;
451mod ops {
452 pub trait Index<Idx> {
453 type Output;
454 }
455}
456"#,
457 );
458 assert_eq!("Foo", type_at_pos(&db, pos));
459}
460
461#[test]
462fn deref_trait() {
463 let t = type_at(
464 r#"
465//- /main.rs
466#[lang = "deref"]
467trait Deref {
468 type Target;
469 fn deref(&self) -> &Self::Target;
470}
471
472struct Arc<T>;
473impl<T> Deref for Arc<T> {
474 type Target = T;
475}
476
477struct S;
478impl S {
479 fn foo(&self) -> u128 {}
480}
481
482fn test(s: Arc<S>) {
483 (*s, s.foo())<|>;
484}
485"#,
486 );
487 assert_eq!(t, "(S, u128)");
488}
489
490#[test]
491fn deref_trait_with_inference_var() {
492 let t = type_at(
493 r#"
494//- /main.rs
495#[lang = "deref"]
496trait Deref {
497 type Target;
498 fn deref(&self) -> &Self::Target;
499}
500
501struct Arc<T>;
502fn new_arc<T>() -> Arc<T> {}
503impl<T> Deref for Arc<T> {
504 type Target = T;
505}
506
507struct S;
508fn foo(a: Arc<S>) {}
509
510fn test() {
511 let a = new_arc();
512 let b = (*a)<|>;
513 foo(a);
514}
515"#,
516 );
517 assert_eq!(t, "S");
518}
519
520#[test]
521fn deref_trait_infinite_recursion() {
522 let t = type_at(
523 r#"
524//- /main.rs
525#[lang = "deref"]
526trait Deref {
527 type Target;
528 fn deref(&self) -> &Self::Target;
529}
530
531struct S;
532
533impl Deref for S {
534 type Target = S;
535}
536
537fn test(s: S) {
538 s.foo()<|>;
539}
540"#,
541 );
542 assert_eq!(t, "{unknown}");
543}
544
545#[test]
546fn deref_trait_with_question_mark_size() {
547 let t = type_at(
548 r#"
549//- /main.rs
550#[lang = "deref"]
551trait Deref {
552 type Target;
553 fn deref(&self) -> &Self::Target;
554}
555
556struct Arc<T>;
557impl<T> Deref for Arc<T> {
558 type Target = T;
559}
560
561struct S;
562impl S {
563 fn foo(&self) -> u128 {}
564}
565
566fn test(s: Arc<S>) {
567 (*s, s.foo())<|>;
568}
569"#,
570 );
571 assert_eq!(t, "(S, u128)");
572}
573
574#[test]
575fn obligation_from_function_clause() {
576 let t = type_at(
577 r#"
578//- /main.rs
579struct S;
580
581trait Trait<T> {}
582impl Trait<u32> for S {}
583
584fn foo<T: Trait<U>, U>(t: T) -> U {}
585
586fn test(s: S) {
587 foo(s)<|>;
588}
589"#,
590 );
591 assert_eq!(t, "u32");
592}
593
594#[test]
595fn obligation_from_method_clause() {
596 let t = type_at(
597 r#"
598//- /main.rs
599struct S;
600
601trait Trait<T> {}
602impl Trait<isize> for S {}
603
604struct O;
605impl O {
606 fn foo<T: Trait<U>, U>(&self, t: T) -> U {}
607}
608
609fn test() {
610 O.foo(S)<|>;
611}
612"#,
613 );
614 assert_eq!(t, "isize");
615}
616
617#[test]
618fn obligation_from_self_method_clause() {
619 let t = type_at(
620 r#"
621//- /main.rs
622struct S;
623
624trait Trait<T> {}
625impl Trait<i64> for S {}
626
627impl S {
628 fn foo<U>(&self) -> U where Self: Trait<U> {}
629}
630
631fn test() {
632 S.foo()<|>;
633}
634"#,
635 );
636 assert_eq!(t, "i64");
637}
638
639#[test]
640fn obligation_from_impl_clause() {
641 let t = type_at(
642 r#"
643//- /main.rs
644struct S;
645
646trait Trait<T> {}
647impl Trait<&str> for S {}
648
649struct O<T>;
650impl<U, T: Trait<U>> O<T> {
651 fn foo(&self) -> U {}
652}
653
654fn test(o: O<S>) {
655 o.foo()<|>;
656}
657"#,
658 );
659 assert_eq!(t, "&str");
660}
661
662#[test]
663fn generic_param_env_1() {
664 let t = type_at(
665 r#"
666//- /main.rs
667trait Clone {}
668trait Trait { fn foo(self) -> u128; }
669struct S;
670impl Clone for S {}
671impl<T> Trait for T where T: Clone {}
672fn test<T: Clone>(t: T) { t.foo()<|>; }
673"#,
674 );
675 assert_eq!(t, "u128");
676}
677
678#[test]
679fn generic_param_env_1_not_met() {
680 let t = type_at(
681 r#"
682//- /main.rs
683trait Clone {}
684trait Trait { fn foo(self) -> u128; }
685struct S;
686impl Clone for S {}
687impl<T> Trait for T where T: Clone {}
688fn test<T>(t: T) { t.foo()<|>; }
689"#,
690 );
691 assert_eq!(t, "{unknown}");
692}
693
694#[test]
695fn generic_param_env_2() {
696 let t = type_at(
697 r#"
698//- /main.rs
699trait Trait { fn foo(self) -> u128; }
700struct S;
701impl Trait for S {}
702fn test<T: Trait>(t: T) { t.foo()<|>; }
703"#,
704 );
705 assert_eq!(t, "u128");
706}
707
708#[test]
709fn generic_param_env_2_not_met() {
710 let t = type_at(
711 r#"
712//- /main.rs
713trait Trait { fn foo(self) -> u128; }
714struct S;
715impl Trait for S {}
716fn test<T>(t: T) { t.foo()<|>; }
717"#,
718 );
719 assert_eq!(t, "{unknown}");
720}
721
722#[test]
723fn generic_param_env_deref() {
724 let t = type_at(
725 r#"
726//- /main.rs
727#[lang = "deref"]
728trait Deref {
729 type Target;
730}
731trait Trait {}
732impl<T> Deref for T where T: Trait {
733 type Target = i128;
734}
735fn test<T: Trait>(t: T) { (*t)<|>; }
736"#,
737 );
738 assert_eq!(t, "i128");
739}
740
741#[test]
742fn associated_type_placeholder() {
743 let t = type_at(
744 r#"
745//- /main.rs
746pub trait ApplyL {
747 type Out;
748}
749
750pub struct RefMutL<T>;
751
752impl<T> ApplyL for RefMutL<T> {
753 type Out = <T as ApplyL>::Out;
754}
755
756fn test<T: ApplyL>() {
757 let y: <RefMutL<T> as ApplyL>::Out = no_matter;
758 y<|>;
759}
760"#,
761 );
762 // 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].
763 // FIXME: fix type parameter names going missing when going through Chalk
764 assert_eq!(t, "ApplyL::Out<[missing name]>");
765}
766
767#[test]
768fn associated_type_placeholder_2() {
769 let t = type_at(
770 r#"
771//- /main.rs
772pub trait ApplyL {
773 type Out;
774}
775fn foo<T: ApplyL>(t: T) -> <T as ApplyL>::Out;
776
777fn test<T: ApplyL>(t: T) {
778 let y = foo(t);
779 y<|>;
780}
781"#,
782 );
783 // FIXME here Chalk doesn't normalize the type to a placeholder. I think we
784 // need to add a rule like Normalize(<T as ApplyL>::Out -> ApplyL::Out<T>)
785 // to the trait env ourselves here; probably Chalk can't do this by itself.
786 // assert_eq!(t, "ApplyL::Out<[missing name]>");
787 assert_eq!(t, "{unknown}");
788}
789
790#[test]
791fn impl_trait() {
792 assert_snapshot!(
793 infer(r#"
794trait Trait<T> {
795 fn foo(&self) -> T;
796 fn foo2(&self) -> i64;
797}
798fn bar() -> impl Trait<u64> {}
799
800fn test(x: impl Trait<u64>, y: &impl Trait<u64>) {
801 x;
802 y;
803 let z = bar();
804 x.foo();
805 y.foo();
806 z.foo();
807 x.foo2();
808 y.foo2();
809 z.foo2();
810}
811"#),
812 @r###"
813 [30; 34) 'self': &Self
814 [55; 59) 'self': &Self
815 [99; 101) '{}': ()
816 [111; 112) 'x': impl Trait<u64>
817 [131; 132) 'y': &impl Trait<u64>
818 [152; 269) '{ ...2(); }': ()
819 [158; 159) 'x': impl Trait<u64>
820 [165; 166) 'y': &impl Trait<u64>
821 [176; 177) 'z': impl Trait<u64>
822 [180; 183) 'bar': fn bar() -> impl Trait<u64>
823 [180; 185) 'bar()': impl Trait<u64>
824 [191; 192) 'x': impl Trait<u64>
825 [191; 198) 'x.foo()': u64
826 [204; 205) 'y': &impl Trait<u64>
827 [204; 211) 'y.foo()': u64
828 [217; 218) 'z': impl Trait<u64>
829 [217; 224) 'z.foo()': u64
830 [230; 231) 'x': impl Trait<u64>
831 [230; 238) 'x.foo2()': i64
832 [244; 245) 'y': &impl Trait<u64>
833 [244; 252) 'y.foo2()': i64
834 [258; 259) 'z': impl Trait<u64>
835 [258; 266) 'z.foo2()': i64
836 "###
837 );
838}
839
840#[test]
841fn dyn_trait() {
842 assert_snapshot!(
843 infer(r#"
844trait Trait<T> {
845 fn foo(&self) -> T;
846 fn foo2(&self) -> i64;
847}
848fn bar() -> dyn Trait<u64> {}
849
850fn test(x: dyn Trait<u64>, y: &dyn Trait<u64>) {
851 x;
852 y;
853 let z = bar();
854 x.foo();
855 y.foo();
856 z.foo();
857 x.foo2();
858 y.foo2();
859 z.foo2();
860}
861"#),
862 @r###"
863 [30; 34) 'self': &Self
864 [55; 59) 'self': &Self
865 [98; 100) '{}': ()
866 [110; 111) 'x': dyn Trait<u64>
867 [129; 130) 'y': &dyn Trait<u64>
868 [149; 266) '{ ...2(); }': ()
869 [155; 156) 'x': dyn Trait<u64>
870 [162; 163) 'y': &dyn Trait<u64>
871 [173; 174) 'z': dyn Trait<u64>
872 [177; 180) 'bar': fn bar() -> dyn Trait<u64>
873 [177; 182) 'bar()': dyn Trait<u64>
874 [188; 189) 'x': dyn Trait<u64>
875 [188; 195) 'x.foo()': u64
876 [201; 202) 'y': &dyn Trait<u64>
877 [201; 208) 'y.foo()': u64
878 [214; 215) 'z': dyn Trait<u64>
879 [214; 221) 'z.foo()': u64
880 [227; 228) 'x': dyn Trait<u64>
881 [227; 235) 'x.foo2()': i64
882 [241; 242) 'y': &dyn Trait<u64>
883 [241; 249) 'y.foo2()': i64
884 [255; 256) 'z': dyn Trait<u64>
885 [255; 263) 'z.foo2()': i64
886 "###
887 );
888}
889
890#[test]
891fn dyn_trait_bare() {
892 assert_snapshot!(
893 infer(r#"
894trait Trait {
895 fn foo(&self) -> u64;
896}
897fn bar() -> Trait {}
898
899fn test(x: Trait, y: &Trait) -> u64 {
900 x;
901 y;
902 let z = bar();
903 x.foo();
904 y.foo();
905 z.foo();
906}
907"#),
908 @r###"
909 [27; 31) 'self': &Self
910 [61; 63) '{}': ()
911 [73; 74) 'x': dyn Trait
912 [83; 84) 'y': &dyn Trait
913 [101; 176) '{ ...o(); }': ()
914 [107; 108) 'x': dyn Trait
915 [114; 115) 'y': &dyn Trait
916 [125; 126) 'z': dyn Trait
917 [129; 132) 'bar': fn bar() -> dyn Trait
918 [129; 134) 'bar()': dyn Trait
919 [140; 141) 'x': dyn Trait
920 [140; 147) 'x.foo()': u64
921 [153; 154) 'y': &dyn Trait
922 [153; 160) 'y.foo()': u64
923 [166; 167) 'z': dyn Trait
924 [166; 173) 'z.foo()': u64
925 "###
926 );
927}
928
929#[test]
930fn weird_bounds() {
931 assert_snapshot!(
932 infer(r#"
933trait Trait {}
934fn test() {
935 let a: impl Trait + 'lifetime = foo;
936 let b: impl 'lifetime = foo;
937 let b: impl (Trait) = foo;
938 let b: impl ('lifetime) = foo;
939 let d: impl ?Sized = foo;
940 let e: impl Trait + ?Sized = foo;
941}
942"#),
943 @r###"
944 [26; 237) '{ ...foo; }': ()
945 [36; 37) 'a': impl Trait + {error}
946 [64; 67) 'foo': impl Trait + {error}
947 [77; 78) 'b': impl {error}
948 [97; 100) 'foo': impl {error}
949 [110; 111) 'b': impl Trait
950 [128; 131) 'foo': impl Trait
951 [141; 142) 'b': impl {error}
952 [163; 166) 'foo': impl {error}
953 [176; 177) 'd': impl {error}
954 [193; 196) 'foo': impl {error}
955 [206; 207) 'e': impl Trait + {error}
956 [231; 234) 'foo': impl Trait + {error}
957 "###
958 );
959}
960
961#[test]
962fn error_bound_chalk() {
963 let t = type_at(
964 r#"
965//- /main.rs
966trait Trait {
967 fn foo(&self) -> u32 {}
968}
969
970fn test(x: (impl Trait + UnknownTrait)) {
971 x.foo()<|>;
972}
973"#,
974 );
975 assert_eq!(t, "u32");
976}
977
978#[test]
979fn assoc_type_bindings() {
980 assert_snapshot!(
981 infer(r#"
982trait Trait {
983 type Type;
984}
985
986fn get<T: Trait>(t: T) -> <T as Trait>::Type {}
987fn get2<U, T: Trait<Type = U>>(t: T) -> U {}
988fn set<T: Trait<Type = u64>>(t: T) -> T {t}
989
990struct S<T>;
991impl<T> Trait for S<T> { type Type = T; }
992
993fn test<T: Trait<Type = u32>>(x: T, y: impl Trait<Type = i64>) {
994 get(x);
995 get2(x);
996 get(y);
997 get2(y);
998 get(set(S));
999 get2(set(S));
1000 get2(S::<str>);
1001}
1002"#),
1003 @r###"
1004 [50; 51) 't': T
1005 [78; 80) '{}': ()
1006 [112; 113) 't': T
1007 [123; 125) '{}': ()
1008 [155; 156) 't': T
1009 [166; 169) '{t}': T
1010 [167; 168) 't': T
1011 [257; 258) 'x': T
1012 [263; 264) 'y': impl Trait<Type = i64>
1013 [290; 398) '{ ...r>); }': ()
1014 [296; 299) 'get': fn get<T>(T) -> <T as Trait>::Type
1015 [296; 302) 'get(x)': {unknown}
1016 [300; 301) 'x': T
1017 [308; 312) 'get2': fn get2<{unknown}, T>(T) -> U
1018 [308; 315) 'get2(x)': {unknown}
1019 [313; 314) 'x': T
1020 [321; 324) 'get': fn get<impl Trait<Type = i64>>(T) -> <T as Trait>::Type
1021 [321; 327) 'get(y)': {unknown}
1022 [325; 326) 'y': impl Trait<Type = i64>
1023 [333; 337) 'get2': fn get2<{unknown}, impl Trait<Type = i64>>(T) -> U
1024 [333; 340) 'get2(y)': {unknown}
1025 [338; 339) 'y': impl Trait<Type = i64>
1026 [346; 349) 'get': fn get<S<u64>>(T) -> <T as Trait>::Type
1027 [346; 357) 'get(set(S))': u64
1028 [350; 353) 'set': fn set<S<u64>>(T) -> T
1029 [350; 356) 'set(S)': S<u64>
1030 [354; 355) 'S': S<u64>
1031 [363; 367) 'get2': fn get2<u64, S<u64>>(T) -> U
1032 [363; 375) 'get2(set(S))': u64
1033 [368; 371) 'set': fn set<S<u64>>(T) -> T
1034 [368; 374) 'set(S)': S<u64>
1035 [372; 373) 'S': S<u64>
1036 [381; 385) 'get2': fn get2<str, S<str>>(T) -> U
1037 [381; 395) 'get2(S::<str>)': str
1038 [386; 394) 'S::<str>': S<str>
1039 "###
1040 );
1041}
1042
1043#[test]
1044fn impl_trait_assoc_binding_projection_bug() {
1045 let (db, pos) = TestDB::with_position(
1046 r#"
1047//- /main.rs crate:main deps:std
1048pub trait Language {
1049 type Kind;
1050}
1051pub enum RustLanguage {}
1052impl Language for RustLanguage {
1053 type Kind = SyntaxKind;
1054}
1055struct SyntaxNode<L> {}
1056fn foo() -> impl Iterator<Item = SyntaxNode<RustLanguage>> {}
1057
1058trait Clone {
1059 fn clone(&self) -> Self;
1060}
1061
1062fn api_walkthrough() {
1063 for node in foo() {
1064 node.clone()<|>;
1065 }
1066}
1067
1068//- /std.rs crate:std
1069#[prelude_import] use iter::*;
1070mod iter {
1071 trait IntoIterator {
1072 type Item;
1073 }
1074 trait Iterator {
1075 type Item;
1076 }
1077 impl<T: Iterator> IntoIterator for T {
1078 type Item = <T as Iterator>::Item;
1079 }
1080}
1081"#,
1082 );
1083 assert_eq!("{unknown}", type_at_pos(&db, pos));
1084}
1085
1086#[test]
1087fn projection_eq_within_chalk() {
1088 // std::env::set_var("CHALK_DEBUG", "1");
1089 assert_snapshot!(
1090 infer(r#"
1091trait Trait1 {
1092 type Type;
1093}
1094trait Trait2<T> {
1095 fn foo(self) -> T;
1096}
1097impl<T, U> Trait2<T> for U where U: Trait1<Type = T> {}
1098
1099fn test<T: Trait1<Type = u32>>(x: T) {
1100 x.foo();
1101}
1102"#),
1103 @r###"
1104 [62; 66) 'self': Self
1105 [164; 165) 'x': T
1106 [170; 186) '{ ...o(); }': ()
1107 [176; 177) 'x': T
1108 [176; 183) 'x.foo()': {unknown}
1109 "###
1110 );
1111}
1112
1113#[test]
1114fn where_clause_trait_in_scope_for_method_resolution() {
1115 let t = type_at(
1116 r#"
1117//- /main.rs
1118mod foo {
1119 trait Trait {
1120 fn foo(&self) -> u32 {}
1121 }
1122}
1123
1124fn test<T: foo::Trait>(x: T) {
1125 x.foo()<|>;
1126}
1127"#,
1128 );
1129 assert_eq!(t, "u32");
1130}
1131
1132#[test]
1133fn super_trait_method_resolution() {
1134 assert_snapshot!(
1135 infer(r#"
1136mod foo {
1137 trait SuperTrait {
1138 fn foo(&self) -> u32 {}
1139 }
1140}
1141trait Trait1: foo::SuperTrait {}
1142trait Trait2 where Self: foo::SuperTrait {}
1143
1144fn test<T: Trait1, U: Trait2>(x: T, y: U) {
1145 x.foo();
1146 y.foo();
1147}
1148"#),
1149 @r###"
1150 [50; 54) 'self': &Self
1151 [63; 65) '{}': ()
1152 [182; 183) 'x': T
1153 [188; 189) 'y': U
1154 [194; 223) '{ ...o(); }': ()
1155 [200; 201) 'x': T
1156 [200; 207) 'x.foo()': u32
1157 [213; 214) 'y': U
1158 [213; 220) 'y.foo()': u32
1159 "###
1160 );
1161}
1162
1163#[test]
1164fn super_trait_cycle() {
1165 // This just needs to not crash
1166 assert_snapshot!(
1167 infer(r#"
1168trait A: B {}
1169trait B: A {}
1170
1171fn test<T: A>(x: T) {
1172 x.foo();
1173}
1174"#),
1175 @r###"
1176 [44; 45) 'x': T
1177 [50; 66) '{ ...o(); }': ()
1178 [56; 57) 'x': T
1179 [56; 63) 'x.foo()': {unknown}
1180 "###
1181 );
1182}
1183
1184#[test]
1185fn super_trait_assoc_type_bounds() {
1186 assert_snapshot!(
1187 infer(r#"
1188trait SuperTrait { type Type; }
1189trait Trait where Self: SuperTrait {}
1190
1191fn get2<U, T: Trait<Type = U>>(t: T) -> U {}
1192fn set<T: Trait<Type = u64>>(t: T) -> T {t}
1193
1194struct S<T>;
1195impl<T> SuperTrait for S<T> { type Type = T; }
1196impl<T> Trait for S<T> {}
1197
1198fn test() {
1199 get2(set(S));
1200}
1201"#),
1202 @r###"
1203 [103; 104) 't': T
1204 [114; 116) '{}': ()
1205 [146; 147) 't': T
1206 [157; 160) '{t}': T
1207 [158; 159) 't': T
1208 [259; 280) '{ ...S)); }': ()
1209 [265; 269) 'get2': fn get2<u64, S<u64>>(T) -> U
1210 [265; 277) 'get2(set(S))': u64
1211 [270; 273) 'set': fn set<S<u64>>(T) -> T
1212 [270; 276) 'set(S)': S<u64>
1213 [274; 275) 'S': S<u64>
1214 "###
1215 );
1216}
1217
1218#[test]
1219fn fn_trait() {
1220 assert_snapshot!(
1221 infer(r#"
1222trait FnOnce<Args> {
1223 type Output;
1224
1225 fn call_once(self, args: Args) -> <Self as FnOnce<Args>>::Output;
1226}
1227
1228fn test<F: FnOnce(u32, u64) -> u128>(f: F) {
1229 f.call_once((1, 2));
1230}
1231"#),
1232 @r###"
1233 [57; 61) 'self': Self
1234 [63; 67) 'args': Args
1235 [150; 151) 'f': F
1236 [156; 184) '{ ...2)); }': ()
1237 [162; 163) 'f': F
1238 [162; 181) 'f.call...1, 2))': {unknown}
1239 [174; 180) '(1, 2)': (u32, u64)
1240 [175; 176) '1': u32
1241 [178; 179) '2': u64
1242 "###
1243 );
1244}
1245
1246#[test]
1247fn closure_1() {
1248 assert_snapshot!(
1249 infer(r#"
1250#[lang = "fn_once"]
1251trait FnOnce<Args> {
1252 type Output;
1253}
1254
1255enum Option<T> { Some(T), None }
1256impl<T> Option<T> {
1257 fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> {}
1258}
1259
1260fn test() {
1261 let x = Option::Some(1u32);
1262 x.map(|v| v + 1);
1263 x.map(|_v| 1u64);
1264 let y: Option<i64> = x.map(|_v| 1);
1265}
1266"#),
1267 @r###"
1268 [148; 152) 'self': Option<T>
1269 [154; 155) 'f': F
1270 [173; 175) '{}': ()
1271 [189; 308) '{ ... 1); }': ()
1272 [199; 200) 'x': Option<u32>
1273 [203; 215) 'Option::Some': Some<u32>(T) -> Option<T>
1274 [203; 221) 'Option...(1u32)': Option<u32>
1275 [216; 220) '1u32': u32
1276 [227; 228) 'x': Option<u32>
1277 [227; 243) 'x.map(...v + 1)': Option<u32>
1278 [233; 242) '|v| v + 1': |u32| -> u32
1279 [234; 235) 'v': u32
1280 [237; 238) 'v': u32
1281 [237; 242) 'v + 1': u32
1282 [241; 242) '1': u32
1283 [249; 250) 'x': Option<u32>
1284 [249; 265) 'x.map(... 1u64)': Option<u64>
1285 [255; 264) '|_v| 1u64': |u32| -> u64
1286 [256; 258) '_v': u32
1287 [260; 264) '1u64': u64
1288 [275; 276) 'y': Option<i64>
1289 [292; 293) 'x': Option<u32>
1290 [292; 305) 'x.map(|_v| 1)': Option<i64>
1291 [298; 304) '|_v| 1': |u32| -> i64
1292 [299; 301) '_v': u32
1293 [303; 304) '1': i64
1294 "###
1295 );
1296}
1297
1298#[test]
1299fn closure_2() {
1300 assert_snapshot!(
1301 infer(r#"
1302trait FnOnce<Args> {
1303 type Output;
1304}
1305
1306fn test<F: FnOnce(u32) -> u64>(f: F) {
1307 f(1);
1308 let g = |v| v + 1;
1309 g(1u64);
1310 let h = |v| 1u128 + v;
1311}
1312"#),
1313 @r###"
1314 [73; 74) 'f': F
1315 [79; 155) '{ ...+ v; }': ()
1316 [85; 86) 'f': F
1317 [85; 89) 'f(1)': {unknown}
1318 [87; 88) '1': i32
1319 [99; 100) 'g': |u64| -> i32
1320 [103; 112) '|v| v + 1': |u64| -> i32
1321 [104; 105) 'v': u64
1322 [107; 108) 'v': u64
1323 [107; 112) 'v + 1': i32
1324 [111; 112) '1': i32
1325 [118; 119) 'g': |u64| -> i32
1326 [118; 125) 'g(1u64)': i32
1327 [120; 124) '1u64': u64
1328 [135; 136) 'h': |u128| -> u128
1329 [139; 152) '|v| 1u128 + v': |u128| -> u128
1330 [140; 141) 'v': u128
1331 [143; 148) '1u128': u128
1332 [143; 152) '1u128 + v': u128
1333 [151; 152) 'v': u128
1334 "###
1335 );
1336}
1337
1338#[test]
1339fn closure_as_argument_inference_order() {
1340 assert_snapshot!(
1341 infer(r#"
1342#[lang = "fn_once"]
1343trait FnOnce<Args> {
1344 type Output;
1345}
1346
1347fn foo1<T, U, F: FnOnce(T) -> U>(x: T, f: F) -> U {}
1348fn foo2<T, U, F: FnOnce(T) -> U>(f: F, x: T) -> U {}
1349
1350struct S;
1351impl S {
1352 fn method(self) -> u64;
1353
1354 fn foo1<T, U, F: FnOnce(T) -> U>(self, x: T, f: F) -> U {}
1355 fn foo2<T, U, F: FnOnce(T) -> U>(self, f: F, x: T) -> U {}
1356}
1357
1358fn test() {
1359 let x1 = foo1(S, |s| s.method());
1360 let x2 = foo2(|s| s.method(), S);
1361 let x3 = S.foo1(S, |s| s.method());
1362 let x4 = S.foo2(|s| s.method(), S);
1363}
1364"#),
1365 @r###"
1366 [95; 96) 'x': T
1367 [101; 102) 'f': F
1368 [112; 114) '{}': ()
1369 [148; 149) 'f': F
1370 [154; 155) 'x': T
1371 [165; 167) '{}': ()
1372 [202; 206) 'self': S
1373 [254; 258) 'self': S
1374 [260; 261) 'x': T
1375 [266; 267) 'f': F
1376 [277; 279) '{}': ()
1377 [317; 321) 'self': S
1378 [323; 324) 'f': F
1379 [329; 330) 'x': T
1380 [340; 342) '{}': ()
1381 [356; 515) '{ ... S); }': ()
1382 [366; 368) 'x1': u64
1383 [371; 375) 'foo1': fn foo1<S, u64, |S| -> u64>(T, F) -> U
1384 [371; 394) 'foo1(S...hod())': u64
1385 [376; 377) 'S': S
1386 [379; 393) '|s| s.method()': |S| -> u64
1387 [380; 381) 's': S
1388 [383; 384) 's': S
1389 [383; 393) 's.method()': u64
1390 [404; 406) 'x2': u64
1391 [409; 413) 'foo2': fn foo2<S, u64, |S| -> u64>(F, T) -> U
1392 [409; 432) 'foo2(|...(), S)': u64
1393 [414; 428) '|s| s.method()': |S| -> u64
1394 [415; 416) 's': S
1395 [418; 419) 's': S
1396 [418; 428) 's.method()': u64
1397 [430; 431) 'S': S
1398 [442; 444) 'x3': u64
1399 [447; 448) 'S': S
1400 [447; 472) 'S.foo1...hod())': u64
1401 [454; 455) 'S': S
1402 [457; 471) '|s| s.method()': |S| -> u64
1403 [458; 459) 's': S
1404 [461; 462) 's': S
1405 [461; 471) 's.method()': u64
1406 [482; 484) 'x4': u64
1407 [487; 488) 'S': S
1408 [487; 512) 'S.foo2...(), S)': u64
1409 [494; 508) '|s| s.method()': |S| -> u64
1410 [495; 496) 's': S
1411 [498; 499) 's': S
1412 [498; 508) 's.method()': u64
1413 [510; 511) 'S': S
1414 "###
1415 );
1416}
1417
1418#[test]
1419fn unselected_projection_in_trait_env_1() {
1420 let t = type_at(
1421 r#"
1422//- /main.rs
1423trait Trait {
1424 type Item;
1425}
1426
1427trait Trait2 {
1428 fn foo(&self) -> u32;
1429}
1430
1431fn test<T: Trait>() where T::Item: Trait2 {
1432 let x: T::Item = no_matter;
1433 x.foo()<|>;
1434}
1435"#,
1436 );
1437 assert_eq!(t, "u32");
1438}
1439
1440#[test]
1441fn unselected_projection_in_trait_env_2() {
1442 let t = type_at(
1443 r#"
1444//- /main.rs
1445trait Trait<T> {
1446 type Item;
1447}
1448
1449trait Trait2 {
1450 fn foo(&self) -> u32;
1451}
1452
1453fn test<T, U>() where T::Item: Trait2, T: Trait<U::Item>, U: Trait<()> {
1454 let x: T::Item = no_matter;
1455 x.foo()<|>;
1456}
1457"#,
1458 );
1459 assert_eq!(t, "u32");
1460}
1461
1462#[test]
1463fn trait_impl_self_ty() {
1464 let t = type_at(
1465 r#"
1466//- /main.rs
1467trait Trait<T> {
1468 fn foo(&self);
1469}
1470
1471struct S;
1472
1473impl Trait<Self> for S {}
1474
1475fn test() {
1476 S.foo()<|>;
1477}
1478"#,
1479 );
1480 assert_eq!(t, "()");
1481}
1482
1483#[test]
1484fn trait_impl_self_ty_cycle() {
1485 let t = type_at(
1486 r#"
1487//- /main.rs
1488trait Trait {
1489 fn foo(&self);
1490}
1491
1492struct S<T>;
1493
1494impl Trait for S<Self> {}
1495
1496fn test() {
1497 S.foo()<|>;
1498}
1499"#,
1500 );
1501 assert_eq!(t, "{unknown}");
1502}
1503
1504#[test]
1505fn unselected_projection_in_trait_env_cycle_1() {
1506 let t = type_at(
1507 r#"
1508//- /main.rs
1509trait Trait {
1510 type Item;
1511}
1512
1513trait Trait2<T> {}
1514
1515fn test<T: Trait>() where T: Trait2<T::Item> {
1516 let x: T::Item = no_matter<|>;
1517}
1518"#,
1519 );
1520 // this is a legitimate cycle
1521 assert_eq!(t, "{unknown}");
1522}
1523
1524#[test]
1525fn unselected_projection_in_trait_env_cycle_2() {
1526 let t = type_at(
1527 r#"
1528//- /main.rs
1529trait Trait<T> {
1530 type Item;
1531}
1532
1533fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> {
1534 let x: T::Item = no_matter<|>;
1535}
1536"#,
1537 );
1538 // this is a legitimate cycle
1539 assert_eq!(t, "{unknown}");
1540}
1541
1542#[test]
1543fn unify_impl_trait() {
1544 covers!(insert_vars_for_impl_trait);
1545 assert_snapshot!(
1546 infer_with_mismatches(r#"
1547trait Trait<T> {}
1548
1549fn foo(x: impl Trait<u32>) { loop {} }
1550fn bar<T>(x: impl Trait<T>) -> T { loop {} }
1551
1552struct S<T>(T);
1553impl<T> Trait<T> for S<T> {}
1554
1555fn default<T>() -> T { loop {} }
1556
1557fn test() -> impl Trait<i32> {
1558 let s1 = S(default());
1559 foo(s1);
1560 let x: i32 = bar(S(default()));
1561 S(default())
1562}
1563"#, true),
1564 @r###"
1565 [27; 28) 'x': impl Trait<u32>
1566 [47; 58) '{ loop {} }': ()
1567 [49; 56) 'loop {}': !
1568 [54; 56) '{}': ()
1569 [69; 70) 'x': impl Trait<T>
1570 [92; 103) '{ loop {} }': T
1571 [94; 101) 'loop {}': !
1572 [99; 101) '{}': ()
1573 [172; 183) '{ loop {} }': T
1574 [174; 181) 'loop {}': !
1575 [179; 181) '{}': ()
1576 [214; 310) '{ ...t()) }': S<i32>
1577 [224; 226) 's1': S<u32>
1578 [229; 230) 'S': S<u32>(T) -> S<T>
1579 [229; 241) 'S(default())': S<u32>
1580 [231; 238) 'default': fn default<u32>() -> T
1581 [231; 240) 'default()': u32
1582 [247; 250) 'foo': fn foo(impl Trait<u32>) -> ()
1583 [247; 254) 'foo(s1)': ()
1584 [251; 253) 's1': S<u32>
1585 [264; 265) 'x': i32
1586 [273; 276) 'bar': fn bar<i32>(impl Trait<T>) -> T
1587 [273; 290) 'bar(S(...lt()))': i32
1588 [277; 278) 'S': S<i32>(T) -> S<T>
1589 [277; 289) 'S(default())': S<i32>
1590 [279; 286) 'default': fn default<i32>() -> T
1591 [279; 288) 'default()': i32
1592 [296; 297) 'S': S<i32>(T) -> S<T>
1593 [296; 308) 'S(default())': S<i32>
1594 [298; 305) 'default': fn default<i32>() -> T
1595 [298; 307) 'default()': i32
1596 "###
1597 );
1598}
diff --git a/crates/ra_hir_ty/src/traits.rs b/crates/ra_hir_ty/src/traits.rs
index 76189a60b..c4dc857bc 100644
--- a/crates/ra_hir_ty/src/traits.rs
+++ b/crates/ra_hir_ty/src/traits.rs
@@ -1,7 +1,7 @@
1//! Trait solving using Chalk. 1//! Trait solving using Chalk.
2use std::sync::{Arc, Mutex}; 2use std::sync::{Arc, Mutex};
3 3
4use chalk_ir::{cast::Cast, family::ChalkIr}; 4use chalk_ir::cast::Cast;
5use hir_def::{expr::ExprId, DefWithBodyId, ImplId, TraitId, TypeAliasId}; 5use hir_def::{expr::ExprId, DefWithBodyId, ImplId, TraitId, TypeAliasId};
6use log::debug; 6use log::debug;
7use ra_db::{impl_intern_key, salsa, CrateId}; 7use ra_db::{impl_intern_key, salsa, CrateId};
@@ -12,14 +12,15 @@ use crate::db::HirDatabase;
12 12
13use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; 13use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk};
14 14
15use self::chalk::{from_chalk, ToChalk}; 15use self::chalk::{from_chalk, ToChalk, TypeFamily};
16 16
17pub(crate) mod chalk; 17pub(crate) mod chalk;
18mod builtin;
18 19
19#[derive(Debug, Clone)] 20#[derive(Debug, Clone)]
20pub struct TraitSolver { 21pub struct TraitSolver {
21 krate: CrateId, 22 krate: CrateId,
22 inner: Arc<Mutex<chalk_solve::Solver<ChalkIr>>>, 23 inner: Arc<Mutex<chalk_solve::Solver<TypeFamily>>>,
23} 24}
24 25
25/// We need eq for salsa 26/// We need eq for salsa
@@ -35,8 +36,8 @@ impl TraitSolver {
35 fn solve( 36 fn solve(
36 &self, 37 &self,
37 db: &impl HirDatabase, 38 db: &impl HirDatabase,
38 goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal<ChalkIr>>>, 39 goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal<TypeFamily>>>,
39 ) -> Option<chalk_solve::Solution<ChalkIr>> { 40 ) -> Option<chalk_solve::Solution<TypeFamily>> {
40 let context = ChalkContext { db, krate: self.krate }; 41 let context = ChalkContext { db, krate: self.krate };
41 debug!("solve goal: {:?}", goal); 42 debug!("solve goal: {:?}", goal);
42 let mut solver = match self.inner.lock() { 43 let mut solver = match self.inner.lock() {
@@ -200,17 +201,17 @@ pub(crate) fn trait_solve_query(
200 201
201fn solution_from_chalk( 202fn solution_from_chalk(
202 db: &impl HirDatabase, 203 db: &impl HirDatabase,
203 solution: chalk_solve::Solution<ChalkIr>, 204 solution: chalk_solve::Solution<TypeFamily>,
204) -> Solution { 205) -> Solution {
205 let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<ChalkIr>>| { 206 let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<TypeFamily>>| {
206 let value = subst 207 let value = subst
207 .value 208 .value
208 .parameters 209 .parameters
209 .into_iter() 210 .into_iter()
210 .map(|p| { 211 .map(|p| {
211 let ty = match p { 212 let ty = match p.ty() {
212 chalk_ir::Parameter(chalk_ir::ParameterKind::Ty(ty)) => from_chalk(db, ty), 213 Some(ty) => from_chalk(db, ty.clone()),
213 chalk_ir::Parameter(chalk_ir::ParameterKind::Lifetime(_)) => unimplemented!(), 214 None => unimplemented!(),
214 }; 215 };
215 ty 216 ty
216 }) 217 })
@@ -290,7 +291,7 @@ impl FnTrait {
290 } 291 }
291} 292}
292 293
293#[derive(Debug, Clone, PartialEq, Eq, Hash)] 294#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
294pub struct ClosureFnTraitImplData { 295pub struct ClosureFnTraitImplData {
295 def: DefWithBodyId, 296 def: DefWithBodyId,
296 expr: ExprId, 297 expr: ExprId,
@@ -299,7 +300,7 @@ pub struct ClosureFnTraitImplData {
299 300
300/// An impl. Usually this comes from an impl block, but some built-in types get 301/// An impl. Usually this comes from an impl block, but some built-in types get
301/// synthetic impls. 302/// synthetic impls.
302#[derive(Debug, Clone, PartialEq, Eq, Hash)] 303#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
303pub enum Impl { 304pub enum Impl {
304 /// A normal impl from an impl block. 305 /// A normal impl from an impl block.
305 ImplBlock(ImplId), 306 ImplBlock(ImplId),
diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs
new file mode 100644
index 000000000..dd41176f0
--- /dev/null
+++ b/crates/ra_hir_ty/src/traits/builtin.rs
@@ -0,0 +1,178 @@
1//! This module provides the built-in trait implementations, e.g. to make
2//! closures implement `Fn`.
3use hir_def::{expr::Expr, lang_item::LangItemTarget, TraitId, TypeAliasId};
4use hir_expand::name::name;
5use ra_db::CrateId;
6
7use super::{AssocTyValue, Impl};
8use crate::{db::HirDatabase, ApplicationTy, Substs, TraitRef, Ty, TypeCtor};
9
10pub(super) struct BuiltinImplData {
11 pub num_vars: usize,
12 pub trait_ref: TraitRef,
13 pub where_clauses: Vec<super::GenericPredicate>,
14 pub assoc_ty_values: Vec<AssocTyValue>,
15}
16
17pub(super) struct BuiltinImplAssocTyValueData {
18 pub impl_: Impl,
19 pub assoc_ty_id: TypeAliasId,
20 pub num_vars: usize,
21 pub value: Ty,
22}
23
24pub(super) fn get_builtin_impls(
25 db: &impl HirDatabase,
26 krate: CrateId,
27 ty: &Ty,
28 trait_: TraitId,
29 mut callback: impl FnMut(Impl),
30) {
31 // Note: since impl_datum needs to be infallible, we need to make sure here
32 // that we have all prerequisites to build the respective impls.
33 if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { def, expr }, .. }) = ty {
34 for &fn_trait in [super::FnTrait::FnOnce, super::FnTrait::FnMut, super::FnTrait::Fn].iter()
35 {
36 if let Some(actual_trait) = get_fn_trait(db, krate, fn_trait) {
37 if trait_ == actual_trait {
38 let impl_ = super::ClosureFnTraitImplData { def: *def, expr: *expr, fn_trait };
39 if check_closure_fn_trait_impl_prerequisites(db, krate, impl_) {
40 callback(Impl::ClosureFnTraitImpl(impl_));
41 }
42 }
43 }
44 }
45 }
46}
47
48pub(super) fn impl_datum(db: &impl HirDatabase, krate: CrateId, impl_: Impl) -> BuiltinImplData {
49 match impl_ {
50 Impl::ImplBlock(_) => unreachable!(),
51 Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data),
52 }
53}
54
55pub(super) fn associated_ty_value(
56 db: &impl HirDatabase,
57 krate: CrateId,
58 data: AssocTyValue,
59) -> BuiltinImplAssocTyValueData {
60 match data {
61 AssocTyValue::TypeAlias(_) => unreachable!(),
62 AssocTyValue::ClosureFnTraitImplOutput(data) => {
63 closure_fn_trait_output_assoc_ty_value(db, krate, data)
64 }
65 }
66}
67
68fn check_closure_fn_trait_impl_prerequisites(
69 db: &impl HirDatabase,
70 krate: CrateId,
71 data: super::ClosureFnTraitImplData,
72) -> bool {
73 // the respective Fn/FnOnce/FnMut trait needs to exist
74 if get_fn_trait(db, krate, data.fn_trait).is_none() {
75 return false;
76 }
77
78 // FIXME: there are more assumptions that we should probably check here:
79 // the traits having no type params, FnOnce being a supertrait
80
81 // the FnOnce trait needs to exist and have an assoc type named Output
82 let fn_once_trait = match get_fn_trait(db, krate, super::FnTrait::FnOnce) {
83 Some(t) => t,
84 None => return false,
85 };
86 db.trait_data(fn_once_trait).associated_type_by_name(&name![Output]).is_some()
87}
88
89fn closure_fn_trait_impl_datum(
90 db: &impl HirDatabase,
91 krate: CrateId,
92 data: super::ClosureFnTraitImplData,
93) -> BuiltinImplData {
94 // for some closure |X, Y| -> Z:
95 // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V }
96
97 let trait_ = get_fn_trait(db, krate, data.fn_trait) // get corresponding fn trait
98 // the existence of the Fn trait has been checked before
99 .expect("fn trait for closure impl missing");
100
101 let num_args: u16 = match &db.body(data.def.into())[data.expr] {
102 Expr::Lambda { args, .. } => args.len() as u16,
103 _ => {
104 log::warn!("closure for closure type {:?} not found", data);
105 0
106 }
107 };
108
109 let arg_ty = Ty::apply(
110 TypeCtor::Tuple { cardinality: num_args },
111 Substs::builder(num_args as usize).fill_with_bound_vars(0).build(),
112 );
113 let sig_ty = Ty::apply(
114 TypeCtor::FnPtr { num_args },
115 Substs::builder(num_args as usize + 1).fill_with_bound_vars(0).build(),
116 );
117
118 let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty);
119
120 let trait_ref = TraitRef {
121 trait_: trait_.into(),
122 substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(),
123 };
124
125 let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone());
126
127 BuiltinImplData {
128 num_vars: num_args as usize + 1,
129 trait_ref,
130 where_clauses: Vec::new(),
131 assoc_ty_values: vec![output_ty_id],
132 }
133}
134
135fn closure_fn_trait_output_assoc_ty_value(
136 db: &impl HirDatabase,
137 krate: CrateId,
138 data: super::ClosureFnTraitImplData,
139) -> BuiltinImplAssocTyValueData {
140 let impl_ = Impl::ClosureFnTraitImpl(data.clone());
141
142 let num_args: u16 = match &db.body(data.def.into())[data.expr] {
143 Expr::Lambda { args, .. } => args.len() as u16,
144 _ => {
145 log::warn!("closure for closure type {:?} not found", data);
146 0
147 }
148 };
149
150 let output_ty = Ty::Bound(num_args.into());
151
152 let fn_once_trait =
153 get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist");
154
155 let output_ty_id = db
156 .trait_data(fn_once_trait)
157 .associated_type_by_name(&name![Output])
158 .expect("assoc ty value should not exist");
159
160 BuiltinImplAssocTyValueData {
161 impl_,
162 assoc_ty_id: output_ty_id,
163 num_vars: num_args as usize + 1,
164 value: output_ty,
165 }
166}
167
168fn get_fn_trait(
169 db: &impl HirDatabase,
170 krate: CrateId,
171 fn_trait: super::FnTrait,
172) -> Option<TraitId> {
173 let target = db.lang_item(krate, fn_trait.lang_item_name().into())?;
174 match target {
175 LangItemTarget::TraitId(t) => Some(t),
176 _ => None,
177 }
178}
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs
index 35de37e6b..555930c9b 100644
--- a/crates/ra_hir_ty/src/traits/chalk.rs
+++ b/crates/ra_hir_ty/src/traits/chalk.rs
@@ -1,32 +1,99 @@
1//! Conversion code from/to Chalk. 1//! Conversion code from/to Chalk.
2use std::sync::Arc; 2use std::{fmt, sync::Arc};
3 3
4use log::debug; 4use log::debug;
5 5
6use chalk_ir::{ 6use chalk_ir::{cast::Cast, Parameter, PlaceholderIndex, TypeName, UniverseIndex};
7 cast::Cast, family::ChalkIr, Identifier, Parameter, PlaceholderIndex, TypeId, TypeKindId,
8 TypeName, UniverseIndex,
9};
10use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum};
11use ra_db::CrateId;
12 7
13use hir_def::{ 8use hir_def::{AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId};
14 expr::Expr, lang_item::LangItemTarget, AssocItemId, AstItemDef, ContainerId, GenericDefId, 9use ra_db::{
15 ImplId, Lookup, TraitId, TypeAliasId, 10 salsa::{InternId, InternKey},
11 CrateId,
16}; 12};
17use hir_expand::name;
18
19use ra_db::salsa::{InternId, InternKey};
20 13
21use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; 14use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation};
22use crate::{ 15use crate::{
23 db::HirDatabase, display::HirDisplay, ApplicationTy, GenericPredicate, ImplTy, ProjectionTy, 16 db::HirDatabase, display::HirDisplay, utils::generics, ApplicationTy, GenericPredicate,
24 Substs, TraitRef, Ty, TypeCtor, TypeWalk, 17 ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk,
25}; 18};
26 19
27/// This represents a trait whose name we could not resolve. 20#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
28const UNKNOWN_TRAIT: chalk_ir::TraitId = 21pub struct TypeFamily {}
29 chalk_ir::TraitId(chalk_ir::RawId { index: u32::max_value() }); 22
23impl chalk_ir::family::TypeFamily for TypeFamily {
24 type InternedType = Box<chalk_ir::TyData<Self>>;
25 type InternedLifetime = chalk_ir::LifetimeData<Self>;
26 type InternedParameter = chalk_ir::ParameterData<Self>;
27 type DefId = InternId;
28
29 // FIXME: implement these
30 fn debug_struct_id(
31 _type_kind_id: chalk_ir::StructId<Self>,
32 _fmt: &mut fmt::Formatter<'_>,
33 ) -> Option<fmt::Result> {
34 None
35 }
36
37 fn debug_trait_id(
38 _type_kind_id: chalk_ir::TraitId<Self>,
39 _fmt: &mut fmt::Formatter<'_>,
40 ) -> Option<fmt::Result> {
41 None
42 }
43
44 fn debug_assoc_type_id(
45 _id: chalk_ir::AssocTypeId<Self>,
46 _fmt: &mut fmt::Formatter<'_>,
47 ) -> Option<fmt::Result> {
48 None
49 }
50
51 fn debug_projection(
52 _projection: &chalk_ir::ProjectionTy<Self>,
53 _fmt: &mut fmt::Formatter<'_>,
54 ) -> Option<fmt::Result> {
55 None
56 }
57
58 fn intern_ty(ty: chalk_ir::TyData<Self>) -> Box<chalk_ir::TyData<Self>> {
59 Box::new(ty)
60 }
61
62 fn ty_data(ty: &Box<chalk_ir::TyData<Self>>) -> &chalk_ir::TyData<Self> {
63 ty
64 }
65
66 fn intern_lifetime(lifetime: chalk_ir::LifetimeData<Self>) -> chalk_ir::LifetimeData<Self> {
67 lifetime
68 }
69
70 fn lifetime_data(lifetime: &chalk_ir::LifetimeData<Self>) -> &chalk_ir::LifetimeData<Self> {
71 lifetime
72 }
73
74 fn intern_parameter(parameter: chalk_ir::ParameterData<Self>) -> chalk_ir::ParameterData<Self> {
75 parameter
76 }
77
78 fn parameter_data(parameter: &chalk_ir::ParameterData<Self>) -> &chalk_ir::ParameterData<Self> {
79 parameter
80 }
81}
82
83impl chalk_ir::family::HasTypeFamily for TypeFamily {
84 type TypeFamily = Self;
85}
86
87pub type AssocTypeId = chalk_ir::AssocTypeId<TypeFamily>;
88pub type AssociatedTyDatum = chalk_rust_ir::AssociatedTyDatum<TypeFamily>;
89pub type TraitId = chalk_ir::TraitId<TypeFamily>;
90pub type TraitDatum = chalk_rust_ir::TraitDatum<TypeFamily>;
91pub type StructId = chalk_ir::StructId<TypeFamily>;
92pub type StructDatum = chalk_rust_ir::StructDatum<TypeFamily>;
93pub type ImplId = chalk_ir::ImplId<TypeFamily>;
94pub type ImplDatum = chalk_rust_ir::ImplDatum<TypeFamily>;
95pub type AssociatedTyValueId = chalk_rust_ir::AssociatedTyValueId;
96pub type AssociatedTyValue = chalk_rust_ir::AssociatedTyValue<TypeFamily>;
30 97
31pub(super) trait ToChalk { 98pub(super) trait ToChalk {
32 type Chalk; 99 type Chalk;
@@ -42,21 +109,11 @@ where
42} 109}
43 110
44impl ToChalk for Ty { 111impl ToChalk for Ty {
45 type Chalk = chalk_ir::Ty<ChalkIr>; 112 type Chalk = chalk_ir::Ty<TypeFamily>;
46 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Ty<ChalkIr> { 113 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Ty<TypeFamily> {
47 match self { 114 match self {
48 Ty::Apply(apply_ty) => { 115 Ty::Apply(apply_ty) => {
49 let name = match apply_ty.ctor { 116 let name = apply_ty.ctor.to_chalk(db);
50 TypeCtor::AssociatedType(type_alias) => {
51 let type_id = type_alias.to_chalk(db);
52 TypeName::AssociatedType(type_id)
53 }
54 _ => {
55 // other TypeCtors get interned and turned into a chalk StructId
56 let struct_id = apply_ty.ctor.to_chalk(db);
57 TypeName::TypeKindId(struct_id.into())
58 }
59 };
60 let parameters = apply_ty.parameters.to_chalk(db); 117 let parameters = apply_ty.parameters.to_chalk(db);
61 chalk_ir::ApplicationTy { name, parameters }.cast().intern() 118 chalk_ir::ApplicationTy { name, parameters }.cast().intern()
62 } 119 }
@@ -66,17 +123,30 @@ impl ToChalk for Ty {
66 chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast().intern() 123 chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast().intern()
67 } 124 }
68 Ty::Param { idx, .. } => { 125 Ty::Param { idx, .. } => {
69 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }.to_ty::<ChalkIr>() 126 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }
127 .to_ty::<TypeFamily>()
70 } 128 }
71 Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(), 129 Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(),
72 Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), 130 Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"),
73 Ty::Dyn(predicates) => { 131 Ty::Dyn(predicates) => {
74 let where_clauses = predicates.iter().cloned().map(|p| p.to_chalk(db)).collect(); 132 let where_clauses = predicates
75 chalk_ir::TyData::Dyn(make_binders(where_clauses, 1)).intern() 133 .iter()
134 .filter(|p| !p.is_error())
135 .cloned()
136 .map(|p| p.to_chalk(db))
137 .collect();
138 let bounded_ty = chalk_ir::BoundedTy { bounds: make_binders(where_clauses, 1) };
139 chalk_ir::TyData::Dyn(bounded_ty).intern()
76 } 140 }
77 Ty::Opaque(predicates) => { 141 Ty::Opaque(predicates) => {
78 let where_clauses = predicates.iter().cloned().map(|p| p.to_chalk(db)).collect(); 142 let where_clauses = predicates
79 chalk_ir::TyData::Opaque(make_binders(where_clauses, 1)).intern() 143 .iter()
144 .filter(|p| !p.is_error())
145 .cloned()
146 .map(|p| p.to_chalk(db))
147 .collect();
148 let bounded_ty = chalk_ir::BoundedTy { bounds: make_binders(where_clauses, 1) };
149 chalk_ir::TyData::Opaque(bounded_ty).intern()
80 } 150 }
81 Ty::Unknown => { 151 Ty::Unknown => {
82 let parameters = Vec::new(); 152 let parameters = Vec::new();
@@ -85,30 +155,19 @@ impl ToChalk for Ty {
85 } 155 }
86 } 156 }
87 } 157 }
88 fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty<ChalkIr>) -> Self { 158 fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty<TypeFamily>) -> Self {
89 match chalk.data().clone() { 159 match chalk.data().clone() {
90 chalk_ir::TyData::Apply(apply_ty) => { 160 chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name {
91 // FIXME this is kind of hacky due to the fact that 161 TypeName::Error => Ty::Unknown,
92 // TypeName::Placeholder is a Ty::Param on our side 162 _ => {
93 match apply_ty.name { 163 let ctor = from_chalk(db, apply_ty.name);
94 TypeName::TypeKindId(TypeKindId::StructId(struct_id)) => { 164 let parameters = from_chalk(db, apply_ty.parameters);
95 let ctor = from_chalk(db, struct_id); 165 Ty::Apply(ApplicationTy { ctor, parameters })
96 let parameters = from_chalk(db, apply_ty.parameters);
97 Ty::Apply(ApplicationTy { ctor, parameters })
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 }
104 TypeName::Error => Ty::Unknown,
105 // FIXME handle TypeKindId::Trait/Type here
106 TypeName::TypeKindId(_) => unimplemented!(),
107 TypeName::Placeholder(idx) => {
108 assert_eq!(idx.ui, UniverseIndex::ROOT);
109 Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() }
110 }
111 } 166 }
167 },
168 chalk_ir::TyData::Placeholder(idx) => {
169 assert_eq!(idx.ui, UniverseIndex::ROOT);
170 Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() }
112 } 171 }
113 chalk_ir::TyData::Projection(proj) => { 172 chalk_ir::TyData::Projection(proj) => {
114 let associated_ty = from_chalk(db, proj.associated_ty_id); 173 let associated_ty = from_chalk(db, proj.associated_ty_id);
@@ -119,15 +178,15 @@ impl ToChalk for Ty {
119 chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx as u32), 178 chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx as u32),
120 chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown, 179 chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown,
121 chalk_ir::TyData::Dyn(where_clauses) => { 180 chalk_ir::TyData::Dyn(where_clauses) => {
122 assert_eq!(where_clauses.binders.len(), 1); 181 assert_eq!(where_clauses.bounds.binders.len(), 1);
123 let predicates = 182 let predicates =
124 where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); 183 where_clauses.bounds.value.into_iter().map(|c| from_chalk(db, c)).collect();
125 Ty::Dyn(predicates) 184 Ty::Dyn(predicates)
126 } 185 }
127 chalk_ir::TyData::Opaque(where_clauses) => { 186 chalk_ir::TyData::Opaque(where_clauses) => {
128 assert_eq!(where_clauses.binders.len(), 1); 187 assert_eq!(where_clauses.bounds.binders.len(), 1);
129 let predicates = 188 let predicates =
130 where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); 189 where_clauses.bounds.value.into_iter().map(|c| from_chalk(db, c)).collect();
131 Ty::Opaque(predicates) 190 Ty::Opaque(predicates)
132 } 191 }
133 } 192 }
@@ -135,18 +194,21 @@ impl ToChalk for Ty {
135} 194}
136 195
137impl ToChalk for Substs { 196impl ToChalk for Substs {
138 type Chalk = Vec<chalk_ir::Parameter<ChalkIr>>; 197 type Chalk = Vec<chalk_ir::Parameter<TypeFamily>>;
139 198
140 fn to_chalk(self, db: &impl HirDatabase) -> Vec<Parameter<ChalkIr>> { 199 fn to_chalk(self, db: &impl HirDatabase) -> Vec<Parameter<TypeFamily>> {
141 self.iter().map(|ty| ty.clone().to_chalk(db).cast()).collect() 200 self.iter().map(|ty| ty.clone().to_chalk(db).cast()).collect()
142 } 201 }
143 202
144 fn from_chalk(db: &impl HirDatabase, parameters: Vec<chalk_ir::Parameter<ChalkIr>>) -> Substs { 203 fn from_chalk(
204 db: &impl HirDatabase,
205 parameters: Vec<chalk_ir::Parameter<TypeFamily>>,
206 ) -> Substs {
145 let tys = parameters 207 let tys = parameters
146 .into_iter() 208 .into_iter()
147 .map(|p| match p { 209 .map(|p| match p.ty() {
148 chalk_ir::Parameter(chalk_ir::ParameterKind::Ty(ty)) => from_chalk(db, ty), 210 Some(ty) => from_chalk(db, ty.clone()),
149 chalk_ir::Parameter(chalk_ir::ParameterKind::Lifetime(_)) => unimplemented!(), 211 None => unimplemented!(),
150 }) 212 })
151 .collect(); 213 .collect();
152 Substs(tys) 214 Substs(tys)
@@ -154,88 +216,102 @@ impl ToChalk for Substs {
154} 216}
155 217
156impl ToChalk for TraitRef { 218impl ToChalk for TraitRef {
157 type Chalk = chalk_ir::TraitRef<ChalkIr>; 219 type Chalk = chalk_ir::TraitRef<TypeFamily>;
158 220
159 fn to_chalk(self: TraitRef, db: &impl HirDatabase) -> chalk_ir::TraitRef<ChalkIr> { 221 fn to_chalk(self: TraitRef, db: &impl HirDatabase) -> chalk_ir::TraitRef<TypeFamily> {
160 let trait_id = self.trait_.to_chalk(db); 222 let trait_id = self.trait_.to_chalk(db);
161 let parameters = self.substs.to_chalk(db); 223 let parameters = self.substs.to_chalk(db);
162 chalk_ir::TraitRef { trait_id, parameters } 224 chalk_ir::TraitRef { trait_id, parameters }
163 } 225 }
164 226
165 fn from_chalk(db: &impl HirDatabase, trait_ref: chalk_ir::TraitRef<ChalkIr>) -> Self { 227 fn from_chalk(db: &impl HirDatabase, trait_ref: chalk_ir::TraitRef<TypeFamily>) -> Self {
166 let trait_ = from_chalk(db, trait_ref.trait_id); 228 let trait_ = from_chalk(db, trait_ref.trait_id);
167 let substs = from_chalk(db, trait_ref.parameters); 229 let substs = from_chalk(db, trait_ref.parameters);
168 TraitRef { trait_, substs } 230 TraitRef { trait_, substs }
169 } 231 }
170} 232}
171 233
172impl ToChalk for TraitId { 234impl ToChalk for hir_def::TraitId {
173 type Chalk = chalk_ir::TraitId; 235 type Chalk = TraitId;
174 236
175 fn to_chalk(self, _db: &impl HirDatabase) -> chalk_ir::TraitId { 237 fn to_chalk(self, _db: &impl HirDatabase) -> TraitId {
176 chalk_ir::TraitId(id_to_chalk(self)) 238 chalk_ir::TraitId(self.as_intern_id())
177 } 239 }
178 240
179 fn from_chalk(_db: &impl HirDatabase, trait_id: chalk_ir::TraitId) -> TraitId { 241 fn from_chalk(_db: &impl HirDatabase, trait_id: TraitId) -> hir_def::TraitId {
180 id_from_chalk(trait_id.0) 242 InternKey::from_intern_id(trait_id.0)
181 } 243 }
182} 244}
183 245
184impl ToChalk for TypeCtor { 246impl ToChalk for TypeCtor {
185 type Chalk = chalk_ir::StructId; 247 type Chalk = TypeName<TypeFamily>;
186 248
187 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::StructId { 249 fn to_chalk(self, db: &impl HirDatabase) -> TypeName<TypeFamily> {
188 db.intern_type_ctor(self).into() 250 match self {
251 TypeCtor::AssociatedType(type_alias) => {
252 let type_id = type_alias.to_chalk(db);
253 TypeName::AssociatedType(type_id)
254 }
255 _ => {
256 // other TypeCtors get interned and turned into a chalk StructId
257 let struct_id = db.intern_type_ctor(self).into();
258 TypeName::Struct(struct_id)
259 }
260 }
189 } 261 }
190 262
191 fn from_chalk(db: &impl HirDatabase, struct_id: chalk_ir::StructId) -> TypeCtor { 263 fn from_chalk(db: &impl HirDatabase, type_name: TypeName<TypeFamily>) -> TypeCtor {
192 db.lookup_intern_type_ctor(struct_id.into()) 264 match type_name {
265 TypeName::Struct(struct_id) => db.lookup_intern_type_ctor(struct_id.into()),
266 TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)),
267 TypeName::Error => {
268 // this should not be reached, since we don't represent TypeName::Error with TypeCtor
269 unreachable!()
270 }
271 }
193 } 272 }
194} 273}
195 274
196impl ToChalk for Impl { 275impl ToChalk for Impl {
197 type Chalk = chalk_ir::ImplId; 276 type Chalk = ImplId;
198 277
199 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ImplId { 278 fn to_chalk(self, db: &impl HirDatabase) -> ImplId {
200 db.intern_chalk_impl(self).into() 279 db.intern_chalk_impl(self).into()
201 } 280 }
202 281
203 fn from_chalk(db: &impl HirDatabase, impl_id: chalk_ir::ImplId) -> Impl { 282 fn from_chalk(db: &impl HirDatabase, impl_id: ImplId) -> Impl {
204 db.lookup_intern_chalk_impl(impl_id.into()) 283 db.lookup_intern_chalk_impl(impl_id.into())
205 } 284 }
206} 285}
207 286
208impl ToChalk for TypeAliasId { 287impl ToChalk for TypeAliasId {
209 type Chalk = chalk_ir::TypeId; 288 type Chalk = AssocTypeId;
210 289
211 fn to_chalk(self, _db: &impl HirDatabase) -> chalk_ir::TypeId { 290 fn to_chalk(self, _db: &impl HirDatabase) -> AssocTypeId {
212 chalk_ir::TypeId(id_to_chalk(self)) 291 chalk_ir::AssocTypeId(self.as_intern_id())
213 } 292 }
214 293
215 fn from_chalk(_db: &impl HirDatabase, type_alias_id: chalk_ir::TypeId) -> TypeAliasId { 294 fn from_chalk(_db: &impl HirDatabase, type_alias_id: AssocTypeId) -> TypeAliasId {
216 id_from_chalk(type_alias_id.0) 295 InternKey::from_intern_id(type_alias_id.0)
217 } 296 }
218} 297}
219 298
220impl ToChalk for AssocTyValue { 299impl ToChalk for AssocTyValue {
221 type Chalk = chalk_rust_ir::AssociatedTyValueId; 300 type Chalk = AssociatedTyValueId;
222 301
223 fn to_chalk(self, db: &impl HirDatabase) -> chalk_rust_ir::AssociatedTyValueId { 302 fn to_chalk(self, db: &impl HirDatabase) -> AssociatedTyValueId {
224 db.intern_assoc_ty_value(self).into() 303 db.intern_assoc_ty_value(self).into()
225 } 304 }
226 305
227 fn from_chalk( 306 fn from_chalk(db: &impl HirDatabase, assoc_ty_value_id: AssociatedTyValueId) -> AssocTyValue {
228 db: &impl HirDatabase,
229 assoc_ty_value_id: chalk_rust_ir::AssociatedTyValueId,
230 ) -> AssocTyValue {
231 db.lookup_intern_assoc_ty_value(assoc_ty_value_id.into()) 307 db.lookup_intern_assoc_ty_value(assoc_ty_value_id.into())
232 } 308 }
233} 309}
234 310
235impl ToChalk for GenericPredicate { 311impl ToChalk for GenericPredicate {
236 type Chalk = chalk_ir::QuantifiedWhereClause<ChalkIr>; 312 type Chalk = chalk_ir::QuantifiedWhereClause<TypeFamily>;
237 313
238 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::QuantifiedWhereClause<ChalkIr> { 314 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::QuantifiedWhereClause<TypeFamily> {
239 match self { 315 match self {
240 GenericPredicate::Implemented(trait_ref) => { 316 GenericPredicate::Implemented(trait_ref) => {
241 make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0) 317 make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0)
@@ -247,26 +323,16 @@ impl ToChalk for GenericPredicate {
247 }), 323 }),
248 0, 324 0,
249 ), 325 ),
250 GenericPredicate::Error => { 326 GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"),
251 let impossible_trait_ref = chalk_ir::TraitRef {
252 trait_id: UNKNOWN_TRAIT,
253 parameters: vec![Ty::Unknown.to_chalk(db).cast()],
254 };
255 make_binders(chalk_ir::WhereClause::Implemented(impossible_trait_ref), 0)
256 }
257 } 327 }
258 } 328 }
259 329
260 fn from_chalk( 330 fn from_chalk(
261 db: &impl HirDatabase, 331 db: &impl HirDatabase,
262 where_clause: chalk_ir::QuantifiedWhereClause<ChalkIr>, 332 where_clause: chalk_ir::QuantifiedWhereClause<TypeFamily>,
263 ) -> GenericPredicate { 333 ) -> GenericPredicate {
264 match where_clause.value { 334 match where_clause.value {
265 chalk_ir::WhereClause::Implemented(tr) => { 335 chalk_ir::WhereClause::Implemented(tr) => {
266 if tr.trait_id == UNKNOWN_TRAIT {
267 // FIXME we need an Error enum on the Chalk side to avoid this
268 return GenericPredicate::Error;
269 }
270 GenericPredicate::Implemented(from_chalk(db, tr)) 336 GenericPredicate::Implemented(from_chalk(db, tr))
271 } 337 }
272 chalk_ir::WhereClause::ProjectionEq(projection_eq) => { 338 chalk_ir::WhereClause::ProjectionEq(projection_eq) => {
@@ -279,9 +345,9 @@ impl ToChalk for GenericPredicate {
279} 345}
280 346
281impl ToChalk for ProjectionTy { 347impl ToChalk for ProjectionTy {
282 type Chalk = chalk_ir::ProjectionTy<ChalkIr>; 348 type Chalk = chalk_ir::ProjectionTy<TypeFamily>;
283 349
284 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ProjectionTy<ChalkIr> { 350 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ProjectionTy<TypeFamily> {
285 chalk_ir::ProjectionTy { 351 chalk_ir::ProjectionTy {
286 associated_ty_id: self.associated_ty.to_chalk(db), 352 associated_ty_id: self.associated_ty.to_chalk(db),
287 parameters: self.parameters.to_chalk(db), 353 parameters: self.parameters.to_chalk(db),
@@ -290,7 +356,7 @@ impl ToChalk for ProjectionTy {
290 356
291 fn from_chalk( 357 fn from_chalk(
292 db: &impl HirDatabase, 358 db: &impl HirDatabase,
293 projection_ty: chalk_ir::ProjectionTy<ChalkIr>, 359 projection_ty: chalk_ir::ProjectionTy<TypeFamily>,
294 ) -> ProjectionTy { 360 ) -> ProjectionTy {
295 ProjectionTy { 361 ProjectionTy {
296 associated_ty: from_chalk(db, projection_ty.associated_ty_id), 362 associated_ty: from_chalk(db, projection_ty.associated_ty_id),
@@ -300,31 +366,31 @@ impl ToChalk for ProjectionTy {
300} 366}
301 367
302impl ToChalk for super::ProjectionPredicate { 368impl ToChalk for super::ProjectionPredicate {
303 type Chalk = chalk_ir::Normalize<ChalkIr>; 369 type Chalk = chalk_ir::Normalize<TypeFamily>;
304 370
305 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Normalize<ChalkIr> { 371 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Normalize<TypeFamily> {
306 chalk_ir::Normalize { 372 chalk_ir::Normalize {
307 projection: self.projection_ty.to_chalk(db), 373 projection: self.projection_ty.to_chalk(db),
308 ty: self.ty.to_chalk(db), 374 ty: self.ty.to_chalk(db),
309 } 375 }
310 } 376 }
311 377
312 fn from_chalk(_db: &impl HirDatabase, _normalize: chalk_ir::Normalize<ChalkIr>) -> Self { 378 fn from_chalk(_db: &impl HirDatabase, _normalize: chalk_ir::Normalize<TypeFamily>) -> Self {
313 unimplemented!() 379 unimplemented!()
314 } 380 }
315} 381}
316 382
317impl ToChalk for Obligation { 383impl ToChalk for Obligation {
318 type Chalk = chalk_ir::DomainGoal<ChalkIr>; 384 type Chalk = chalk_ir::DomainGoal<TypeFamily>;
319 385
320 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::DomainGoal<ChalkIr> { 386 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::DomainGoal<TypeFamily> {
321 match self { 387 match self {
322 Obligation::Trait(tr) => tr.to_chalk(db).cast(), 388 Obligation::Trait(tr) => tr.to_chalk(db).cast(),
323 Obligation::Projection(pr) => pr.to_chalk(db).cast(), 389 Obligation::Projection(pr) => pr.to_chalk(db).cast(),
324 } 390 }
325 } 391 }
326 392
327 fn from_chalk(_db: &impl HirDatabase, _goal: chalk_ir::DomainGoal<ChalkIr>) -> Self { 393 fn from_chalk(_db: &impl HirDatabase, _goal: chalk_ir::DomainGoal<TypeFamily>) -> Self {
328 unimplemented!() 394 unimplemented!()
329 } 395 }
330} 396}
@@ -348,16 +414,17 @@ where
348} 414}
349 415
350impl ToChalk for Arc<super::TraitEnvironment> { 416impl ToChalk for Arc<super::TraitEnvironment> {
351 type Chalk = chalk_ir::Environment<ChalkIr>; 417 type Chalk = chalk_ir::Environment<TypeFamily>;
352 418
353 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Environment<ChalkIr> { 419 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Environment<TypeFamily> {
354 let mut clauses = Vec::new(); 420 let mut clauses = Vec::new();
355 for pred in &self.predicates { 421 for pred in &self.predicates {
356 if pred.is_error() { 422 if pred.is_error() {
357 // for env, we just ignore errors 423 // for env, we just ignore errors
358 continue; 424 continue;
359 } 425 }
360 let program_clause: chalk_ir::ProgramClause<ChalkIr> = pred.clone().to_chalk(db).cast(); 426 let program_clause: chalk_ir::ProgramClause<TypeFamily> =
427 pred.clone().to_chalk(db).cast();
361 clauses.push(program_clause.into_from_env_clause()); 428 clauses.push(program_clause.into_from_env_clause());
362 } 429 }
363 chalk_ir::Environment::new().add_clauses(clauses) 430 chalk_ir::Environment::new().add_clauses(clauses)
@@ -365,7 +432,7 @@ impl ToChalk for Arc<super::TraitEnvironment> {
365 432
366 fn from_chalk( 433 fn from_chalk(
367 _db: &impl HirDatabase, 434 _db: &impl HirDatabase,
368 _env: chalk_ir::Environment<ChalkIr>, 435 _env: chalk_ir::Environment<TypeFamily>,
369 ) -> Arc<super::TraitEnvironment> { 436 ) -> Arc<super::TraitEnvironment> {
370 unimplemented!() 437 unimplemented!()
371 } 438 }
@@ -373,7 +440,7 @@ impl ToChalk for Arc<super::TraitEnvironment> {
373 440
374impl<T: ToChalk> ToChalk for super::InEnvironment<T> 441impl<T: ToChalk> ToChalk for super::InEnvironment<T>
375where 442where
376 T::Chalk: chalk_ir::family::HasTypeFamily<TypeFamily = ChalkIr>, 443 T::Chalk: chalk_ir::family::HasTypeFamily<TypeFamily = TypeFamily>,
377{ 444{
378 type Chalk = chalk_ir::InEnvironment<T::Chalk>; 445 type Chalk = chalk_ir::InEnvironment<T::Chalk>;
379 446
@@ -395,6 +462,51 @@ where
395 } 462 }
396} 463}
397 464
465impl ToChalk for builtin::BuiltinImplData {
466 type Chalk = ImplDatum;
467
468 fn to_chalk(self, db: &impl HirDatabase) -> ImplDatum {
469 let impl_type = chalk_rust_ir::ImplType::External;
470 let where_clauses = self.where_clauses.into_iter().map(|w| w.to_chalk(db)).collect();
471
472 let impl_datum_bound =
473 chalk_rust_ir::ImplDatumBound { trait_ref: self.trait_ref.to_chalk(db), where_clauses };
474 let associated_ty_value_ids =
475 self.assoc_ty_values.into_iter().map(|v| v.to_chalk(db)).collect();
476 chalk_rust_ir::ImplDatum {
477 binders: make_binders(impl_datum_bound, self.num_vars),
478 impl_type,
479 polarity: chalk_rust_ir::Polarity::Positive,
480 associated_ty_value_ids,
481 }
482 }
483
484 fn from_chalk(_db: &impl HirDatabase, _data: ImplDatum) -> Self {
485 unimplemented!()
486 }
487}
488
489impl ToChalk for builtin::BuiltinImplAssocTyValueData {
490 type Chalk = AssociatedTyValue;
491
492 fn to_chalk(self, db: &impl HirDatabase) -> AssociatedTyValue {
493 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: self.value.to_chalk(db) };
494
495 chalk_rust_ir::AssociatedTyValue {
496 associated_ty_id: self.assoc_ty_id.to_chalk(db),
497 impl_id: self.impl_.to_chalk(db),
498 value: make_binders(value_bound, self.num_vars),
499 }
500 }
501
502 fn from_chalk(
503 _db: &impl HirDatabase,
504 _data: AssociatedTyValue,
505 ) -> builtin::BuiltinImplAssocTyValueData {
506 unimplemented!()
507 }
508}
509
398fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> { 510fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> {
399 chalk_ir::Binders { 511 chalk_ir::Binders {
400 value, 512 value,
@@ -406,46 +518,46 @@ fn convert_where_clauses(
406 db: &impl HirDatabase, 518 db: &impl HirDatabase,
407 def: GenericDefId, 519 def: GenericDefId,
408 substs: &Substs, 520 substs: &Substs,
409) -> Vec<chalk_ir::QuantifiedWhereClause<ChalkIr>> { 521) -> Vec<chalk_ir::QuantifiedWhereClause<TypeFamily>> {
410 let generic_predicates = db.generic_predicates(def); 522 let generic_predicates = db.generic_predicates(def);
411 let mut result = Vec::with_capacity(generic_predicates.len()); 523 let mut result = Vec::with_capacity(generic_predicates.len());
412 for pred in generic_predicates.iter() { 524 for pred in generic_predicates.iter() {
413 if pred.is_error() { 525 if pred.is_error() {
414 // HACK: Return just the single predicate (which is always false 526 // skip errored predicates completely
415 // anyway), otherwise Chalk can easily get into slow situations 527 continue;
416 return vec![pred.clone().subst(substs).to_chalk(db)];
417 } 528 }
418 result.push(pred.clone().subst(substs).to_chalk(db)); 529 result.push(pred.clone().subst(substs).to_chalk(db));
419 } 530 }
420 result 531 result
421} 532}
422 533
423impl<'a, DB> chalk_solve::RustIrDatabase<ChalkIr> for ChalkContext<'a, DB> 534impl<'a, DB> chalk_solve::RustIrDatabase<TypeFamily> for ChalkContext<'a, DB>
424where 535where
425 DB: HirDatabase, 536 DB: HirDatabase,
426{ 537{
427 fn associated_ty_data(&self, id: TypeId) -> Arc<AssociatedTyDatum<ChalkIr>> { 538 fn associated_ty_data(&self, id: AssocTypeId) -> Arc<AssociatedTyDatum> {
428 self.db.associated_ty_data(id) 539 self.db.associated_ty_data(id)
429 } 540 }
430 fn trait_datum(&self, trait_id: chalk_ir::TraitId) -> Arc<TraitDatum<ChalkIr>> { 541 fn trait_datum(&self, trait_id: TraitId) -> Arc<TraitDatum> {
431 self.db.trait_datum(self.krate, trait_id) 542 self.db.trait_datum(self.krate, trait_id)
432 } 543 }
433 fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc<StructDatum<ChalkIr>> { 544 fn struct_datum(&self, struct_id: StructId) -> Arc<StructDatum> {
434 self.db.struct_datum(self.krate, struct_id) 545 self.db.struct_datum(self.krate, struct_id)
435 } 546 }
436 fn impl_datum(&self, impl_id: chalk_ir::ImplId) -> Arc<ImplDatum<ChalkIr>> { 547 fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> {
437 self.db.impl_datum(self.krate, impl_id) 548 self.db.impl_datum(self.krate, impl_id)
438 } 549 }
439 fn impls_for_trait( 550 fn impls_for_trait(
440 &self, 551 &self,
441 trait_id: chalk_ir::TraitId, 552 trait_id: TraitId,
442 parameters: &[Parameter<ChalkIr>], 553 parameters: &[Parameter<TypeFamily>],
443 ) -> Vec<chalk_ir::ImplId> { 554 ) -> Vec<ImplId> {
444 debug!("impls_for_trait {:?}", trait_id); 555 debug!("impls_for_trait {:?}", trait_id);
445 if trait_id == UNKNOWN_TRAIT { 556 let trait_: hir_def::TraitId = from_chalk(self.db, trait_id);
446 return Vec::new(); 557
447 } 558 // Note: Since we're using impls_for_trait, only impls where the trait
448 let trait_: TraitId = from_chalk(self.db, trait_id); 559 // can be resolved should ever reach Chalk. `impl_datum` relies on that
560 // and will panic if the trait can't be resolved.
449 let mut result: Vec<_> = self 561 let mut result: Vec<_> = self
450 .db 562 .db
451 .impls_for_trait(self.krate, trait_.into()) 563 .impls_for_trait(self.krate, trait_.into())
@@ -456,62 +568,47 @@ where
456 .collect(); 568 .collect();
457 569
458 let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref().clone()); 570 let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref().clone());
459 if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { def, expr }, .. }) = ty { 571
460 for &fn_trait in 572 builtin::get_builtin_impls(self.db, self.krate, &ty, trait_, |i| {
461 [super::FnTrait::FnOnce, super::FnTrait::FnMut, super::FnTrait::Fn].iter() 573 result.push(i.to_chalk(self.db))
462 { 574 });
463 if let Some(actual_trait) = get_fn_trait(self.db, self.krate, fn_trait) {
464 if trait_ == actual_trait {
465 let impl_ = super::ClosureFnTraitImplData { def, expr, fn_trait };
466 result.push(Impl::ClosureFnTraitImpl(impl_).to_chalk(self.db));
467 }
468 }
469 }
470 }
471 575
472 debug!("impls_for_trait returned {} impls", result.len()); 576 debug!("impls_for_trait returned {} impls", result.len());
473 result 577 result
474 } 578 }
475 fn impl_provided_for( 579 fn impl_provided_for(&self, auto_trait_id: TraitId, struct_id: StructId) -> bool {
476 &self,
477 auto_trait_id: chalk_ir::TraitId,
478 struct_id: chalk_ir::StructId,
479 ) -> bool {
480 debug!("impl_provided_for {:?}, {:?}", auto_trait_id, struct_id); 580 debug!("impl_provided_for {:?}, {:?}", auto_trait_id, struct_id);
481 false // FIXME 581 false // FIXME
482 } 582 }
483 fn type_name(&self, _id: TypeKindId) -> Identifier { 583 fn associated_ty_value(&self, id: AssociatedTyValueId) -> Arc<AssociatedTyValue> {
484 unimplemented!()
485 }
486 fn associated_ty_value(
487 &self,
488 id: chalk_rust_ir::AssociatedTyValueId,
489 ) -> Arc<AssociatedTyValue<ChalkIr>> {
490 self.db.associated_ty_value(self.krate.into(), id) 584 self.db.associated_ty_value(self.krate.into(), id)
491 } 585 }
492 fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<ChalkIr>> { 586 fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<TypeFamily>> {
493 vec![] 587 vec![]
494 } 588 }
495 fn local_impls_to_coherence_check( 589 fn local_impls_to_coherence_check(&self, _trait_id: TraitId) -> Vec<ImplId> {
496 &self,
497 _trait_id: chalk_ir::TraitId,
498 ) -> Vec<chalk_ir::ImplId> {
499 // We don't do coherence checking (yet) 590 // We don't do coherence checking (yet)
500 unimplemented!() 591 unimplemented!()
501 } 592 }
593 fn as_struct_id(&self, id: &TypeName<TypeFamily>) -> Option<StructId> {
594 match id {
595 TypeName::Struct(struct_id) => Some(*struct_id),
596 _ => None,
597 }
598 }
502} 599}
503 600
504pub(crate) fn associated_ty_data_query( 601pub(crate) fn associated_ty_data_query(
505 db: &impl HirDatabase, 602 db: &impl HirDatabase,
506 id: TypeId, 603 id: AssocTypeId,
507) -> Arc<AssociatedTyDatum<ChalkIr>> { 604) -> Arc<AssociatedTyDatum> {
508 debug!("associated_ty_data {:?}", id); 605 debug!("associated_ty_data {:?}", id);
509 let type_alias: TypeAliasId = from_chalk(db, id); 606 let type_alias: TypeAliasId = from_chalk(db, id);
510 let trait_ = match type_alias.lookup(db).container { 607 let trait_ = match type_alias.lookup(db).container {
511 ContainerId::TraitId(t) => t, 608 AssocContainerId::TraitId(t) => t,
512 _ => panic!("associated type not in trait"), 609 _ => panic!("associated type not in trait"),
513 }; 610 };
514 let generic_params = db.generic_params(type_alias.into()); 611 let generic_params = generics(db, type_alias.into());
515 let bound_data = chalk_rust_ir::AssociatedTyDatumBound { 612 let bound_data = chalk_rust_ir::AssociatedTyDatumBound {
516 // FIXME add bounds and where clauses 613 // FIXME add bounds and where clauses
517 bounds: vec![], 614 bounds: vec![],
@@ -521,7 +618,7 @@ pub(crate) fn associated_ty_data_query(
521 trait_id: trait_.to_chalk(db), 618 trait_id: trait_.to_chalk(db),
522 id, 619 id,
523 name: lalrpop_intern::intern(&db.type_alias_data(type_alias).name.to_string()), 620 name: lalrpop_intern::intern(&db.type_alias_data(type_alias).name.to_string()),
524 binders: make_binders(bound_data, generic_params.count_params_including_parent()), 621 binders: make_binders(bound_data, generic_params.len()),
525 }; 622 };
526 Arc::new(datum) 623 Arc::new(datum)
527} 624}
@@ -529,35 +626,17 @@ pub(crate) fn associated_ty_data_query(
529pub(crate) fn trait_datum_query( 626pub(crate) fn trait_datum_query(
530 db: &impl HirDatabase, 627 db: &impl HirDatabase,
531 krate: CrateId, 628 krate: CrateId,
532 trait_id: chalk_ir::TraitId, 629 trait_id: TraitId,
533) -> Arc<TraitDatum<ChalkIr>> { 630) -> Arc<TraitDatum> {
534 debug!("trait_datum {:?}", trait_id); 631 debug!("trait_datum {:?}", trait_id);
535 if trait_id == UNKNOWN_TRAIT { 632 let trait_: hir_def::TraitId = from_chalk(db, trait_id);
536 let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses: Vec::new() };
537
538 let flags = chalk_rust_ir::TraitFlags {
539 auto: false,
540 marker: false,
541 upstream: true,
542 fundamental: false,
543 non_enumerable: true,
544 coinductive: false,
545 };
546 return Arc::new(TraitDatum {
547 id: trait_id,
548 binders: make_binders(trait_datum_bound, 1),
549 flags,
550 associated_ty_ids: vec![],
551 });
552 }
553 let trait_: TraitId = from_chalk(db, trait_id);
554 let trait_data = db.trait_data(trait_); 633 let trait_data = db.trait_data(trait_);
555 debug!("trait {:?} = {:?}", trait_id, trait_data.name); 634 debug!("trait {:?} = {:?}", trait_id, trait_data.name);
556 let generic_params = db.generic_params(trait_.into()); 635 let generic_params = generics(db, trait_.into());
557 let bound_vars = Substs::bound_vars(&generic_params); 636 let bound_vars = Substs::bound_vars(&generic_params);
558 let flags = chalk_rust_ir::TraitFlags { 637 let flags = chalk_rust_ir::TraitFlags {
559 auto: trait_data.auto, 638 auto: trait_data.auto,
560 upstream: trait_.module(db).krate != krate, 639 upstream: trait_.lookup(db).container.module(db).krate != krate,
561 non_enumerable: true, 640 non_enumerable: true,
562 coinductive: false, // only relevant for Chalk testing 641 coinductive: false, // only relevant for Chalk testing
563 // FIXME set these flags correctly 642 // FIXME set these flags correctly
@@ -580,17 +659,17 @@ pub(crate) fn trait_datum_query(
580pub(crate) fn struct_datum_query( 659pub(crate) fn struct_datum_query(
581 db: &impl HirDatabase, 660 db: &impl HirDatabase,
582 krate: CrateId, 661 krate: CrateId,
583 struct_id: chalk_ir::StructId, 662 struct_id: StructId,
584) -> Arc<StructDatum<ChalkIr>> { 663) -> Arc<StructDatum> {
585 debug!("struct_datum {:?}", struct_id); 664 debug!("struct_datum {:?}", struct_id);
586 let type_ctor: TypeCtor = from_chalk(db, struct_id); 665 let type_ctor: TypeCtor = from_chalk(db, TypeName::Struct(struct_id));
587 debug!("struct {:?} = {:?}", struct_id, type_ctor); 666 debug!("struct {:?} = {:?}", struct_id, type_ctor);
588 let num_params = type_ctor.num_ty_params(db); 667 let num_params = type_ctor.num_ty_params(db);
589 let upstream = type_ctor.krate(db) != Some(krate); 668 let upstream = type_ctor.krate(db) != Some(krate);
590 let where_clauses = type_ctor 669 let where_clauses = type_ctor
591 .as_generic_def() 670 .as_generic_def()
592 .map(|generic_def| { 671 .map(|generic_def| {
593 let generic_params = db.generic_params(generic_def.into()); 672 let generic_params = generics(db, generic_def.into());
594 let bound_vars = Substs::bound_vars(&generic_params); 673 let bound_vars = Substs::bound_vars(&generic_params);
595 convert_where_clauses(db, generic_def, &bound_vars) 674 convert_where_clauses(db, generic_def, &bound_vars)
596 }) 675 })
@@ -612,35 +691,34 @@ pub(crate) fn struct_datum_query(
612pub(crate) fn impl_datum_query( 691pub(crate) fn impl_datum_query(
613 db: &impl HirDatabase, 692 db: &impl HirDatabase,
614 krate: CrateId, 693 krate: CrateId,
615 impl_id: chalk_ir::ImplId, 694 impl_id: ImplId,
616) -> Arc<ImplDatum<ChalkIr>> { 695) -> Arc<ImplDatum> {
617 let _p = ra_prof::profile("impl_datum"); 696 let _p = ra_prof::profile("impl_datum");
618 debug!("impl_datum {:?}", impl_id); 697 debug!("impl_datum {:?}", impl_id);
619 let impl_: Impl = from_chalk(db, impl_id); 698 let impl_: Impl = from_chalk(db, impl_id);
620 match impl_ { 699 match impl_ {
621 Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block), 700 Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block),
622 Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data), 701 _ => Arc::new(builtin::impl_datum(db, krate, impl_).to_chalk(db)),
623 } 702 }
624 .unwrap_or_else(invalid_impl_datum)
625} 703}
626 704
627fn impl_block_datum( 705fn impl_block_datum(
628 db: &impl HirDatabase, 706 db: &impl HirDatabase,
629 krate: CrateId, 707 krate: CrateId,
630 chalk_id: chalk_ir::ImplId, 708 chalk_id: ImplId,
631 impl_id: ImplId, 709 impl_id: hir_def::ImplId,
632) -> Option<Arc<ImplDatum<ChalkIr>>> { 710) -> Arc<ImplDatum> {
633 let trait_ref = match db.impl_ty(impl_id) { 711 let trait_ref = db
634 ImplTy::TraitRef(it) => it, 712 .impl_trait(impl_id)
635 ImplTy::Inherent(_) => return None, 713 // ImplIds for impls where the trait ref can't be resolved should never reach Chalk
636 }; 714 .expect("invalid impl passed to Chalk");
637 let impl_data = db.impl_data(impl_id); 715 let impl_data = db.impl_data(impl_id);
638 716
639 let generic_params = db.generic_params(impl_id.into()); 717 let generic_params = generics(db, impl_id.into());
640 let bound_vars = Substs::bound_vars(&generic_params); 718 let bound_vars = Substs::bound_vars(&generic_params);
641 let trait_ref = trait_ref.subst(&bound_vars); 719 let trait_ref = trait_ref.subst(&bound_vars);
642 let trait_ = trait_ref.trait_; 720 let trait_ = trait_ref.trait_;
643 let impl_type = if impl_id.module(db).krate == krate { 721 let impl_type = if impl_id.lookup(db).container.module(db).krate == krate {
644 chalk_rust_ir::ImplType::Local 722 chalk_rust_ir::ImplType::Local
645 } else { 723 } else {
646 chalk_rust_ir::ImplType::External 724 chalk_rust_ir::ImplType::External
@@ -685,94 +763,20 @@ fn impl_block_datum(
685 polarity, 763 polarity,
686 associated_ty_value_ids, 764 associated_ty_value_ids,
687 }; 765 };
688 Some(Arc::new(impl_datum))
689}
690
691fn invalid_impl_datum() -> Arc<ImplDatum<ChalkIr>> {
692 let trait_ref = chalk_ir::TraitRef {
693 trait_id: UNKNOWN_TRAIT,
694 parameters: vec![chalk_ir::TyData::BoundVar(0).cast().intern().cast()],
695 };
696 let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses: Vec::new() };
697 let impl_datum = ImplDatum {
698 binders: make_binders(impl_datum_bound, 1),
699 impl_type: chalk_rust_ir::ImplType::External,
700 polarity: chalk_rust_ir::Polarity::Positive,
701 associated_ty_value_ids: Vec::new(),
702 };
703 Arc::new(impl_datum) 766 Arc::new(impl_datum)
704} 767}
705 768
706fn closure_fn_trait_impl_datum(
707 db: &impl HirDatabase,
708 krate: CrateId,
709 data: super::ClosureFnTraitImplData,
710) -> Option<Arc<ImplDatum<ChalkIr>>> {
711 // for some closure |X, Y| -> Z:
712 // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V }
713
714 let trait_ = get_fn_trait(db, krate, data.fn_trait)?; // get corresponding fn trait
715
716 // validate FnOnce trait, since we need it in the assoc ty value definition
717 // and don't want to return a valid value only to find out later that FnOnce
718 // is broken
719 let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?;
720 let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name::OUTPUT_TYPE)?;
721
722 let num_args: u16 = match &db.body(data.def.into())[data.expr] {
723 Expr::Lambda { args, .. } => args.len() as u16,
724 _ => {
725 log::warn!("closure for closure type {:?} not found", data);
726 0
727 }
728 };
729
730 let arg_ty = Ty::apply(
731 TypeCtor::Tuple { cardinality: num_args },
732 Substs::builder(num_args as usize).fill_with_bound_vars(0).build(),
733 );
734 let sig_ty = Ty::apply(
735 TypeCtor::FnPtr { num_args },
736 Substs::builder(num_args as usize + 1).fill_with_bound_vars(0).build(),
737 );
738
739 let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty);
740
741 let trait_ref = TraitRef {
742 trait_: trait_.into(),
743 substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(),
744 };
745
746 let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone()).to_chalk(db);
747
748 let impl_type = chalk_rust_ir::ImplType::External;
749
750 let impl_datum_bound = chalk_rust_ir::ImplDatumBound {
751 trait_ref: trait_ref.to_chalk(db),
752 where_clauses: Vec::new(),
753 };
754 let impl_datum = ImplDatum {
755 binders: make_binders(impl_datum_bound, num_args as usize + 1),
756 impl_type,
757 polarity: chalk_rust_ir::Polarity::Positive,
758 associated_ty_value_ids: vec![output_ty_id],
759 };
760 Some(Arc::new(impl_datum))
761}
762
763pub(crate) fn associated_ty_value_query( 769pub(crate) fn associated_ty_value_query(
764 db: &impl HirDatabase, 770 db: &impl HirDatabase,
765 krate: CrateId, 771 krate: CrateId,
766 id: chalk_rust_ir::AssociatedTyValueId, 772 id: AssociatedTyValueId,
767) -> Arc<chalk_rust_ir::AssociatedTyValue<ChalkIr>> { 773) -> Arc<AssociatedTyValue> {
768 let data: AssocTyValue = from_chalk(db, id); 774 let data: AssocTyValue = from_chalk(db, id);
769 match data { 775 match data {
770 AssocTyValue::TypeAlias(type_alias) => { 776 AssocTyValue::TypeAlias(type_alias) => {
771 type_alias_associated_ty_value(db, krate, type_alias) 777 type_alias_associated_ty_value(db, krate, type_alias)
772 } 778 }
773 AssocTyValue::ClosureFnTraitImplOutput(data) => { 779 _ => Arc::new(builtin::associated_ty_value(db, krate, data).to_chalk(db)),
774 closure_fn_trait_output_assoc_ty_value(db, krate, data)
775 }
776 } 780 }
777} 781}
778 782
@@ -780,24 +784,20 @@ fn type_alias_associated_ty_value(
780 db: &impl HirDatabase, 784 db: &impl HirDatabase,
781 _krate: CrateId, 785 _krate: CrateId,
782 type_alias: TypeAliasId, 786 type_alias: TypeAliasId,
783) -> Arc<AssociatedTyValue<ChalkIr>> { 787) -> Arc<AssociatedTyValue> {
784 let type_alias_data = db.type_alias_data(type_alias); 788 let type_alias_data = db.type_alias_data(type_alias);
785 let impl_id = match type_alias.lookup(db).container { 789 let impl_id = match type_alias.lookup(db).container {
786 ContainerId::ImplId(it) => it, 790 AssocContainerId::ImplId(it) => it,
787 _ => panic!("assoc ty value should be in impl"), 791 _ => panic!("assoc ty value should be in impl"),
788 }; 792 };
789 793
790 let trait_ref = match db.impl_ty(impl_id) { 794 let trait_ref = db.impl_trait(impl_id).expect("assoc ty value should not exist"); // we don't return any assoc ty values if the impl'd trait can't be resolved
791 ImplTy::TraitRef(it) => it,
792 // we don't return any assoc ty values if the impl'd trait can't be resolved
793 ImplTy::Inherent(_) => panic!("assoc ty value should not exist"),
794 };
795 795
796 let assoc_ty = db 796 let assoc_ty = db
797 .trait_data(trait_ref.trait_) 797 .trait_data(trait_ref.trait_)
798 .associated_type_by_name(&type_alias_data.name) 798 .associated_type_by_name(&type_alias_data.name)
799 .expect("assoc ty value should not exist"); // validated when building the impl data as well 799 .expect("assoc ty value should not exist"); // validated when building the impl data as well
800 let generic_params = db.generic_params(impl_id.into()); 800 let generic_params = generics(db, impl_id.into());
801 let bound_vars = Substs::bound_vars(&generic_params); 801 let bound_vars = Substs::bound_vars(&generic_params);
802 let ty = db.ty(type_alias.into()).subst(&bound_vars); 802 let ty = db.ty(type_alias.into()).subst(&bound_vars);
803 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) }; 803 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) };
@@ -809,53 +809,6 @@ fn type_alias_associated_ty_value(
809 Arc::new(value) 809 Arc::new(value)
810} 810}
811 811
812fn closure_fn_trait_output_assoc_ty_value(
813 db: &impl HirDatabase,
814 krate: CrateId,
815 data: super::ClosureFnTraitImplData,
816) -> Arc<AssociatedTyValue<ChalkIr>> {
817 let impl_id = Impl::ClosureFnTraitImpl(data.clone()).to_chalk(db);
818
819 let num_args: u16 = match &db.body(data.def.into())[data.expr] {
820 Expr::Lambda { args, .. } => args.len() as u16,
821 _ => {
822 log::warn!("closure for closure type {:?} not found", data);
823 0
824 }
825 };
826
827 let output_ty = Ty::Bound(num_args.into());
828
829 let fn_once_trait =
830 get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist");
831
832 let output_ty_id = db
833 .trait_data(fn_once_trait)
834 .associated_type_by_name(&name::OUTPUT_TYPE)
835 .expect("assoc ty value should not exist");
836
837 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: output_ty.to_chalk(db) };
838
839 let value = chalk_rust_ir::AssociatedTyValue {
840 associated_ty_id: output_ty_id.to_chalk(db),
841 impl_id,
842 value: make_binders(value_bound, num_args as usize + 1),
843 };
844 Arc::new(value)
845}
846
847fn get_fn_trait(
848 db: &impl HirDatabase,
849 krate: CrateId,
850 fn_trait: super::FnTrait,
851) -> Option<TraitId> {
852 let target = db.lang_item(krate, fn_trait.lang_item_name().into())?;
853 match target {
854 LangItemTarget::TraitId(t) => Some(t),
855 _ => None,
856 }
857}
858
859fn id_from_chalk<T: InternKey>(chalk_id: chalk_ir::RawId) -> T { 812fn id_from_chalk<T: InternKey>(chalk_id: chalk_ir::RawId) -> T {
860 T::from_intern_id(InternId::from(chalk_id.index)) 813 T::from_intern_id(InternId::from(chalk_id.index))
861} 814}
@@ -863,27 +816,27 @@ fn id_to_chalk<T: InternKey>(salsa_id: T) -> chalk_ir::RawId {
863 chalk_ir::RawId { index: salsa_id.as_intern_id().as_u32() } 816 chalk_ir::RawId { index: salsa_id.as_intern_id().as_u32() }
864} 817}
865 818
866impl From<chalk_ir::StructId> for crate::TypeCtorId { 819impl From<StructId> for crate::TypeCtorId {
867 fn from(struct_id: chalk_ir::StructId) -> Self { 820 fn from(struct_id: StructId) -> Self {
868 id_from_chalk(struct_id.0) 821 InternKey::from_intern_id(struct_id.0)
869 } 822 }
870} 823}
871 824
872impl From<crate::TypeCtorId> for chalk_ir::StructId { 825impl From<crate::TypeCtorId> for StructId {
873 fn from(type_ctor_id: crate::TypeCtorId) -> Self { 826 fn from(type_ctor_id: crate::TypeCtorId) -> Self {
874 chalk_ir::StructId(id_to_chalk(type_ctor_id)) 827 chalk_ir::StructId(type_ctor_id.as_intern_id())
875 } 828 }
876} 829}
877 830
878impl From<chalk_ir::ImplId> for crate::traits::GlobalImplId { 831impl From<ImplId> for crate::traits::GlobalImplId {
879 fn from(impl_id: chalk_ir::ImplId) -> Self { 832 fn from(impl_id: ImplId) -> Self {
880 id_from_chalk(impl_id.0) 833 InternKey::from_intern_id(impl_id.0)
881 } 834 }
882} 835}
883 836
884impl From<crate::traits::GlobalImplId> for chalk_ir::ImplId { 837impl From<crate::traits::GlobalImplId> for ImplId {
885 fn from(impl_id: crate::traits::GlobalImplId) -> Self { 838 fn from(impl_id: crate::traits::GlobalImplId) -> Self {
886 chalk_ir::ImplId(id_to_chalk(impl_id)) 839 chalk_ir::ImplId(impl_id.as_intern_id())
887 } 840 }
888} 841}
889 842
diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs
index e4ba890ef..0b1806a84 100644
--- a/crates/ra_hir_ty/src/utils.rs
+++ b/crates/ra_hir_ty/src/utils.rs
@@ -5,14 +5,14 @@ use std::sync::Arc;
5use hir_def::{ 5use hir_def::{
6 adt::VariantData, 6 adt::VariantData,
7 db::DefDatabase, 7 db::DefDatabase,
8 generics::{GenericParams, TypeParamData},
9 path::Path,
8 resolver::{HasResolver, TypeNs}, 10 resolver::{HasResolver, TypeNs},
9 type_ref::TypeRef, 11 type_ref::TypeRef,
10 TraitId, TypeAliasId, VariantId, 12 AssocContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId, VariantId,
11}; 13};
12use hir_expand::name::{self, Name}; 14use hir_expand::name::{name, Name};
13 15
14// FIXME: this is wrong, b/c it can't express `trait T: PartialEq<()>`.
15// We should return a `TraitREf` here.
16fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> { 16fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> {
17 let resolver = trait_.resolver(db); 17 let resolver = trait_.resolver(db);
18 // returning the iterator directly doesn't easily work because of 18 // returning the iterator directly doesn't easily work because of
@@ -23,10 +23,10 @@ fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> {
23 .where_predicates 23 .where_predicates
24 .iter() 24 .iter()
25 .filter_map(|pred| match &pred.type_ref { 25 .filter_map(|pred| match &pred.type_ref {
26 TypeRef::Path(p) if p.as_ident() == Some(&name::SELF_TYPE) => pred.bound.as_path(), 26 TypeRef::Path(p) if p == &Path::from(name![Self]) => pred.bound.as_path(),
27 _ => None, 27 _ => None,
28 }) 28 })
29 .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path) { 29 .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path.mod_path()) {
30 Some(TypeNs::TraitId(t)) => Some(t), 30 Some(TypeNs::TraitId(t)) => Some(t),
31 _ => None, 31 _ => None,
32 }) 32 })
@@ -82,3 +82,81 @@ pub(crate) fn make_mut_slice<T: Clone>(a: &mut Arc<[T]>) -> &mut [T] {
82 } 82 }
83 Arc::get_mut(a).unwrap() 83 Arc::get_mut(a).unwrap()
84} 84}
85
86pub(crate) fn generics(db: &impl DefDatabase, def: GenericDefId) -> Generics {
87 let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def)));
88 Generics { def, params: db.generic_params(def), parent_generics }
89}
90
91pub(crate) struct Generics {
92 def: GenericDefId,
93 pub(crate) params: Arc<GenericParams>,
94 parent_generics: Option<Box<Generics>>,
95}
96
97impl Generics {
98 pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = (u32, &'a TypeParamData)> + 'a {
99 self.parent_generics
100 .as_ref()
101 .into_iter()
102 .flat_map(|it| it.params.types.iter())
103 .chain(self.params.types.iter())
104 .enumerate()
105 .map(|(i, (_local_id, p))| (i as u32, p))
106 }
107
108 pub(crate) fn iter_parent<'a>(&'a self) -> impl Iterator<Item = (u32, &'a TypeParamData)> + 'a {
109 self.parent_generics
110 .as_ref()
111 .into_iter()
112 .flat_map(|it| it.params.types.iter())
113 .enumerate()
114 .map(|(i, (_local_id, p))| (i as u32, p))
115 }
116
117 pub(crate) fn len(&self) -> usize {
118 self.len_split().0
119 }
120 /// (total, parents, child)
121 pub(crate) fn len_split(&self) -> (usize, usize, usize) {
122 let parent = self.parent_generics.as_ref().map_or(0, |p| p.len());
123 let child = self.params.types.len();
124 (parent + child, parent, child)
125 }
126 pub(crate) fn param_idx(&self, param: TypeParamId) -> u32 {
127 self.find_param(param).0
128 }
129 pub(crate) fn param_name(&self, param: TypeParamId) -> Name {
130 self.find_param(param).1.name.clone()
131 }
132 fn find_param(&self, param: TypeParamId) -> (u32, &TypeParamData) {
133 if param.parent == self.def {
134 let (idx, (_local_id, data)) = self
135 .params
136 .types
137 .iter()
138 .enumerate()
139 .find(|(_, (idx, _))| *idx == param.local_id)
140 .unwrap();
141 let (_total, parent_len, _child) = self.len_split();
142 return ((parent_len + idx) as u32, data);
143 }
144 self.parent_generics.as_ref().unwrap().find_param(param)
145 }
146}
147
148fn parent_generic_def(db: &impl DefDatabase, def: GenericDefId) -> Option<GenericDefId> {
149 let container = match def {
150 GenericDefId::FunctionId(it) => it.lookup(db).container,
151 GenericDefId::TypeAliasId(it) => it.lookup(db).container,
152 GenericDefId::ConstId(it) => it.lookup(db).container,
153 GenericDefId::EnumVariantId(it) => return Some(it.parent.into()),
154 GenericDefId::AdtId(_) | GenericDefId::TraitId(_) | GenericDefId::ImplId(_) => return None,
155 };
156
157 match container {
158 AssocContainerId::ImplId(it) => Some(it.into()),
159 AssocContainerId::TraitId(it) => Some(it.into()),
160 AssocContainerId::ContainerId(_) => None,
161 }
162}