aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r--crates/ra_hir_ty/src/_match.rs77
-rw-r--r--crates/ra_hir_ty/src/db.rs15
-rw-r--r--crates/ra_hir_ty/src/diagnostics.rs12
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs81
-rw-r--r--crates/ra_hir_ty/src/infer/path.rs2
-rw-r--r--crates/ra_hir_ty/src/lib.rs63
-rw-r--r--crates/ra_hir_ty/src/lower.rs25
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs69
-rw-r--r--crates/ra_hir_ty/src/tests/regression.rs151
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs223
-rw-r--r--crates/ra_hir_ty/src/traits.rs43
-rw-r--r--crates/ra_hir_ty/src/traits/builtin.rs20
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs28
-rw-r--r--crates/ra_hir_ty/src/utils.rs14
14 files changed, 689 insertions, 134 deletions
diff --git a/crates/ra_hir_ty/src/_match.rs b/crates/ra_hir_ty/src/_match.rs
index 02a7a61f1..5495ce284 100644
--- a/crates/ra_hir_ty/src/_match.rs
+++ b/crates/ra_hir_ty/src/_match.rs
@@ -312,20 +312,16 @@ impl PatStack {
312 Self(v) 312 Self(v)
313 } 313 }
314 314
315 fn is_empty(&self) -> bool {
316 self.0.is_empty()
317 }
318
319 fn head(&self) -> PatIdOrWild {
320 self.0[0]
321 }
322
323 fn get_head(&self) -> Option<PatIdOrWild> { 315 fn get_head(&self) -> Option<PatIdOrWild> {
324 self.0.first().copied() 316 self.0.first().copied()
325 } 317 }
326 318
319 fn tail(&self) -> &[PatIdOrWild] {
320 self.0.get(1..).unwrap_or(&[])
321 }
322
327 fn to_tail(&self) -> PatStack { 323 fn to_tail(&self) -> PatStack {
328 Self::from_slice(&self.0[1..]) 324 Self::from_slice(self.tail())
329 } 325 }
330 326
331 fn replace_head_with<I, T>(&self, pats: I) -> PatStack 327 fn replace_head_with<I, T>(&self, pats: I) -> PatStack
@@ -347,7 +343,7 @@ impl PatStack {
347 /// 343 ///
348 /// See the module docs and the associated documentation in rustc for details. 344 /// See the module docs and the associated documentation in rustc for details.
349 fn specialize_wildcard(&self, cx: &MatchCheckCtx) -> Option<PatStack> { 345 fn specialize_wildcard(&self, cx: &MatchCheckCtx) -> Option<PatStack> {
350 if matches!(self.head().as_pat(cx), Pat::Wild) { 346 if matches!(self.get_head()?.as_pat(cx), Pat::Wild) {
351 Some(self.to_tail()) 347 Some(self.to_tail())
352 } else { 348 } else {
353 None 349 None
@@ -362,11 +358,12 @@ impl PatStack {
362 cx: &MatchCheckCtx, 358 cx: &MatchCheckCtx,
363 constructor: &Constructor, 359 constructor: &Constructor,
364 ) -> MatchCheckResult<Option<PatStack>> { 360 ) -> MatchCheckResult<Option<PatStack>> {
365 if self.is_empty() { 361 let head = match self.get_head() {
366 return Ok(None); 362 Some(head) => head,
367 } 363 None => return Ok(None),
364 };
368 365
369 let head_pat = self.head().as_pat(cx); 366 let head_pat = head.as_pat(cx);
370 let result = match (head_pat, constructor) { 367 let result = match (head_pat, constructor) {
371 (Pat::Tuple { args: ref pat_ids, ellipsis }, Constructor::Tuple { arity: _ }) => { 368 (Pat::Tuple { args: ref pat_ids, ellipsis }, Constructor::Tuple { arity: _ }) => {
372 if ellipsis.is_some() { 369 if ellipsis.is_some() {
@@ -394,7 +391,7 @@ impl PatStack {
394 (Pat::Wild, constructor) => Some(self.expand_wildcard(cx, constructor)?), 391 (Pat::Wild, constructor) => Some(self.expand_wildcard(cx, constructor)?),
395 (Pat::Path(_), Constructor::Enum(constructor)) => { 392 (Pat::Path(_), Constructor::Enum(constructor)) => {
396 // unit enum variants become `Pat::Path` 393 // unit enum variants become `Pat::Path`
397 let pat_id = self.head().as_id().expect("we know this isn't a wild"); 394 let pat_id = head.as_id().expect("we know this isn't a wild");
398 if !enum_variant_matches(cx, pat_id, *constructor) { 395 if !enum_variant_matches(cx, pat_id, *constructor) {
399 None 396 None
400 } else { 397 } else {
@@ -405,7 +402,7 @@ impl PatStack {
405 Pat::TupleStruct { args: ref pat_ids, ellipsis, .. }, 402 Pat::TupleStruct { args: ref pat_ids, ellipsis, .. },
406 Constructor::Enum(enum_constructor), 403 Constructor::Enum(enum_constructor),
407 ) => { 404 ) => {
408 let pat_id = self.head().as_id().expect("we know this isn't a wild"); 405 let pat_id = head.as_id().expect("we know this isn't a wild");
409 if !enum_variant_matches(cx, pat_id, *enum_constructor) { 406 if !enum_variant_matches(cx, pat_id, *enum_constructor) {
410 None 407 None
411 } else { 408 } else {
@@ -445,7 +442,7 @@ impl PatStack {
445 } 442 }
446 } 443 }
447 (Pat::Record { args: ref arg_patterns, .. }, Constructor::Enum(e)) => { 444 (Pat::Record { args: ref arg_patterns, .. }, Constructor::Enum(e)) => {
448 let pat_id = self.head().as_id().expect("we know this isn't a wild"); 445 let pat_id = head.as_id().expect("we know this isn't a wild");
449 if !enum_variant_matches(cx, pat_id, *e) { 446 if !enum_variant_matches(cx, pat_id, *e) {
450 None 447 None
451 } else { 448 } else {
@@ -491,7 +488,7 @@ impl PatStack {
491 ) -> MatchCheckResult<PatStack> { 488 ) -> MatchCheckResult<PatStack> {
492 assert_eq!( 489 assert_eq!(
493 Pat::Wild, 490 Pat::Wild,
494 self.head().as_pat(cx), 491 self.get_head().expect("expand_wildcard called on empty PatStack").as_pat(cx),
495 "expand_wildcard must only be called on PatStack with wild at head", 492 "expand_wildcard must only be called on PatStack with wild at head",
496 ); 493 );
497 494
@@ -509,7 +506,6 @@ impl PatStack {
509 } 506 }
510} 507}
511 508
512#[derive(Debug)]
513/// A collection of PatStack. 509/// A collection of PatStack.
514/// 510///
515/// This type is modeled from the struct of the same name in `rustc`. 511/// This type is modeled from the struct of the same name in `rustc`.
@@ -623,13 +619,16 @@ pub(crate) fn is_useful(
623 _ => (), 619 _ => (),
624 } 620 }
625 621
626 if v.is_empty() { 622 let head = match v.get_head() {
627 let result = if matrix.is_empty() { Usefulness::Useful } else { Usefulness::NotUseful }; 623 Some(head) => head,
624 None => {
625 let result = if matrix.is_empty() { Usefulness::Useful } else { Usefulness::NotUseful };
628 626
629 return Ok(result); 627 return Ok(result);
630 } 628 }
629 };
631 630
632 if let Pat::Or(pat_ids) = v.head().as_pat(cx) { 631 if let Pat::Or(pat_ids) = head.as_pat(cx) {
633 let mut found_unimplemented = false; 632 let mut found_unimplemented = false;
634 let any_useful = pat_ids.iter().any(|&pat_id| { 633 let any_useful = pat_ids.iter().any(|&pat_id| {
635 let v = PatStack::from_pattern(pat_id); 634 let v = PatStack::from_pattern(pat_id);
@@ -653,7 +652,7 @@ pub(crate) fn is_useful(
653 }; 652 };
654 } 653 }
655 654
656 if let Some(constructor) = pat_constructor(cx, v.head())? { 655 if let Some(constructor) = pat_constructor(cx, head)? {
657 let matrix = matrix.specialize_constructor(&cx, &constructor)?; 656 let matrix = matrix.specialize_constructor(&cx, &constructor)?;
658 let v = v 657 let v = v
659 .specialize_constructor(&cx, &constructor)? 658 .specialize_constructor(&cx, &constructor)?
@@ -854,10 +853,10 @@ mod tests {
854 } 853 }
855 854
856 pub(super) fn check_no_diagnostic(ra_fixture: &str) { 855 pub(super) fn check_no_diagnostic(ra_fixture: &str) {
857 let diagnostic_count = 856 let (s, diagnostic_count) =
858 TestDB::with_single_file(ra_fixture).0.diagnostic::<MissingMatchArms>().1; 857 TestDB::with_single_file(ra_fixture).0.diagnostic::<MissingMatchArms>();
859 858
860 assert_eq!(0, diagnostic_count, "expected no diagnostic, found one"); 859 assert_eq!(0, diagnostic_count, "expected no diagnostic, found one: {}", s);
861 } 860 }
862 861
863 #[test] 862 #[test]
@@ -2014,6 +2013,28 @@ mod tests {
2014 ", 2013 ",
2015 ); 2014 );
2016 } 2015 }
2016
2017 #[test]
2018 fn or_pattern_panic_2() {
2019 // FIXME: This is a false positive, but the code used to cause a panic in the match checker,
2020 // so this acts as a regression test for that.
2021 check_diagnostic(
2022 r"
2023 pub enum Category {
2024 Infinity,
2025 Zero,
2026 }
2027
2028 fn panic(a: Category, b: Category) {
2029 match (a, b) {
2030 (Category::Infinity, Category::Infinity) | (Category::Zero, Category::Zero) => {}
2031
2032 (Category::Infinity | Category::Zero, _) => {}
2033 }
2034 }
2035 ",
2036 );
2037 }
2017} 2038}
2018 2039
2019#[cfg(test)] 2040#[cfg(test)]
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs
index bf71d38d6..7889b8d2c 100644
--- a/crates/ra_hir_ty/src/db.rs
+++ b/crates/ra_hir_ty/src/db.rs
@@ -3,15 +3,15 @@
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::{ 5use hir_def::{
6 db::DefDatabase, DefWithBodyId, FunctionId, GenericDefId, ImplId, LocalFieldId, TraitId, 6 db::DefDatabase, DefWithBodyId, FunctionId, GenericDefId, ImplId, LocalFieldId, TypeParamId,
7 TypeParamId, VariantId, 7 VariantId,
8}; 8};
9use ra_arena::map::ArenaMap; 9use ra_arena::map::ArenaMap;
10use ra_db::{impl_intern_key, salsa, CrateId, Upcast}; 10use ra_db::{impl_intern_key, salsa, CrateId, Upcast};
11use ra_prof::profile; 11use ra_prof::profile;
12 12
13use crate::{ 13use crate::{
14 method_resolution::{CrateImplDefs, TyFingerprint}, 14 method_resolution::CrateImplDefs,
15 traits::{chalk, AssocTyValue, Impl}, 15 traits::{chalk, AssocTyValue, Impl},
16 Binders, CallableDef, GenericPredicate, InferenceResult, OpaqueTyId, PolyFnSig, 16 Binders, CallableDef, GenericPredicate, InferenceResult, OpaqueTyId, PolyFnSig,
17 ReturnTypeImplTraits, Substs, TraitRef, Ty, TyDefId, TypeCtor, ValueTyDefId, 17 ReturnTypeImplTraits, Substs, TraitRef, Ty, TyDefId, TypeCtor, ValueTyDefId,
@@ -70,13 +70,8 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
70 #[salsa::invoke(crate::method_resolution::CrateImplDefs::impls_in_crate_query)] 70 #[salsa::invoke(crate::method_resolution::CrateImplDefs::impls_in_crate_query)]
71 fn impls_in_crate(&self, krate: CrateId) -> Arc<CrateImplDefs>; 71 fn impls_in_crate(&self, krate: CrateId) -> Arc<CrateImplDefs>;
72 72
73 #[salsa::invoke(crate::traits::impls_for_trait_query)] 73 #[salsa::invoke(crate::method_resolution::CrateImplDefs::impls_from_deps_query)]
74 fn impls_for_trait( 74 fn impls_from_deps(&self, krate: CrateId) -> Arc<CrateImplDefs>;
75 &self,
76 krate: CrateId,
77 trait_: TraitId,
78 self_ty_fp: Option<TyFingerprint>,
79 ) -> Arc<[ImplId]>;
80 75
81 // Interned IDs for Chalk integration 76 // Interned IDs for Chalk integration
82 #[salsa::interned] 77 #[salsa::interned]
diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs
index 2c7298714..ebd9cb08f 100644
--- a/crates/ra_hir_ty/src/diagnostics.rs
+++ b/crates/ra_hir_ty/src/diagnostics.rs
@@ -6,7 +6,7 @@ use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile};
6use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr}; 6use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr};
7use stdx::format_to; 7use stdx::format_to;
8 8
9pub use hir_def::{diagnostics::UnresolvedModule, expr::MatchArm}; 9pub use hir_def::{diagnostics::UnresolvedModule, expr::MatchArm, path::Path};
10pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; 10pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink};
11 11
12#[derive(Debug)] 12#[derive(Debug)]
@@ -29,6 +29,16 @@ impl Diagnostic for NoSuchField {
29 } 29 }
30} 30}
31 31
32impl AstDiagnostic for NoSuchField {
33 type AST = ast::RecordField;
34
35 fn ast(&self, db: &impl AstDatabase) -> Self::AST {
36 let root = db.parse_or_expand(self.source().file_id).unwrap();
37 let node = self.source().value.to_node(&root);
38 ast::RecordField::cast(node).unwrap()
39 }
40}
41
32#[derive(Debug)] 42#[derive(Debug)]
33pub struct MissingFields { 43pub struct MissingFields {
34 pub file: HirFileId, 44 pub file: HirFileId,
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index 9fd310f69..a9565a58d 100644
--- a/crates/ra_hir_ty/src/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -10,12 +10,12 @@ use hir_def::{
10 resolver::resolver_for_expr, 10 resolver::resolver_for_expr,
11 AdtId, AssocContainerId, FieldId, Lookup, 11 AdtId, AssocContainerId, FieldId, Lookup,
12}; 12};
13use hir_expand::name::Name; 13use hir_expand::name::{name, Name};
14use ra_syntax::ast::RangeOp; 14use ra_syntax::ast::RangeOp;
15 15
16use crate::{ 16use crate::{
17 autoderef, method_resolution, op, 17 autoderef, method_resolution, op,
18 traits::InEnvironment, 18 traits::{FnTrait, InEnvironment},
19 utils::{generics, variant_data, Generics}, 19 utils::{generics, variant_data, Generics},
20 ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Rawness, Substs, 20 ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Rawness, Substs,
21 TraitRef, Ty, TypeCtor, 21 TraitRef, Ty, TypeCtor,
@@ -63,6 +63,58 @@ impl<'a> InferenceContext<'a> {
63 self.resolve_ty_as_possible(ty) 63 self.resolve_ty_as_possible(ty)
64 } 64 }
65 65
66 fn callable_sig_from_fn_trait(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> {
67 let krate = self.resolver.krate()?;
68 let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?;
69 let output_assoc_type =
70 self.db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?;
71 let generic_params = generics(self.db.upcast(), fn_once_trait.into());
72 if generic_params.len() != 2 {
73 return None;
74 }
75
76 let mut param_builder = Substs::builder(num_args);
77 let mut arg_tys = vec![];
78 for _ in 0..num_args {
79 let arg = self.table.new_type_var();
80 param_builder = param_builder.push(arg.clone());
81 arg_tys.push(arg);
82 }
83 let parameters = param_builder.build();
84 let arg_ty = Ty::Apply(ApplicationTy {
85 ctor: TypeCtor::Tuple { cardinality: num_args as u16 },
86 parameters,
87 });
88 let substs = Substs::build_for_generics(&generic_params)
89 .push(ty.clone())
90 .push(arg_ty.clone())
91 .build();
92
93 let trait_env = Arc::clone(&self.trait_env);
94 let implements_fn_trait =
95 Obligation::Trait(TraitRef { trait_: fn_once_trait, substs: substs.clone() });
96 let goal = self.canonicalizer().canonicalize_obligation(InEnvironment {
97 value: implements_fn_trait.clone(),
98 environment: trait_env,
99 });
100 if self.db.trait_solve(krate, goal.value).is_some() {
101 self.obligations.push(implements_fn_trait);
102 let output_proj_ty =
103 crate::ProjectionTy { associated_ty: output_assoc_type, parameters: substs };
104 let return_ty = self.normalize_projection_ty(output_proj_ty);
105 Some((arg_tys, return_ty))
106 } else {
107 None
108 }
109 }
110
111 pub fn callable_sig(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> {
112 match ty.callable_sig(self.db) {
113 Some(sig) => Some((sig.params().to_vec(), sig.ret().clone())),
114 None => self.callable_sig_from_fn_trait(ty, num_args),
115 }
116 }
117
66 fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { 118 fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
67 let body = Arc::clone(&self.body); // avoid borrow checker problem 119 let body = Arc::clone(&self.body); // avoid borrow checker problem
68 let ty = match &body[tgt_expr] { 120 let ty = match &body[tgt_expr] {
@@ -198,14 +250,23 @@ impl<'a> InferenceContext<'a> {
198 } 250 }
199 Expr::Call { callee, args } => { 251 Expr::Call { callee, args } => {
200 let callee_ty = self.infer_expr(*callee, &Expectation::none()); 252 let callee_ty = self.infer_expr(*callee, &Expectation::none());
201 let (param_tys, ret_ty) = match callee_ty.callable_sig(self.db) { 253 let canonicalized = self.canonicalizer().canonicalize_ty(callee_ty.clone());
202 Some(sig) => (sig.params().to_vec(), sig.ret().clone()), 254 let mut derefs = autoderef(
203 None => { 255 self.db,
204 // Not callable 256 self.resolver.krate(),
205 // FIXME: report an error 257 InEnvironment {
206 (Vec::new(), Ty::Unknown) 258 value: canonicalized.value.clone(),
207 } 259 environment: self.trait_env.clone(),
208 }; 260 },
261 );
262 let (param_tys, ret_ty): (Vec<Ty>, Ty) = derefs
263 .find_map(|callee_deref_ty| {
264 self.callable_sig(
265 &canonicalized.decanonicalize_ty(callee_deref_ty.value),
266 args.len(),
267 )
268 })
269 .unwrap_or((Vec::new(), Ty::Unknown));
209 self.register_obligations_for_call(&callee_ty); 270 self.register_obligations_for_call(&callee_ty);
210 self.check_call_arguments(args, &param_tys); 271 self.check_call_arguments(args, &param_tys);
211 self.normalize_associated_types_in(ret_ty) 272 self.normalize_associated_types_in(ret_ty)
diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs
index 1ad0d8397..80d7ed10e 100644
--- a/crates/ra_hir_ty/src/infer/path.rs
+++ b/crates/ra_hir_ty/src/infer/path.rs
@@ -81,7 +81,7 @@ impl<'a> InferenceContext<'a> {
81 let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); 81 let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
82 let substs = Substs::type_params_for_generics(&generics); 82 let substs = Substs::type_params_for_generics(&generics);
83 let ty = self.db.impl_self_ty(impl_id).subst(&substs); 83 let ty = self.db.impl_self_ty(impl_id).subst(&substs);
84 if let Some((AdtId::StructId(struct_id), _)) = ty.as_adt() { 84 if let Some((AdtId::StructId(struct_id), substs)) = ty.as_adt() {
85 let ty = self.db.value_ty(struct_id.into()).subst(&substs); 85 let ty = self.db.value_ty(struct_id.into()).subst(&substs);
86 return Some(ty); 86 return Some(ty);
87 } else { 87 } else {
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index 2b9372b4b..f22232324 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -73,6 +73,7 @@ pub use lower::{
73pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; 73pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment};
74 74
75pub use chalk_ir::{BoundVar, DebruijnIndex}; 75pub use chalk_ir::{BoundVar, DebruijnIndex};
76use itertools::Itertools;
76 77
77/// A type constructor or type name: this might be something like the primitive 78/// A type constructor or type name: this might be something like the primitive
78/// type `bool`, a struct like `Vec`, or things like function pointers or 79/// type `bool`, a struct like `Vec`, or things like function pointers or
@@ -815,6 +816,11 @@ impl Ty {
815 } 816 }
816 } 817 }
817 818
819 /// If this is a `dyn Trait`, returns that trait.
820 pub fn dyn_trait(&self) -> Option<TraitId> {
821 self.dyn_trait_ref().map(|it| it.trait_)
822 }
823
818 fn builtin_deref(&self) -> Option<Ty> { 824 fn builtin_deref(&self) -> Option<Ty> {
819 match self { 825 match self {
820 Ty::Apply(a_ty) => match a_ty.ctor { 826 Ty::Apply(a_ty) => match a_ty.ctor {
@@ -867,13 +873,56 @@ impl Ty {
867 } 873 }
868 } 874 }
869 875
870 /// If this is a `dyn Trait`, returns that trait. 876 pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<GenericPredicate>> {
871 pub fn dyn_trait(&self) -> Option<TraitId> {
872 match self { 877 match self {
873 Ty::Dyn(predicates) => predicates.iter().find_map(|pred| match pred { 878 Ty::Opaque(opaque_ty) => {
874 GenericPredicate::Implemented(tr) => Some(tr.trait_), 879 let predicates = match opaque_ty.opaque_ty_id {
875 _ => None, 880 OpaqueTyId::ReturnTypeImplTrait(func, idx) => {
876 }), 881 db.return_type_impl_traits(func).map(|it| {
882 let data = (*it)
883 .as_ref()
884 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
885 data.clone().subst(&opaque_ty.parameters)
886 })
887 }
888 };
889
890 predicates.map(|it| it.value)
891 }
892 Ty::Placeholder(id) => {
893 let generic_params = db.generic_params(id.parent);
894 let param_data = &generic_params.types[id.local_id];
895 match param_data.provenance {
896 hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
897 let predicates = db
898 .generic_predicates_for_param(*id)
899 .into_iter()
900 .map(|pred| pred.value.clone())
901 .collect_vec();
902
903 Some(predicates)
904 }
905 _ => None,
906 }
907 }
908 _ => None,
909 }
910 }
911
912 pub fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId> {
913 match self {
914 Ty::Apply(ApplicationTy { ctor: TypeCtor::AssociatedType(type_alias_id), .. }) => {
915 match type_alias_id.lookup(db.upcast()).container {
916 AssocContainerId::TraitId(trait_id) => Some(trait_id),
917 _ => None,
918 }
919 }
920 Ty::Projection(projection_ty) => {
921 match projection_ty.associated_ty.lookup(db.upcast()).container {
922 AssocContainerId::TraitId(trait_id) => Some(trait_id),
923 _ => None,
924 }
925 }
877 _ => None, 926 _ => None,
878 } 927 }
879 } 928 }
@@ -1057,5 +1106,5 @@ pub struct ReturnTypeImplTraits {
1057 1106
1058#[derive(Clone, PartialEq, Eq, Debug, Hash)] 1107#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1059pub(crate) struct ReturnTypeImplTrait { 1108pub(crate) struct ReturnTypeImplTrait {
1060 pub(crate) bounds: Binders<Vec<GenericPredicate>>, 1109 pub bounds: Binders<Vec<GenericPredicate>>,
1061} 1110}
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index 42713928f..d5154f436 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -337,17 +337,17 @@ impl Ty {
337 TraitRef::from_resolved_path(ctx, trait_, resolved_segment, self_ty); 337 TraitRef::from_resolved_path(ctx, trait_, resolved_segment, self_ty);
338 let ty = if remaining_segments.len() == 1 { 338 let ty = if remaining_segments.len() == 1 {
339 let segment = remaining_segments.first().unwrap(); 339 let segment = remaining_segments.first().unwrap();
340 let associated_ty = associated_type_by_name_including_super_traits( 340 let found = associated_type_by_name_including_super_traits(
341 ctx.db.upcast(), 341 ctx.db,
342 trait_ref.trait_, 342 trait_ref.clone(),
343 &segment.name, 343 &segment.name,
344 ); 344 );
345 match associated_ty { 345 match found {
346 Some(associated_ty) => { 346 Some((super_trait_ref, associated_ty)) => {
347 // FIXME handle type parameters on the segment 347 // FIXME handle type parameters on the segment
348 Ty::Projection(ProjectionTy { 348 Ty::Projection(ProjectionTy {
349 associated_ty, 349 associated_ty,
350 parameters: trait_ref.substs, 350 parameters: super_trait_ref.substs,
351 }) 351 })
352 } 352 }
353 None => { 353 None => {
@@ -467,6 +467,9 @@ impl Ty {
467 } 467 }
468 TypeParamLoweringMode::Variable => t.substs.clone(), 468 TypeParamLoweringMode::Variable => t.substs.clone(),
469 }; 469 };
470 // We need to shift in the bound vars, since
471 // associated_type_shorthand_candidates does not do that
472 let substs = substs.shift_bound_vars(ctx.in_binders);
470 // FIXME handle type parameters on the segment 473 // FIXME handle type parameters on the segment
471 return Some(Ty::Projection(ProjectionTy { 474 return Some(Ty::Projection(ProjectionTy {
472 associated_ty, 475 associated_ty,
@@ -706,17 +709,17 @@ fn assoc_type_bindings_from_type_bound<'a>(
706 .flat_map(|segment| segment.args_and_bindings.into_iter()) 709 .flat_map(|segment| segment.args_and_bindings.into_iter())
707 .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) 710 .flat_map(|args_and_bindings| args_and_bindings.bindings.iter())
708 .flat_map(move |binding| { 711 .flat_map(move |binding| {
709 let associated_ty = associated_type_by_name_including_super_traits( 712 let found = associated_type_by_name_including_super_traits(
710 ctx.db.upcast(), 713 ctx.db,
711 trait_ref.trait_, 714 trait_ref.clone(),
712 &binding.name, 715 &binding.name,
713 ); 716 );
714 let associated_ty = match associated_ty { 717 let (super_trait_ref, associated_ty) = match found {
715 None => return SmallVec::<[GenericPredicate; 1]>::new(), 718 None => return SmallVec::<[GenericPredicate; 1]>::new(),
716 Some(t) => t, 719 Some(t) => t,
717 }; 720 };
718 let projection_ty = 721 let projection_ty =
719 ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() }; 722 ProjectionTy { associated_ty, parameters: super_trait_ref.substs.clone() };
720 let mut preds = SmallVec::with_capacity( 723 let mut preds = SmallVec::with_capacity(
721 binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(), 724 binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
722 ); 725 );
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index e83b39456..ed638c195 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -38,18 +38,53 @@ impl TyFingerprint {
38 } 38 }
39} 39}
40 40
41/// A queryable and mergeable collection of impls.
41#[derive(Debug, PartialEq, Eq)] 42#[derive(Debug, PartialEq, Eq)]
42pub struct CrateImplDefs { 43pub struct CrateImplDefs {
43 impls: FxHashMap<TyFingerprint, Vec<ImplId>>, 44 inherent_impls: FxHashMap<TyFingerprint, Vec<ImplId>>,
44 impls_by_trait: FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Vec<ImplId>>>, 45 impls_by_trait: FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Vec<ImplId>>>,
45} 46}
46 47
47impl CrateImplDefs { 48impl CrateImplDefs {
48 pub(crate) fn impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<CrateImplDefs> { 49 pub(crate) fn impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<CrateImplDefs> {
49 let _p = profile("impls_in_crate_query"); 50 let _p = profile("impls_in_crate_query");
50 let mut res = 51 let mut res = CrateImplDefs {
51 CrateImplDefs { impls: FxHashMap::default(), impls_by_trait: FxHashMap::default() }; 52 inherent_impls: FxHashMap::default(),
53 impls_by_trait: FxHashMap::default(),
54 };
55 res.fill(db, krate);
56
57 Arc::new(res)
58 }
59
60 /// Collects all impls from transitive dependencies of `krate` that may be used by `krate`.
61 ///
62 /// The full set of impls that can be used by `krate` is the returned map plus all the impls
63 /// from `krate` itself.
64 pub(crate) fn impls_from_deps_query(
65 db: &dyn HirDatabase,
66 krate: CrateId,
67 ) -> Arc<CrateImplDefs> {
68 let _p = profile("impls_from_deps_query");
69 let crate_graph = db.crate_graph();
70 let mut res = CrateImplDefs {
71 inherent_impls: FxHashMap::default(),
72 impls_by_trait: FxHashMap::default(),
73 };
52 74
75 // For each dependency, calculate `impls_from_deps` recursively, then add its own
76 // `impls_in_crate`.
77 // As we might visit crates multiple times, `merge` has to deduplicate impls to avoid
78 // wasting memory.
79 for dep in &crate_graph[krate].dependencies {
80 res.merge(&db.impls_from_deps(dep.crate_id));
81 res.merge(&db.impls_in_crate(dep.crate_id));
82 }
83
84 Arc::new(res)
85 }
86
87 fn fill(&mut self, db: &dyn HirDatabase, krate: CrateId) {
53 let crate_def_map = db.crate_def_map(krate); 88 let crate_def_map = db.crate_def_map(krate);
54 for (_module_id, module_data) in crate_def_map.modules.iter() { 89 for (_module_id, module_data) in crate_def_map.modules.iter() {
55 for impl_id in module_data.scope.impls() { 90 for impl_id in module_data.scope.impls() {
@@ -57,7 +92,7 @@ impl CrateImplDefs {
57 Some(tr) => { 92 Some(tr) => {
58 let self_ty = db.impl_self_ty(impl_id); 93 let self_ty = db.impl_self_ty(impl_id);
59 let self_ty_fp = TyFingerprint::for_impl(&self_ty.value); 94 let self_ty_fp = TyFingerprint::for_impl(&self_ty.value);
60 res.impls_by_trait 95 self.impls_by_trait
61 .entry(tr.value.trait_) 96 .entry(tr.value.trait_)
62 .or_default() 97 .or_default()
63 .entry(self_ty_fp) 98 .entry(self_ty_fp)
@@ -67,18 +102,36 @@ impl CrateImplDefs {
67 None => { 102 None => {
68 let self_ty = db.impl_self_ty(impl_id); 103 let self_ty = db.impl_self_ty(impl_id);
69 if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty.value) { 104 if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty.value) {
70 res.impls.entry(self_ty_fp).or_default().push(impl_id); 105 self.inherent_impls.entry(self_ty_fp).or_default().push(impl_id);
71 } 106 }
72 } 107 }
73 } 108 }
74 } 109 }
75 } 110 }
111 }
76 112
77 Arc::new(res) 113 fn merge(&mut self, other: &Self) {
114 for (fp, impls) in &other.inherent_impls {
115 let vec = self.inherent_impls.entry(*fp).or_default();
116 vec.extend(impls);
117 vec.sort();
118 vec.dedup();
119 }
120
121 for (trait_, other_map) in &other.impls_by_trait {
122 let map = self.impls_by_trait.entry(*trait_).or_default();
123 for (fp, impls) in other_map {
124 let vec = map.entry(*fp).or_default();
125 vec.extend(impls);
126 vec.sort();
127 vec.dedup();
128 }
129 }
78 } 130 }
131
79 pub fn lookup_impl_defs(&self, ty: &Ty) -> impl Iterator<Item = ImplId> + '_ { 132 pub fn lookup_impl_defs(&self, ty: &Ty) -> impl Iterator<Item = ImplId> + '_ {
80 let fingerprint = TyFingerprint::for_impl(ty); 133 let fingerprint = TyFingerprint::for_impl(ty);
81 fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flatten().copied() 134 fingerprint.and_then(|f| self.inherent_impls.get(&f)).into_iter().flatten().copied()
82 } 135 }
83 136
84 pub fn lookup_impl_defs_for_trait(&self, tr: TraitId) -> impl Iterator<Item = ImplId> + '_ { 137 pub fn lookup_impl_defs_for_trait(&self, tr: TraitId) -> impl Iterator<Item = ImplId> + '_ {
@@ -110,7 +163,7 @@ impl CrateImplDefs {
110 } 163 }
111 164
112 pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplId> + 'a { 165 pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplId> + 'a {
113 self.impls 166 self.inherent_impls
114 .values() 167 .values()
115 .chain(self.impls_by_trait.values().flat_map(|m| m.values())) 168 .chain(self.impls_by_trait.values().flat_map(|m| m.values()))
116 .flatten() 169 .flatten()
diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs
index 1f004bd63..4da2e972b 100644
--- a/crates/ra_hir_ty/src/tests/regression.rs
+++ b/crates/ra_hir_ty/src/tests/regression.rs
@@ -633,3 +633,154 @@ where
633 "### 633 "###
634 ); 634 );
635} 635}
636
637#[test]
638fn issue_4953() {
639 assert_snapshot!(
640 infer(r#"
641pub struct Foo(pub i64);
642impl Foo {
643 fn test() -> Self { Self(0i64) }
644}
645"#),
646 @r###"
647 59..73 '{ Self(0i64) }': Foo
648 61..65 'Self': Foo(i64) -> Foo
649 61..71 'Self(0i64)': Foo
650 66..70 '0i64': i64
651 "###
652 );
653 assert_snapshot!(
654 infer(r#"
655pub struct Foo<T>(pub T);
656impl Foo<i64> {
657 fn test() -> Self { Self(0i64) }
658}
659"#),
660 @r###"
661 65..79 '{ Self(0i64) }': Foo<i64>
662 67..71 'Self': Foo<i64>(i64) -> Foo<i64>
663 67..77 'Self(0i64)': Foo<i64>
664 72..76 '0i64': i64
665 "###
666 );
667}
668
669#[test]
670fn issue_4931() {
671 assert_snapshot!(
672 infer(r#"
673trait Div<T> {
674 type Output;
675}
676
677trait CheckedDiv: Div<()> {}
678
679trait PrimInt: CheckedDiv<Output = ()> {
680 fn pow(self);
681}
682
683fn check<T: PrimInt>(i: T) {
684 i.pow();
685}
686"#),
687 @r###"
688 118..122 'self': Self
689 149..150 'i': T
690 155..171 '{ ...w(); }': ()
691 161..162 'i': T
692 161..168 'i.pow()': ()
693 "###
694 );
695}
696
697#[test]
698fn issue_4885() {
699 assert_snapshot!(
700 infer(r#"
701#[lang = "coerce_unsized"]
702pub trait CoerceUnsized<T> {}
703
704trait Future {
705 type Output;
706}
707trait Foo<R> {
708 type Bar;
709}
710fn foo<R, K>(key: &K) -> impl Future<Output = K::Bar>
711where
712 K: Foo<R>,
713{
714 bar(key)
715}
716fn bar<R, K>(key: &K) -> impl Future<Output = K::Bar>
717where
718 K: Foo<R>,
719{
720}
721"#),
722 @r###"
723 137..140 'key': &K
724 199..215 '{ ...key) }': impl Future<Output = <K as Foo<R>>::Bar>
725 205..208 'bar': fn bar<R, K>(&K) -> impl Future<Output = <K as Foo<R>>::Bar>
726 205..213 'bar(key)': impl Future<Output = <K as Foo<R>>::Bar>
727 209..212 'key': &K
728 229..232 'key': &K
729 291..294 '{ }': ()
730 "###
731 );
732}
733
734#[test]
735fn issue_4800() {
736 assert_snapshot!(
737 infer(r#"
738trait Debug {}
739
740struct Foo<T>;
741
742type E1<T> = (T, T, T);
743type E2<T> = E1<E1<E1<(T, T, T)>>>;
744
745impl Debug for Foo<E2<()>> {}
746
747struct Request;
748
749pub trait Future {
750 type Output;
751}
752
753pub struct PeerSet<D>;
754
755impl<D> Service<Request> for PeerSet<D>
756where
757 D: Discover,
758 D::Key: Debug,
759{
760 type Error = ();
761 type Future = dyn Future<Output = Self::Error>;
762
763 fn call(&mut self) -> Self::Future {
764 loop {}
765 }
766}
767
768pub trait Discover {
769 type Key;
770}
771
772pub trait Service<Request> {
773 type Error;
774 type Future: Future<Output = Self::Error>;
775 fn call(&mut self) -> Self::Future;
776}
777"#),
778 @r###"
779 380..384 'self': &mut PeerSet<D>
780 402..425 '{ ... }': dyn Future<Output = ()>
781 412..419 'loop {}': !
782 417..419 '{}': ()
783 576..580 'self': &mut Self
784 "###
785 );
786}
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index e81193a3c..961be4abd 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -2888,3 +2888,226 @@ impl<A: Step> iter::Iterator for ops::Range<A> {
2888 ); 2888 );
2889 assert_eq!(t, "i32"); 2889 assert_eq!(t, "i32");
2890} 2890}
2891
2892#[test]
2893fn infer_closure_arg() {
2894 assert_snapshot!(
2895 infer(
2896 r#"
2897 //- /lib.rs
2898
2899 enum Option<T> {
2900 None,
2901 Some(T)
2902 }
2903
2904 fn foo() {
2905 let s = Option::None;
2906 let f = |x: Option<i32>| {};
2907 (&f)(s)
2908 }
2909 "#
2910 ),
2911 @r###"
2912 137..259 '{ ... }': ()
2913 159..160 's': Option<i32>
2914 163..175 'Option::None': Option<i32>
2915 197..198 'f': |Option<i32>| -> ()
2916 201..220 '|x: Op...2>| {}': |Option<i32>| -> ()
2917 202..203 'x': Option<i32>
2918 218..220 '{}': ()
2919 238..245 '(&f)(s)': ()
2920 239..241 '&f': &|Option<i32>| -> ()
2921 240..241 'f': |Option<i32>| -> ()
2922 243..244 's': Option<i32>
2923 "###
2924 );
2925}
2926
2927#[test]
2928fn infer_fn_trait_arg() {
2929 assert_snapshot!(
2930 infer(
2931 r#"
2932 //- /lib.rs deps:std
2933
2934 #[lang = "fn_once"]
2935 pub trait FnOnce<Args> {
2936 type Output;
2937
2938 extern "rust-call" fn call_once(&self, args: Args) -> Self::Output;
2939 }
2940
2941 #[lang = "fn"]
2942 pub trait Fn<Args>:FnOnce<Args> {
2943 extern "rust-call" fn call(&self, args: Args) -> Self::Output;
2944 }
2945
2946 enum Option<T> {
2947 None,
2948 Some(T)
2949 }
2950
2951 fn foo<F, T>(f: F) -> T
2952 where
2953 F: Fn(Option<i32>) -> T,
2954 {
2955 let s = None;
2956 f(s)
2957 }
2958 "#
2959 ),
2960 @r###"
2961 183..187 'self': &Self
2962 189..193 'args': Args
2963 350..354 'self': &Self
2964 356..360 'args': Args
2965 515..516 'f': F
2966 597..663 '{ ... }': T
2967 619..620 's': Option<i32>
2968 623..627 'None': Option<i32>
2969 645..646 'f': F
2970 645..649 'f(s)': T
2971 647..648 's': Option<i32>
2972 "###
2973 );
2974}
2975
2976#[test]
2977fn infer_box_fn_arg() {
2978 assert_snapshot!(
2979 infer(
2980 r#"
2981 //- /lib.rs deps:std
2982
2983 #[lang = "fn_once"]
2984 pub trait FnOnce<Args> {
2985 type Output;
2986
2987 extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
2988 }
2989
2990 #[lang = "deref"]
2991 pub trait Deref {
2992 type Target: ?Sized;
2993
2994 fn deref(&self) -> &Self::Target;
2995 }
2996
2997 #[lang = "owned_box"]
2998 pub struct Box<T: ?Sized> {
2999 inner: *mut T,
3000 }
3001
3002 impl<T: ?Sized> Deref for Box<T> {
3003 type Target = T;
3004
3005 fn deref(&self) -> &T {
3006 &self.inner
3007 }
3008 }
3009
3010 enum Option<T> {
3011 None,
3012 Some(T)
3013 }
3014
3015 fn foo() {
3016 let s = Option::None;
3017 let f: Box<dyn FnOnce(&Option<i32>)> = box (|ps| {});
3018 f(&s)
3019 }
3020 "#
3021 ),
3022 @r###"
3023 182..186 'self': Self
3024 188..192 'args': Args
3025 356..360 'self': &Self
3026 622..626 'self': &Box<T>
3027 634..685 '{ ... }': &T
3028 656..667 '&self.inner': &*mut T
3029 657..661 'self': &Box<T>
3030 657..667 'self.inner': *mut T
3031 812..957 '{ ... }': FnOnce::Output<dyn FnOnce<(&Option<i32>,)>, (&Option<i32>,)>
3032 834..835 's': Option<i32>
3033 838..850 'Option::None': Option<i32>
3034 872..873 'f': Box<dyn FnOnce<(&Option<i32>,)>>
3035 907..920 'box (|ps| {})': Box<|{unknown}| -> ()>
3036 912..919 '|ps| {}': |{unknown}| -> ()
3037 913..915 'ps': {unknown}
3038 917..919 '{}': ()
3039 938..939 'f': Box<dyn FnOnce<(&Option<i32>,)>>
3040 938..943 'f(&s)': FnOnce::Output<dyn FnOnce<(&Option<i32>,)>, (&Option<i32>,)>
3041 940..942 '&s': &Option<i32>
3042 941..942 's': Option<i32>
3043 "###
3044 );
3045}
3046
3047#[test]
3048fn infer_dyn_fn_output() {
3049 assert_snapshot!(
3050 infer(
3051 r#"
3052 //- /lib.rs deps:std
3053
3054 #[lang = "fn_once"]
3055 pub trait FnOnce<Args> {
3056 type Output;
3057
3058 extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
3059 }
3060
3061 #[lang = "fn"]
3062 pub trait Fn<Args>:FnOnce<Args> {
3063 extern "rust-call" fn call(&self, args: Args) -> Self::Output;
3064 }
3065
3066 #[lang = "deref"]
3067 pub trait Deref {
3068 type Target: ?Sized;
3069
3070 fn deref(&self) -> &Self::Target;
3071 }
3072
3073 #[lang = "owned_box"]
3074 pub struct Box<T: ?Sized> {
3075 inner: *mut T,
3076 }
3077
3078 impl<T: ?Sized> Deref for Box<T> {
3079 type Target = T;
3080
3081 fn deref(&self) -> &T {
3082 &self.inner
3083 }
3084 }
3085
3086 fn foo() {
3087 let f: Box<dyn Fn() -> i32> = box(|| 5);
3088 let x = f();
3089 }
3090 "#
3091 ),
3092 @r###"
3093 182..186 'self': Self
3094 188..192 'args': Args
3095 349..353 'self': &Self
3096 355..359 'args': Args
3097 523..527 'self': &Self
3098 789..793 'self': &Box<T>
3099 801..852 '{ ... }': &T
3100 823..834 '&self.inner': &*mut T
3101 824..828 'self': &Box<T>
3102 824..834 'self.inner': *mut T
3103 889..990 '{ ... }': ()
3104 911..912 'f': Box<dyn Fn<(), Output = i32>>
3105 937..946 'box(|| 5)': Box<|| -> i32>
3106 941..945 '|| 5': || -> i32
3107 944..945 '5': i32
3108 968..969 'x': FnOnce::Output<dyn Fn<(), Output = i32>, ()>
3109 972..973 'f': Box<dyn Fn<(), Output = i32>>
3110 972..975 'f()': FnOnce::Output<dyn Fn<(), Output = i32>, ()>
3111 "###
3112 );
3113}
diff --git a/crates/ra_hir_ty/src/traits.rs b/crates/ra_hir_ty/src/traits.rs
index 6bc6d474c..6f43c3a22 100644
--- a/crates/ra_hir_ty/src/traits.rs
+++ b/crates/ra_hir_ty/src/traits.rs
@@ -2,12 +2,13 @@
2use std::{panic, sync::Arc}; 2use std::{panic, sync::Arc};
3 3
4use chalk_ir::cast::Cast; 4use chalk_ir::cast::Cast;
5use hir_def::{expr::ExprId, DefWithBodyId, ImplId, TraitId, TypeAliasId}; 5use hir_def::{
6 expr::ExprId, lang_item::LangItemTarget, DefWithBodyId, ImplId, TraitId, TypeAliasId,
7};
6use ra_db::{impl_intern_key, salsa, CrateId}; 8use ra_db::{impl_intern_key, salsa, CrateId};
7use ra_prof::profile; 9use ra_prof::profile;
8use rustc_hash::FxHashSet;
9 10
10use crate::{db::HirDatabase, method_resolution::TyFingerprint, DebruijnIndex}; 11use crate::{db::HirDatabase, DebruijnIndex};
11 12
12use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; 13use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk};
13 14
@@ -36,34 +37,6 @@ fn create_chalk_solver() -> chalk_solve::Solver<Interner> {
36 solver_choice.into_solver() 37 solver_choice.into_solver()
37} 38}
38 39
39/// Collects impls for the given trait in the whole dependency tree of `krate`.
40pub(crate) fn impls_for_trait_query(
41 db: &dyn HirDatabase,
42 krate: CrateId,
43 trait_: TraitId,
44 self_ty_fp: Option<TyFingerprint>,
45) -> Arc<[ImplId]> {
46 // FIXME: We could be a lot smarter here - because of the orphan rules and
47 // the fact that the trait and the self type need to be in the dependency
48 // tree of a crate somewhere for an impl to exist, we could skip looking in
49 // a lot of crates completely
50 let mut impls = FxHashSet::default();
51 // We call the query recursively here. On the one hand, this means we can
52 // reuse results from queries for different crates; on the other hand, this
53 // will only ever get called for a few crates near the root of the tree (the
54 // ones the user is editing), so this may actually be a waste of memory. I'm
55 // doing it like this mainly for simplicity for now.
56 for dep in &db.crate_graph()[krate].dependencies {
57 impls.extend(db.impls_for_trait(dep.crate_id, trait_, self_ty_fp).iter());
58 }
59 let crate_impl_defs = db.impls_in_crate(krate);
60 match self_ty_fp {
61 Some(fp) => impls.extend(crate_impl_defs.lookup_impl_defs_for_trait_and_ty(trait_, fp)),
62 None => impls.extend(crate_impl_defs.lookup_impl_defs_for_trait(trait_)),
63 }
64 impls.into_iter().collect()
65}
66
67/// A set of clauses that we assume to be true. E.g. if we are inside this function: 40/// A set of clauses that we assume to be true. E.g. if we are inside this function:
68/// ```rust 41/// ```rust
69/// fn foo<T: Default>(t: T) {} 42/// fn foo<T: Default>(t: T) {}
@@ -298,6 +271,14 @@ impl FnTrait {
298 FnTrait::Fn => "fn", 271 FnTrait::Fn => "fn",
299 } 272 }
300 } 273 }
274
275 pub fn get_id(&self, db: &dyn HirDatabase, krate: CrateId) -> Option<TraitId> {
276 let target = db.lang_item(krate, self.lang_item_name().into())?;
277 match target {
278 LangItemTarget::TraitId(t) => Some(t),
279 _ => None,
280 }
281 }
301} 282}
302 283
303#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 284#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs
index 88a422d2c..6d5f2d46a 100644
--- a/crates/ra_hir_ty/src/traits/builtin.rs
+++ b/crates/ra_hir_ty/src/traits/builtin.rs
@@ -40,7 +40,7 @@ pub(super) fn get_builtin_impls(
40 if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { def, expr }, .. }) = ty { 40 if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { def, expr }, .. }) = ty {
41 for &fn_trait in [super::FnTrait::FnOnce, super::FnTrait::FnMut, super::FnTrait::Fn].iter() 41 for &fn_trait in [super::FnTrait::FnOnce, super::FnTrait::FnMut, super::FnTrait::Fn].iter()
42 { 42 {
43 if let Some(actual_trait) = get_fn_trait(db, krate, fn_trait) { 43 if let Some(actual_trait) = fn_trait.get_id(db, krate) {
44 if trait_ == actual_trait { 44 if trait_ == actual_trait {
45 let impl_ = super::ClosureFnTraitImplData { def: *def, expr: *expr, fn_trait }; 45 let impl_ = super::ClosureFnTraitImplData { def: *def, expr: *expr, fn_trait };
46 if check_closure_fn_trait_impl_prerequisites(db, krate, impl_) { 46 if check_closure_fn_trait_impl_prerequisites(db, krate, impl_) {
@@ -128,7 +128,7 @@ fn check_closure_fn_trait_impl_prerequisites(
128 data: super::ClosureFnTraitImplData, 128 data: super::ClosureFnTraitImplData,
129) -> bool { 129) -> bool {
130 // the respective Fn/FnOnce/FnMut trait needs to exist 130 // the respective Fn/FnOnce/FnMut trait needs to exist
131 if get_fn_trait(db, krate, data.fn_trait).is_none() { 131 if data.fn_trait.get_id(db, krate).is_none() {
132 return false; 132 return false;
133 } 133 }
134 134
@@ -136,7 +136,7 @@ fn check_closure_fn_trait_impl_prerequisites(
136 // the traits having no type params, FnOnce being a supertrait 136 // the traits having no type params, FnOnce being a supertrait
137 137
138 // the FnOnce trait needs to exist and have an assoc type named Output 138 // the FnOnce trait needs to exist and have an assoc type named Output
139 let fn_once_trait = match get_fn_trait(db, krate, super::FnTrait::FnOnce) { 139 let fn_once_trait = match (super::FnTrait::FnOnce).get_id(db, krate) {
140 Some(t) => t, 140 Some(t) => t,
141 None => return false, 141 None => return false,
142 }; 142 };
@@ -151,7 +151,9 @@ fn closure_fn_trait_impl_datum(
151 // for some closure |X, Y| -> Z: 151 // for some closure |X, Y| -> Z:
152 // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V } 152 // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V }
153 153
154 let trait_ = get_fn_trait(db, krate, data.fn_trait) // get corresponding fn trait 154 let trait_ = data
155 .fn_trait
156 .get_id(db, krate) // get corresponding fn trait
155 // the existence of the Fn trait has been checked before 157 // the existence of the Fn trait has been checked before
156 .expect("fn trait for closure impl missing"); 158 .expect("fn trait for closure impl missing");
157 159
@@ -211,7 +213,7 @@ fn closure_fn_trait_output_assoc_ty_value(
211 let output_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, num_args.into())); 213 let output_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, num_args.into()));
212 214
213 let fn_once_trait = 215 let fn_once_trait =
214 get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist"); 216 (super::FnTrait::FnOnce).get_id(db, krate).expect("assoc ty value should not exist");
215 217
216 let output_ty_id = db 218 let output_ty_id = db
217 .trait_data(fn_once_trait) 219 .trait_data(fn_once_trait)
@@ -360,14 +362,6 @@ fn super_trait_object_unsize_impl_datum(
360 BuiltinImplData { num_vars, trait_ref, where_clauses: Vec::new(), assoc_ty_values: Vec::new() } 362 BuiltinImplData { num_vars, trait_ref, where_clauses: Vec::new(), assoc_ty_values: Vec::new() }
361} 363}
362 364
363fn get_fn_trait(db: &dyn HirDatabase, krate: CrateId, fn_trait: super::FnTrait) -> Option<TraitId> {
364 let target = db.lang_item(krate, fn_trait.lang_item_name().into())?;
365 match target {
366 LangItemTarget::TraitId(t) => Some(t),
367 _ => None,
368 }
369}
370
371fn get_unsize_trait(db: &dyn HirDatabase, krate: CrateId) -> Option<TraitId> { 365fn get_unsize_trait(db: &dyn HirDatabase, krate: CrateId) -> Option<TraitId> {
372 let target = db.lang_item(krate, "unsize".into())?; 366 let target = db.lang_item(krate, "unsize".into())?;
373 match target { 367 match target {
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs
index a72a82f5a..2f35d6d49 100644
--- a/crates/ra_hir_ty/src/traits/chalk.rs
+++ b/crates/ra_hir_ty/src/traits/chalk.rs
@@ -74,14 +74,26 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
74 // Note: Since we're using impls_for_trait, only impls where the trait 74 // Note: Since we're using impls_for_trait, only impls where the trait
75 // can be resolved should ever reach Chalk. `impl_datum` relies on that 75 // can be resolved should ever reach Chalk. `impl_datum` relies on that
76 // and will panic if the trait can't be resolved. 76 // and will panic if the trait can't be resolved.
77 let mut result: Vec<_> = self 77 let in_deps = self.db.impls_from_deps(self.krate);
78 .db 78 let in_self = self.db.impls_in_crate(self.krate);
79 .impls_for_trait(self.krate, trait_, self_ty_fp) 79 let impl_maps = [in_deps, in_self];
80 .iter() 80
81 .copied() 81 let id_to_chalk = |id: hir_def::ImplId| Impl::ImplDef(id).to_chalk(self.db);
82 .map(Impl::ImplDef) 82
83 .map(|impl_| impl_.to_chalk(self.db)) 83 let mut result: Vec<_> = match self_ty_fp {
84 .collect(); 84 Some(fp) => impl_maps
85 .iter()
86 .flat_map(|crate_impl_defs| {
87 crate_impl_defs.lookup_impl_defs_for_trait_and_ty(trait_, fp).map(id_to_chalk)
88 })
89 .collect(),
90 None => impl_maps
91 .iter()
92 .flat_map(|crate_impl_defs| {
93 crate_impl_defs.lookup_impl_defs_for_trait(trait_).map(id_to_chalk)
94 })
95 .collect(),
96 };
85 97
86 let arg: Option<Ty> = 98 let arg: Option<Ty> =
87 parameters.get(1).map(|p| from_chalk(self.db, p.assert_ty_ref(&Interner).clone())); 99 parameters.get(1).map(|p| from_chalk(self.db, p.assert_ty_ref(&Interner).clone()));
diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs
index f98350bf9..c45820ff0 100644
--- a/crates/ra_hir_ty/src/utils.rs
+++ b/crates/ra_hir_ty/src/utils.rs
@@ -143,13 +143,14 @@ pub(super) fn find_super_trait_path(
143} 143}
144 144
145pub(super) fn associated_type_by_name_including_super_traits( 145pub(super) fn associated_type_by_name_including_super_traits(
146 db: &dyn DefDatabase, 146 db: &dyn HirDatabase,
147 trait_: TraitId, 147 trait_ref: TraitRef,
148 name: &Name, 148 name: &Name,
149) -> Option<TypeAliasId> { 149) -> Option<(TraitRef, TypeAliasId)> {
150 all_super_traits(db, trait_) 150 all_super_trait_refs(db, trait_ref).into_iter().find_map(|t| {
151 .into_iter() 151 let assoc_type = db.trait_data(t.trait_).associated_type_by_name(name)?;
152 .find_map(|t| db.trait_data(t).associated_type_by_name(name)) 152 Some((t, assoc_type))
153 })
153} 154}
154 155
155pub(super) fn variant_data(db: &dyn DefDatabase, var: VariantId) -> Arc<VariantData> { 156pub(super) fn variant_data(db: &dyn DefDatabase, var: VariantId) -> Arc<VariantData> {
@@ -176,6 +177,7 @@ pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
176 Generics { def, params: db.generic_params(def), parent_generics } 177 Generics { def, params: db.generic_params(def), parent_generics }
177} 178}
178 179
180#[derive(Debug)]
179pub(crate) struct Generics { 181pub(crate) struct Generics {
180 def: GenericDefId, 182 def: GenericDefId,
181 pub(crate) params: Arc<GenericParams>, 183 pub(crate) params: Arc<GenericParams>,