aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r--crates/ra_hir/src/ty/autoderef.rs14
-rw-r--r--crates/ra_hir/src/ty/display.rs2
-rw-r--r--crates/ra_hir/src/ty/infer.rs36
-rw-r--r--crates/ra_hir/src/ty/infer/path.rs10
-rw-r--r--crates/ra_hir/src/ty/infer/unify.rs24
-rw-r--r--crates/ra_hir/src/ty/lower.rs20
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs18
-rw-r--r--crates/ra_hir/src/ty/op.rs2
-rw-r--r--crates/ra_hir/src/ty/primitive.rs2
-rw-r--r--crates/ra_hir/src/ty/tests.rs142
-rw-r--r--crates/ra_hir/src/ty/traits.rs12
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs80
12 files changed, 235 insertions, 127 deletions
diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs
index 94f8ecdc9..02492ca14 100644
--- a/crates/ra_hir/src/ty/autoderef.rs
+++ b/crates/ra_hir/src/ty/autoderef.rs
@@ -7,7 +7,7 @@ use std::iter::successors;
7 7
8use log::{info, warn}; 8use log::{info, warn};
9 9
10use super::{traits::Solution, Canonical, Ty, TypeWalk}; 10use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk};
11use crate::{db::HirDatabase, name, HasGenericParams, Resolver}; 11use crate::{db::HirDatabase, name, HasGenericParams, Resolver};
12 12
13const AUTODEREF_RECURSION_LIMIT: usize = 10; 13const AUTODEREF_RECURSION_LIMIT: usize = 10;
@@ -44,7 +44,8 @@ fn deref_by_trait(
44 }; 44 };
45 let target = deref_trait.associated_type_by_name(db, &name::TARGET_TYPE)?; 45 let target = deref_trait.associated_type_by_name(db, &name::TARGET_TYPE)?;
46 46
47 if target.generic_params(db).count_params_including_parent() != 1 { 47 let generic_params = target.generic_params(db);
48 if generic_params.count_params_including_parent() != 1 {
48 // the Target type + Deref trait should only have one generic parameter, 49 // the Target type + Deref trait should only have one generic parameter,
49 // namely Deref's Self type 50 // namely Deref's Self type
50 return None; 51 return None;
@@ -54,12 +55,13 @@ fn deref_by_trait(
54 55
55 let env = super::lower::trait_env(db, resolver); 56 let env = super::lower::trait_env(db, resolver);
56 57
58 let parameters = Substs::build_for_generics(&generic_params)
59 .push(ty.value.clone().shift_bound_vars(1))
60 .build();
61
57 let projection = super::traits::ProjectionPredicate { 62 let projection = super::traits::ProjectionPredicate {
58 ty: Ty::Bound(0), 63 ty: Ty::Bound(0),
59 projection_ty: super::ProjectionTy { 64 projection_ty: super::ProjectionTy { associated_ty: target, parameters },
60 associated_ty: target,
61 parameters: vec![ty.value.clone().shift_bound_vars(1)].into(),
62 },
63 }; 65 };
64 66
65 let obligation = super::Obligation::Projection(projection); 67 let obligation = super::Obligation::Projection(projection);
diff --git a/crates/ra_hir/src/ty/display.rs b/crates/ra_hir/src/ty/display.rs
index 63ec9d7e1..7910429d7 100644
--- a/crates/ra_hir/src/ty/display.rs
+++ b/crates/ra_hir/src/ty/display.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::fmt; 3use std::fmt;
2 4
3use crate::db::HirDatabase; 5use crate::db::HirDatabase;
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index db3377357..ca9aefc42 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -609,7 +609,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
609 609
610 for (i, &subpat) in subpats.iter().enumerate() { 610 for (i, &subpat) in subpats.iter().enumerate() {
611 let expected_ty = def 611 let expected_ty = def
612 .and_then(|d| d.field(self.db, &Name::tuple_field_name(i))) 612 .and_then(|d| d.field(self.db, &Name::new_tuple_field(i)))
613 .map_or(Ty::Unknown, |field| field.ty(self.db)) 613 .map_or(Ty::Unknown, |field| field.ty(self.db))
614 .subst(&substs); 614 .subst(&substs);
615 let expected_ty = self.normalize_associated_types_in(expected_ty); 615 let expected_ty = self.normalize_associated_types_in(expected_ty);
@@ -688,14 +688,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
688 }; 688 };
689 let expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown)); 689 let expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown));
690 690
691 let inner_tys: Substs = args 691 let inner_tys = args
692 .iter() 692 .iter()
693 .zip(expectations_iter) 693 .zip(expectations_iter)
694 .map(|(&pat, ty)| self.infer_pat(pat, ty, default_bm)) 694 .map(|(&pat, ty)| self.infer_pat(pat, ty, default_bm))
695 .collect::<Vec<_>>() 695 .collect();
696 .into();
697 696
698 Ty::apply(TypeCtor::Tuple { cardinality: inner_tys.len() as u16 }, inner_tys) 697 Ty::apply(TypeCtor::Tuple { cardinality: args.len() as u16 }, Substs(inner_tys))
699 } 698 }
700 Pat::Ref { pat, mutability } => { 699 Pat::Ref { pat, mutability } => {
701 let expectation = match expected.as_reference() { 700 let expectation = match expected.as_reference() {
@@ -1229,7 +1228,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1229 ty: pat_ty.clone(), 1228 ty: pat_ty.clone(),
1230 projection_ty: ProjectionTy { 1229 projection_ty: ProjectionTy {
1231 associated_ty: into_iter_item_alias, 1230 associated_ty: into_iter_item_alias,
1232 parameters: vec![iterable_ty].into(), 1231 parameters: Substs::single(iterable_ty),
1233 }, 1232 },
1234 }; 1233 };
1235 self.obligations.push(Obligation::Projection(projection)); 1234 self.obligations.push(Obligation::Projection(projection));
@@ -1262,7 +1261,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1262 sig_tys.push(ret_ty.clone()); 1261 sig_tys.push(ret_ty.clone());
1263 let sig_ty = Ty::apply( 1262 let sig_ty = Ty::apply(
1264 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, 1263 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 },
1265 sig_tys.into(), 1264 Substs(sig_tys.into()),
1266 ); 1265 );
1267 let closure_ty = Ty::apply_one( 1266 let closure_ty = Ty::apply_one(
1268 TypeCtor::Closure { def: self.body.owner(), expr: tgt_expr }, 1267 TypeCtor::Closure { def: self.body.owner(), expr: tgt_expr },
@@ -1375,10 +1374,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1375 ) 1374 )
1376 .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) { 1375 .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) {
1377 Ty::Apply(a_ty) => match a_ty.ctor { 1376 Ty::Apply(a_ty) => match a_ty.ctor {
1378 TypeCtor::Tuple { .. } => { 1377 TypeCtor::Tuple { .. } => name
1379 let i = name.to_string().parse::<usize>().ok(); 1378 .as_tuple_index()
1380 i.and_then(|i| a_ty.parameters.0.get(i).cloned()) 1379 .and_then(|idx| a_ty.parameters.0.get(idx).cloned()),
1381 }
1382 TypeCtor::Adt(Adt::Struct(s)) => s.field(self.db, name).map(|field| { 1380 TypeCtor::Adt(Adt::Struct(s)) => s.field(self.db, name).map(|field| {
1383 self.write_field_resolution(tgt_expr, field); 1381 self.write_field_resolution(tgt_expr, field);
1384 field.ty(self.db).subst(&a_ty.parameters) 1382 field.ty(self.db).subst(&a_ty.parameters)
@@ -1400,7 +1398,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1400 ty: ty.clone(), 1398 ty: ty.clone(),
1401 projection_ty: ProjectionTy { 1399 projection_ty: ProjectionTy {
1402 associated_ty: future_future_output_alias, 1400 associated_ty: future_future_output_alias,
1403 parameters: vec![inner_ty].into(), 1401 parameters: Substs::single(inner_ty),
1404 }, 1402 },
1405 }; 1403 };
1406 self.obligations.push(Obligation::Projection(projection)); 1404 self.obligations.push(Obligation::Projection(projection));
@@ -1419,7 +1417,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1419 ty: ty.clone(), 1417 ty: ty.clone(),
1420 projection_ty: ProjectionTy { 1418 projection_ty: ProjectionTy {
1421 associated_ty: ops_try_ok_alias, 1419 associated_ty: ops_try_ok_alias,
1422 parameters: vec![inner_ty].into(), 1420 parameters: Substs::single(inner_ty),
1423 }, 1421 },
1424 }; 1422 };
1425 self.obligations.push(Obligation::Projection(projection)); 1423 self.obligations.push(Obligation::Projection(projection));
@@ -1604,6 +1602,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1604 tail: Option<ExprId>, 1602 tail: Option<ExprId>,
1605 expected: &Expectation, 1603 expected: &Expectation,
1606 ) -> Ty { 1604 ) -> Ty {
1605 let mut diverges = false;
1607 for stmt in statements { 1606 for stmt in statements {
1608 match stmt { 1607 match stmt {
1609 Statement::Let { pat, type_ref, initializer } => { 1608 Statement::Let { pat, type_ref, initializer } => {
@@ -1625,16 +1624,23 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1625 self.infer_pat(*pat, &ty, BindingMode::default()); 1624 self.infer_pat(*pat, &ty, BindingMode::default());
1626 } 1625 }
1627 Statement::Expr(expr) => { 1626 Statement::Expr(expr) => {
1628 self.infer_expr(*expr, &Expectation::none()); 1627 if let ty_app!(TypeCtor::Never) = self.infer_expr(*expr, &Expectation::none()) {
1628 diverges = true;
1629 }
1629 } 1630 }
1630 } 1631 }
1631 } 1632 }
1632 1633
1633 if let Some(expr) = tail { 1634 let ty = if let Some(expr) = tail {
1634 self.infer_expr_coerce(expr, expected) 1635 self.infer_expr_coerce(expr, expected)
1635 } else { 1636 } else {
1636 self.coerce(&Ty::unit(), &expected.ty); 1637 self.coerce(&Ty::unit(), &expected.ty);
1637 Ty::unit() 1638 Ty::unit()
1639 };
1640 if diverges {
1641 Ty::simple(TypeCtor::Never)
1642 } else {
1643 ty
1638 } 1644 }
1639 } 1645 }
1640 1646
diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir/src/ty/infer/path.rs
index feb7481b2..db979353a 100644
--- a/crates/ra_hir/src/ty/infer/path.rs
+++ b/crates/ra_hir/src/ty/infer/path.rs
@@ -158,13 +158,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
158 AssocItem::Const(c) => ValueNs::Const(c), 158 AssocItem::Const(c) => ValueNs::Const(c),
159 AssocItem::TypeAlias(_) => unreachable!(), 159 AssocItem::TypeAlias(_) => unreachable!(),
160 }; 160 };
161 let generics = item.generic_params(self.db); 161 let substs = Substs::build_for_def(self.db, item)
162 let mut substs = Vec::with_capacity(generics.count_params_including_parent()); 162 .use_parent_substs(&trait_ref.substs)
163 substs.extend(trait_ref.substs.iter().cloned()); 163 .fill_with_unknown()
164 substs.extend(std::iter::repeat(Ty::Unknown).take(generics.params.len())); 164 .build();
165 165
166 self.write_assoc_resolution(id, item); 166 self.write_assoc_resolution(id, item);
167 Some((def, Some(substs.into()))) 167 Some((def, Some(substs)))
168 } 168 }
169 169
170 fn resolve_ty_assoc_item( 170 fn resolve_ty_assoc_item(
diff --git a/crates/ra_hir/src/ty/infer/unify.rs b/crates/ra_hir/src/ty/infer/unify.rs
index b6ebee3b1..d161aa6b3 100644
--- a/crates/ra_hir/src/ty/infer/unify.rs
+++ b/crates/ra_hir/src/ty/infer/unify.rs
@@ -3,7 +3,8 @@
3use super::{InferenceContext, Obligation}; 3use super::{InferenceContext, Obligation};
4use crate::db::HirDatabase; 4use crate::db::HirDatabase;
5use crate::ty::{ 5use crate::ty::{
6 Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, TraitRef, Ty, TypeWalk, 6 Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty,
7 TypeWalk,
7}; 8};
8 9
9impl<'a, D: HirDatabase> InferenceContext<'a, D> { 10impl<'a, D: HirDatabase> InferenceContext<'a, D> {
@@ -74,12 +75,9 @@ where
74 } 75 }
75 76
76 fn do_canonicalize_trait_ref(&mut self, trait_ref: TraitRef) -> TraitRef { 77 fn do_canonicalize_trait_ref(&mut self, trait_ref: TraitRef) -> TraitRef {
77 let substs = trait_ref 78 let substs =
78 .substs 79 trait_ref.substs.iter().map(|ty| self.do_canonicalize_ty(ty.clone())).collect();
79 .iter() 80 TraitRef { trait_: trait_ref.trait_, substs: Substs(substs) }
80 .map(|ty| self.do_canonicalize_ty(ty.clone()))
81 .collect::<Vec<_>>();
82 TraitRef { trait_: trait_ref.trait_, substs: substs.into() }
83 } 81 }
84 82
85 fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { 83 fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> {
@@ -90,12 +88,9 @@ where
90 } 88 }
91 89
92 fn do_canonicalize_projection_ty(&mut self, projection_ty: ProjectionTy) -> ProjectionTy { 90 fn do_canonicalize_projection_ty(&mut self, projection_ty: ProjectionTy) -> ProjectionTy {
93 let params = projection_ty 91 let params =
94 .parameters 92 projection_ty.parameters.iter().map(|ty| self.do_canonicalize_ty(ty.clone())).collect();
95 .iter() 93 ProjectionTy { associated_ty: projection_ty.associated_ty, parameters: Substs(params) }
96 .map(|ty| self.do_canonicalize_ty(ty.clone()))
97 .collect::<Vec<_>>();
98 ProjectionTy { associated_ty: projection_ty.associated_ty, parameters: params.into() }
99 } 94 }
100 95
101 fn do_canonicalize_projection_predicate( 96 fn do_canonicalize_projection_predicate(
@@ -153,8 +148,7 @@ impl<T> Canonicalized<T> {
153 solution: Canonical<Vec<Ty>>, 148 solution: Canonical<Vec<Ty>>,
154 ) { 149 ) {
155 // the solution may contain new variables, which we need to convert to new inference vars 150 // the solution may contain new variables, which we need to convert to new inference vars
156 let new_vars = 151 let new_vars = Substs((0..solution.num_vars).map(|_| ctx.new_type_var()).collect());
157 (0..solution.num_vars).map(|_| ctx.new_type_var()).collect::<Vec<_>>().into();
158 for (i, ty) in solution.value.into_iter().enumerate() { 152 for (i, ty) in solution.value.into_iter().enumerate() {
159 let var = self.free_vars[i]; 153 let var = self.free_vars[i];
160 ctx.unify(&Ty::Infer(var), &ty.subst_bound_vars(&new_vars)); 154 ctx.unify(&Ty::Infer(var), &ty.subst_bound_vars(&new_vars));
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index dd503d771..4b67c82e7 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -239,14 +239,10 @@ impl Ty {
239 let traits = traits_from_env.flat_map(|t| t.all_super_traits(db)); 239 let traits = traits_from_env.flat_map(|t| t.all_super_traits(db));
240 for t in traits { 240 for t in traits {
241 if let Some(associated_ty) = t.associated_type_by_name(db, &segment.name) { 241 if let Some(associated_ty) = t.associated_type_by_name(db, &segment.name) {
242 let generics = t.generic_params(db); 242 let substs =
243 let mut substs = Vec::new(); 243 Substs::build_for_def(db, t).push(self_ty.clone()).fill_with_unknown().build();
244 substs.push(self_ty.clone());
245 substs.extend(
246 iter::repeat(Ty::Unknown).take(generics.count_params_including_parent() - 1),
247 );
248 // FIXME handle type parameters on the segment 244 // FIXME handle type parameters on the segment
249 return Ty::Projection(ProjectionTy { associated_ty, parameters: substs.into() }); 245 return Ty::Projection(ProjectionTy { associated_ty, parameters: substs });
250 } 246 }
251 } 247 }
252 Ty::Unknown 248 Ty::Unknown
@@ -766,6 +762,16 @@ pub enum CallableDef {
766} 762}
767impl_froms!(CallableDef: Function, Struct, EnumVariant); 763impl_froms!(CallableDef: Function, Struct, EnumVariant);
768 764
765impl CallableDef {
766 pub fn krate(self, db: &impl HirDatabase) -> Option<crate::Crate> {
767 match self {
768 CallableDef::Function(f) => f.krate(db),
769 CallableDef::Struct(s) => s.krate(db),
770 CallableDef::EnumVariant(e) => e.parent_enum(db).krate(db),
771 }
772 }
773}
774
769impl From<CallableDef> for GenericDef { 775impl From<CallableDef> for GenericDef {
770 fn from(def: CallableDef) -> GenericDef { 776 fn from(def: CallableDef) -> GenericDef {
771 match def { 777 match def {
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 4b71b376f..ad2ab560d 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -10,7 +10,6 @@ use rustc_hash::FxHashMap;
10use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef}; 10use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef};
11use crate::{ 11use crate::{
12 db::HirDatabase, 12 db::HirDatabase,
13 generics::HasGenericParams,
14 impl_block::{ImplBlock, ImplId}, 13 impl_block::{ImplBlock, ImplId},
15 nameres::CrateModuleId, 14 nameres::CrateModuleId,
16 resolve::Resolver, 15 resolve::Resolver,
@@ -331,20 +330,13 @@ fn generic_implements_goal(
331 trait_: Trait, 330 trait_: Trait,
332 self_ty: Canonical<Ty>, 331 self_ty: Canonical<Ty>,
333) -> Canonical<InEnvironment<super::Obligation>> { 332) -> Canonical<InEnvironment<super::Obligation>> {
334 let mut substs = Vec::new();
335 let generics = trait_.generic_params(db);
336 let num_vars = self_ty.num_vars; 333 let num_vars = self_ty.num_vars;
337 substs.push(self_ty.value); 334 let substs = super::Substs::build_for_def(db, trait_)
338 substs.extend( 335 .push(self_ty.value)
339 generics 336 .fill_with_bound_vars(num_vars as u32)
340 .params_including_parent() 337 .build();
341 .into_iter()
342 .skip(1)
343 .enumerate()
344 .map(|(i, _p)| Ty::Bound((i + num_vars) as u32)),
345 );
346 let num_vars = substs.len() - 1 + self_ty.num_vars; 338 let num_vars = substs.len() - 1 + self_ty.num_vars;
347 let trait_ref = TraitRef { trait_, substs: substs.into() }; 339 let trait_ref = TraitRef { trait_, substs };
348 let obligation = super::Obligation::Trait(trait_ref); 340 let obligation = super::Obligation::Trait(trait_ref);
349 Canonical { num_vars, value: InEnvironment::new(env, obligation) } 341 Canonical { num_vars, value: InEnvironment::new(env, obligation) }
350} 342}
diff --git a/crates/ra_hir/src/ty/op.rs b/crates/ra_hir/src/ty/op.rs
index 1b30a5b9b..bcfa3a6a2 100644
--- a/crates/ra_hir/src/ty/op.rs
+++ b/crates/ra_hir/src/ty/op.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use super::{InferTy, Ty, TypeCtor}; 3use super::{InferTy, Ty, TypeCtor};
2use crate::{ 4use crate::{
3 expr::{BinaryOp, CmpOp}, 5 expr::{BinaryOp, CmpOp},
diff --git a/crates/ra_hir/src/ty/primitive.rs b/crates/ra_hir/src/ty/primitive.rs
index 2c60fefd6..8966f9d1d 100644
--- a/crates/ra_hir/src/ty/primitive.rs
+++ b/crates/ra_hir/src/ty/primitive.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::fmt; 3use std::fmt;
2 4
3#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 5#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 4362bb27a..25dad81eb 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -3,6 +3,7 @@ use std::sync::Arc;
3 3
4use insta::assert_snapshot; 4use insta::assert_snapshot;
5 5
6use ra_cfg::CfgOptions;
6use ra_db::{salsa::Database, FilePosition, SourceDatabase}; 7use ra_db::{salsa::Database, FilePosition, SourceDatabase};
7use ra_syntax::{ 8use ra_syntax::{
8 algo, 9 algo,
@@ -24,6 +25,50 @@ mod never_type;
24mod coercion; 25mod coercion;
25 26
26#[test] 27#[test]
28fn cfg_impl_block() {
29 let (mut db, pos) = MockDatabase::with_position(
30 r#"
31//- /main.rs
32use foo::S as T;
33struct S;
34
35#[cfg(test)]
36impl S {
37 fn foo1(&self) -> i32 { 0 }
38}
39
40#[cfg(not(test))]
41impl S {
42 fn foo2(&self) -> i32 { 0 }
43}
44
45fn test() {
46 let t = (S.foo1(), S.foo2(), T.foo3(), T.foo4());
47 t<|>;
48}
49
50//- /foo.rs
51struct S;
52
53#[cfg(not(test))]
54impl S {
55 fn foo3(&self) -> i32 { 0 }
56}
57
58#[cfg(test)]
59impl S {
60 fn foo4(&self) -> i32 { 0 }
61}
62"#,
63 );
64 db.set_crate_graph_from_fixture(crate_graph! {
65 "main": ("/main.rs", ["foo"], CfgOptions::default().atom("test".into())),
66 "foo": ("/foo.rs", []),
67 });
68 assert_eq!("(i32, {unknown}, i32, {unknown})", type_at_pos(&db, pos));
69}
70
71#[test]
27fn infer_await() { 72fn infer_await() {
28 let (mut db, pos) = MockDatabase::with_position( 73 let (mut db, pos) = MockDatabase::with_position(
29 r#" 74 r#"
@@ -218,7 +263,7 @@ fn test(a: u32, b: isize, c: !, d: &str) {
218 [17; 18) 'b': isize 263 [17; 18) 'b': isize
219 [27; 28) 'c': ! 264 [27; 28) 'c': !
220 [33; 34) 'd': &str 265 [33; 34) 'd': &str
221 [42; 121) '{ ...f32; }': () 266 [42; 121) '{ ...f32; }': !
222 [48; 49) 'a': u32 267 [48; 49) 'a': u32
223 [55; 56) 'b': isize 268 [55; 56) 'b': isize
224 [62; 63) 'c': ! 269 [62; 63) 'c': !
@@ -981,6 +1026,67 @@ fn main(foo: Foo) {
981} 1026}
982 1027
983#[test] 1028#[test]
1029fn infer_if_match_with_return() {
1030 assert_snapshot!(
1031 infer(r#"
1032fn foo() {
1033 let _x1 = if true {
1034 1
1035 } else {
1036 return;
1037 };
1038 let _x2 = if true {
1039 2
1040 } else {
1041 return
1042 };
1043 let _x3 = match true {
1044 true => 3,
1045 _ => {
1046 return;
1047 }
1048 };
1049 let _x4 = match true {
1050 true => 4,
1051 _ => return
1052 };
1053}"#),
1054 @r###"
1055 [10; 323) '{ ... }; }': ()
1056 [20; 23) '_x1': i32
1057 [26; 80) 'if tru... }': i32
1058 [29; 33) 'true': bool
1059 [34; 51) '{ ... }': i32
1060 [44; 45) '1': i32
1061 [57; 80) '{ ... }': !
1062 [67; 73) 'return': !
1063 [90; 93) '_x2': i32
1064 [96; 149) 'if tru... }': i32
1065 [99; 103) 'true': bool
1066 [104; 121) '{ ... }': i32
1067 [114; 115) '2': i32
1068 [127; 149) '{ ... }': !
1069 [137; 143) 'return': !
1070 [159; 162) '_x3': i32
1071 [165; 247) 'match ... }': i32
1072 [171; 175) 'true': bool
1073 [186; 190) 'true': bool
1074 [194; 195) '3': i32
1075 [205; 206) '_': bool
1076 [210; 241) '{ ... }': !
1077 [224; 230) 'return': !
1078 [257; 260) '_x4': i32
1079 [263; 320) 'match ... }': i32
1080 [269; 273) 'true': bool
1081 [284; 288) 'true': bool
1082 [292; 293) '4': i32
1083 [303; 304) '_': bool
1084 [308; 314) 'return': !
1085 "###
1086 )
1087}
1088
1089#[test]
984fn infer_inherent_method() { 1090fn infer_inherent_method() {
985 assert_snapshot!( 1091 assert_snapshot!(
986 infer(r#" 1092 infer(r#"
@@ -3130,6 +3236,39 @@ fn test() { S.foo()<|>; }
3130 assert_eq!(t, "u128"); 3236 assert_eq!(t, "u128");
3131} 3237}
3132 3238
3239#[test]
3240fn infer_macro_with_dollar_crate_is_correct_in_expr() {
3241 covers!(macro_dollar_crate_other);
3242 let (mut db, pos) = MockDatabase::with_position(
3243 r#"
3244//- /main.rs
3245fn test() {
3246 let x = (foo::foo!(1), foo::foo!(2));
3247 x<|>;
3248}
3249
3250//- /lib.rs
3251#[macro_export]
3252macro_rules! foo {
3253 (1) => { $crate::bar!() };
3254 (2) => { 1 + $crate::baz() };
3255}
3256
3257#[macro_export]
3258macro_rules! bar {
3259 () => { 42 }
3260}
3261
3262pub fn baz() -> usize { 31usize }
3263"#,
3264 );
3265 db.set_crate_graph_from_fixture(crate_graph! {
3266 "main": ("/main.rs", ["foo"]),
3267 "foo": ("/lib.rs", []),
3268 });
3269 assert_eq!("(i32, usize)", type_at_pos(&db, pos));
3270}
3271
3133#[ignore] 3272#[ignore]
3134#[test] 3273#[test]
3135fn method_resolution_trait_before_autoref() { 3274fn method_resolution_trait_before_autoref() {
@@ -3321,7 +3460,6 @@ fn test() { S2.into()<|>; }
3321 3460
3322#[test] 3461#[test]
3323fn method_resolution_encountering_fn_type() { 3462fn method_resolution_encountering_fn_type() {
3324 covers!(trait_resolution_on_fn_type);
3325 type_at( 3463 type_at(
3326 r#" 3464 r#"
3327//- /main.rs 3465//- /main.rs
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs
index d11dab294..b0f67ae50 100644
--- a/crates/ra_hir/src/ty/traits.rs
+++ b/crates/ra_hir/src/ty/traits.rs
@@ -1,9 +1,8 @@
1//! Trait solving using Chalk. 1//! Trait solving using Chalk.
2use std::sync::Arc; 2use std::sync::{Arc, Mutex};
3 3
4use chalk_ir::cast::Cast; 4use chalk_ir::cast::Cast;
5use log::debug; 5use log::debug;
6use parking_lot::Mutex;
7use ra_db::salsa; 6use ra_db::salsa;
8use ra_prof::profile; 7use ra_prof::profile;
9use rustc_hash::FxHashSet; 8use rustc_hash::FxHashSet;
@@ -38,7 +37,14 @@ impl TraitSolver {
38 ) -> Option<chalk_solve::Solution> { 37 ) -> Option<chalk_solve::Solution> {
39 let context = ChalkContext { db, krate: self.krate }; 38 let context = ChalkContext { db, krate: self.krate };
40 debug!("solve goal: {:?}", goal); 39 debug!("solve goal: {:?}", goal);
41 let solution = self.inner.lock().solve(&context, goal); 40 let mut solver = match self.inner.lock() {
41 Ok(it) => it,
42 // Our cancellation works via unwinding, but, as chalk is not
43 // panic-safe, we need to make sure to propagate the cancellation.
44 // Ideally, we should also make chalk panic-safe.
45 Err(_) => ra_db::Canceled::throw(),
46 };
47 let solution = solver.solve(&context, goal);
42 debug!("solve({:?}) => {:?}", goal, solution); 48 debug!("solve({:?}) => {:?}", goal, solution);
43 solution 49 solution
44 } 50 }
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 538b4d3ec..2642a54bf 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -10,17 +10,13 @@ use chalk_ir::{
10use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum}; 10use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum};
11 11
12use ra_db::salsa::{InternId, InternKey}; 12use ra_db::salsa::{InternId, InternKey};
13use test_utils::tested_by;
14 13
15use super::{Canonical, ChalkContext, Impl, Obligation}; 14use super::{Canonical, ChalkContext, Impl, Obligation};
16use crate::{ 15use crate::{
17 db::HirDatabase, 16 db::HirDatabase,
18 generics::GenericDef, 17 generics::GenericDef,
19 ty::display::HirDisplay, 18 ty::display::HirDisplay,
20 ty::{ 19 ty::{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk},
21 ApplicationTy, CallableDef, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
22 TypeWalk,
23 },
24 AssocItem, Crate, HasGenericParams, ImplBlock, Trait, TypeAlias, 20 AssocItem, Crate, HasGenericParams, ImplBlock, Trait, TypeAlias,
25}; 21};
26 22
@@ -124,14 +120,15 @@ impl ToChalk for Substs {
124 } 120 }
125 121
126 fn from_chalk(db: &impl HirDatabase, parameters: Vec<chalk_ir::Parameter>) -> Substs { 122 fn from_chalk(db: &impl HirDatabase, parameters: Vec<chalk_ir::Parameter>) -> Substs {
127 parameters 123 let tys = parameters
128 .into_iter() 124 .into_iter()
129 .map(|p| match p { 125 .map(|p| match p {
130 chalk_ir::Parameter(chalk_ir::ParameterKind::Ty(ty)) => from_chalk(db, ty), 126 chalk_ir::Parameter(chalk_ir::ParameterKind::Ty(ty)) => from_chalk(db, ty),
131 chalk_ir::Parameter(chalk_ir::ParameterKind::Lifetime(_)) => unimplemented!(), 127 chalk_ir::Parameter(chalk_ir::ParameterKind::Lifetime(_)) => unimplemented!(),
132 }) 128 })
133 .collect::<Vec<_>>() 129 .collect::<Vec<_>>()
134 .into() 130 .into();
131 Substs(tys)
135 } 132 }
136} 133}
137 134
@@ -539,60 +536,18 @@ pub(crate) fn struct_datum_query(
539 struct_id: chalk_ir::StructId, 536 struct_id: chalk_ir::StructId,
540) -> Arc<StructDatum> { 537) -> Arc<StructDatum> {
541 debug!("struct_datum {:?}", struct_id); 538 debug!("struct_datum {:?}", struct_id);
542 let type_ctor = from_chalk(db, struct_id); 539 let type_ctor: TypeCtor = from_chalk(db, struct_id);
543 debug!("struct {:?} = {:?}", struct_id, type_ctor); 540 debug!("struct {:?} = {:?}", struct_id, type_ctor);
544 // FIXME might be nicer if we can create a fake GenericParams for the TypeCtor 541 let num_params = type_ctor.num_ty_params(db);
545 // FIXME extract this to a method on Ty 542 let upstream = type_ctor.krate(db) != Some(krate);
546 let (num_params, where_clauses, upstream) = match type_ctor { 543 let where_clauses = type_ctor
547 TypeCtor::Bool 544 .as_generic_def()
548 | TypeCtor::Char 545 .map(|generic_def| {
549 | TypeCtor::Int(_)
550 | TypeCtor::Float(_)
551 | TypeCtor::Never
552 | TypeCtor::Str => (0, vec![], true),
553 TypeCtor::Slice | TypeCtor::Array | TypeCtor::RawPtr(_) | TypeCtor::Ref(_) => {
554 (1, vec![], true)
555 }
556 TypeCtor::FnPtr { num_args } => (num_args as usize + 1, vec![], true),
557 TypeCtor::Tuple { cardinality } => (cardinality as usize, vec![], true),
558 TypeCtor::FnDef(callable) => {
559 tested_by!(trait_resolution_on_fn_type);
560 let upstream = match callable {
561 CallableDef::Function(f) => f.module(db).krate(db),
562 CallableDef::Struct(s) => s.module(db).krate(db),
563 CallableDef::EnumVariant(v) => v.parent_enum(db).module(db).krate(db),
564 } != Some(krate);
565 let generic_def: GenericDef = callable.into();
566 let generic_params = generic_def.generic_params(db); 546 let generic_params = generic_def.generic_params(db);
567 let bound_vars = Substs::bound_vars(&generic_params); 547 let bound_vars = Substs::bound_vars(&generic_params);
568 let where_clauses = convert_where_clauses(db, generic_def, &bound_vars); 548 convert_where_clauses(db, generic_def, &bound_vars)
569 (generic_params.count_params_including_parent(), where_clauses, upstream) 549 })
570 } 550 .unwrap_or_else(Vec::new);
571 TypeCtor::Adt(adt) => {
572 let generic_params = adt.generic_params(db);
573 let bound_vars = Substs::bound_vars(&generic_params);
574 let where_clauses = convert_where_clauses(db, adt.into(), &bound_vars);
575 (
576 generic_params.count_params_including_parent(),
577 where_clauses,
578 adt.krate(db) != Some(krate),
579 )
580 }
581 TypeCtor::AssociatedType(type_alias) => {
582 let generic_params = type_alias.generic_params(db);
583 let bound_vars = Substs::bound_vars(&generic_params);
584 let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars);
585 (
586 generic_params.count_params_including_parent(),
587 where_clauses,
588 type_alias.krate(db) != Some(krate),
589 )
590 }
591 TypeCtor::Closure { def, .. } => {
592 let upstream = def.krate(db) != Some(krate);
593 (1, vec![], upstream)
594 }
595 };
596 let flags = chalk_rust_ir::StructFlags { 551 let flags = chalk_rust_ir::StructFlags {
597 upstream, 552 upstream,
598 // FIXME set fundamental flag correctly 553 // FIXME set fundamental flag correctly
@@ -729,17 +684,20 @@ fn closure_fn_trait_impl_datum(
729 684
730 let arg_ty = Ty::apply( 685 let arg_ty = Ty::apply(
731 TypeCtor::Tuple { cardinality: num_args }, 686 TypeCtor::Tuple { cardinality: num_args },
732 (0..num_args).map(|i| Ty::Bound(i.into())).collect::<Vec<_>>().into(), 687 Substs::builder(num_args as usize).fill_with_bound_vars(0).build(),
733 ); 688 );
734 let output_ty = Ty::Bound(num_args.into()); 689 let output_ty = Ty::Bound(num_args.into());
735 let sig_ty = Ty::apply( 690 let sig_ty = Ty::apply(
736 TypeCtor::FnPtr { num_args }, 691 TypeCtor::FnPtr { num_args },
737 (0..num_args + 1).map(|i| Ty::Bound(i.into())).collect::<Vec<_>>().into(), 692 Substs::builder(num_args as usize + 1).fill_with_bound_vars(0).build(),
738 ); 693 );
739 694
740 let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty); 695 let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty);
741 696
742 let trait_ref = TraitRef { trait_, substs: vec![self_ty, arg_ty].into() }; 697 let trait_ref = TraitRef {
698 trait_,
699 substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(),
700 };
743 701
744 let output_ty_id = fn_once_trait.associated_type_by_name(db, &crate::name::OUTPUT_TYPE)?; 702 let output_ty_id = fn_once_trait.associated_type_by_name(db, &crate::name::OUTPUT_TYPE)?;
745 703