diff options
Diffstat (limited to 'crates/ra_hir_ty/src')
-rw-r--r-- | crates/ra_hir_ty/src/autoderef.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/expr.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer.rs | 67 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/expr.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/path.rs | 25 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/lower.rs | 70 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/marks.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/traits.rs | 65 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/builtin.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/utils.rs | 9 |
10 files changed, 171 insertions, 85 deletions
diff --git a/crates/ra_hir_ty/src/autoderef.rs b/crates/ra_hir_ty/src/autoderef.rs index d557962b4..ee48fa537 100644 --- a/crates/ra_hir_ty/src/autoderef.rs +++ b/crates/ra_hir_ty/src/autoderef.rs | |||
@@ -6,7 +6,7 @@ | |||
6 | use std::iter::successors; | 6 | use std::iter::successors; |
7 | 7 | ||
8 | use hir_def::lang_item::LangItemTarget; | 8 | use hir_def::lang_item::LangItemTarget; |
9 | use hir_expand::name; | 9 | use hir_expand::name::name; |
10 | use log::{info, warn}; | 10 | use log::{info, warn}; |
11 | use ra_db::CrateId; | 11 | use ra_db::CrateId; |
12 | 12 | ||
@@ -52,7 +52,7 @@ fn deref_by_trait( | |||
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 = generics(db, target.into()); | 57 | let generic_params = generics(db, target.into()); |
58 | if generic_params.len() != 1 { | 58 | if generic_params.len() != 1 { |
diff --git a/crates/ra_hir_ty/src/expr.rs b/crates/ra_hir_ty/src/expr.rs index d2bd64e5c..f752a9f09 100644 --- a/crates/ra_hir_ty/src/expr.rs +++ b/crates/ra_hir_ty/src/expr.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use hir_def::{ | 5 | use hir_def::{ |
6 | path::{known, Path}, | 6 | path::{path, Path}, |
7 | resolver::HasResolver, | 7 | resolver::HasResolver, |
8 | AdtId, FunctionId, | 8 | AdtId, FunctionId, |
9 | }; | 9 | }; |
@@ -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) { |
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index a1201b3e4..98ba05fc2 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs | |||
@@ -24,14 +24,15 @@ use hir_def::{ | |||
24 | body::Body, | 24 | body::Body, |
25 | data::{ConstData, FunctionData}, | 25 | data::{ConstData, FunctionData}, |
26 | expr::{BindingAnnotation, ExprId, PatId}, | 26 | expr::{BindingAnnotation, ExprId, PatId}, |
27 | path::{known, Path}, | 27 | path::{path, Path}, |
28 | resolver::{HasResolver, Resolver, TypeNs}, | 28 | resolver::{HasResolver, Resolver, TypeNs}, |
29 | type_ref::{Mutability, TypeRef}, | 29 | type_ref::{Mutability, TypeRef}, |
30 | AdtId, AssocItemId, DefWithBodyId, FunctionId, StructFieldId, TypeAliasId, VariantId, | 30 | AdtId, AssocItemId, DefWithBodyId, FunctionId, StructFieldId, TypeAliasId, VariantId, |
31 | }; | 31 | }; |
32 | use hir_expand::{diagnostics::DiagnosticSink, name}; | 32 | use hir_expand::{diagnostics::DiagnosticSink, name::name}; |
33 | use ra_arena::map::ArenaMap; | 33 | use ra_arena::map::ArenaMap; |
34 | use ra_prof::profile; | 34 | use ra_prof::profile; |
35 | use test_utils::tested_by; | ||
35 | 36 | ||
36 | use super::{ | 37 | use super::{ |
37 | primitive::{FloatTy, IntTy}, | 38 | primitive::{FloatTy, IntTy}, |
@@ -274,6 +275,29 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
274 | self.normalize_associated_types_in(ty) | 275 | self.normalize_associated_types_in(ty) |
275 | } | 276 | } |
276 | 277 | ||
278 | /// Replaces `impl Trait` in `ty` by type variables and obligations for | ||
279 | /// those variables. This is done for function arguments when calling a | ||
280 | /// function, and for return types when inside the function body, i.e. in | ||
281 | /// the cases where the `impl Trait` is 'transparent'. In other cases, `impl | ||
282 | /// Trait` is represented by `Ty::Opaque`. | ||
283 | fn insert_vars_for_impl_trait(&mut self, ty: Ty) -> Ty { | ||
284 | ty.fold(&mut |ty| match ty { | ||
285 | Ty::Opaque(preds) => { | ||
286 | tested_by!(insert_vars_for_impl_trait); | ||
287 | let var = self.table.new_type_var(); | ||
288 | let var_subst = Substs::builder(1).push(var.clone()).build(); | ||
289 | self.obligations.extend( | ||
290 | preds | ||
291 | .iter() | ||
292 | .map(|pred| pred.clone().subst_bound_vars(&var_subst)) | ||
293 | .filter_map(Obligation::from_predicate), | ||
294 | ); | ||
295 | var | ||
296 | } | ||
297 | _ => ty, | ||
298 | }) | ||
299 | } | ||
300 | |||
277 | /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. | 301 | /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. |
278 | fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { | 302 | fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { |
279 | match ty { | 303 | match ty { |
@@ -386,7 +410,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
386 | let resolver = &self.resolver; | 410 | let resolver = &self.resolver; |
387 | // FIXME: this should resolve assoc items as well, see this example: | 411 | // FIXME: this should resolve assoc items as well, see this example: |
388 | // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521 | 412 | // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521 |
389 | match resolver.resolve_path_in_type_ns_fully(self.db, &path) { | 413 | match resolver.resolve_path_in_type_ns_fully(self.db, path.mod_path()) { |
390 | Some(TypeNs::AdtId(AdtId::StructId(strukt))) => { | 414 | Some(TypeNs::AdtId(AdtId::StructId(strukt))) => { |
391 | let substs = Ty::substs_from_path(self.db, resolver, path, strukt.into()); | 415 | let substs = Ty::substs_from_path(self.db, resolver, path, strukt.into()); |
392 | let ty = self.db.ty(strukt.into()); | 416 | let ty = self.db.ty(strukt.into()); |
@@ -414,7 +438,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
414 | 438 | ||
415 | self.infer_pat(*pat, &ty, BindingMode::default()); | 439 | self.infer_pat(*pat, &ty, BindingMode::default()); |
416 | } | 440 | } |
417 | self.return_ty = self.make_ty(&data.ret_type); | 441 | let return_ty = self.make_ty(&data.ret_type); |
442 | self.return_ty = self.insert_vars_for_impl_trait(return_ty); | ||
418 | } | 443 | } |
419 | 444 | ||
420 | fn infer_body(&mut self) { | 445 | fn infer_body(&mut self) { |
@@ -422,73 +447,73 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
422 | } | 447 | } |
423 | 448 | ||
424 | fn resolve_into_iter_item(&self) -> Option<TypeAliasId> { | 449 | fn resolve_into_iter_item(&self) -> Option<TypeAliasId> { |
425 | let path = known::std_iter_into_iterator(); | 450 | let path = path![std::iter::IntoIterator]; |
426 | let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; | 451 | let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; |
427 | self.db.trait_data(trait_).associated_type_by_name(&name::ITEM_TYPE) | 452 | self.db.trait_data(trait_).associated_type_by_name(&name![Item]) |
428 | } | 453 | } |
429 | 454 | ||
430 | fn resolve_ops_try_ok(&self) -> Option<TypeAliasId> { | 455 | fn resolve_ops_try_ok(&self) -> Option<TypeAliasId> { |
431 | let path = known::std_ops_try(); | 456 | let path = path![std::ops::Try]; |
432 | let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; | 457 | let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; |
433 | self.db.trait_data(trait_).associated_type_by_name(&name::OK_TYPE) | 458 | self.db.trait_data(trait_).associated_type_by_name(&name![Ok]) |
434 | } | 459 | } |
435 | 460 | ||
436 | fn resolve_ops_neg_output(&self) -> Option<TypeAliasId> { | 461 | fn resolve_ops_neg_output(&self) -> Option<TypeAliasId> { |
437 | let path = known::std_ops_neg(); | 462 | let path = path![std::ops::Neg]; |
438 | let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; | 463 | let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; |
439 | self.db.trait_data(trait_).associated_type_by_name(&name::OUTPUT_TYPE) | 464 | self.db.trait_data(trait_).associated_type_by_name(&name![Output]) |
440 | } | 465 | } |
441 | 466 | ||
442 | fn resolve_ops_not_output(&self) -> Option<TypeAliasId> { | 467 | fn resolve_ops_not_output(&self) -> Option<TypeAliasId> { |
443 | let path = known::std_ops_not(); | 468 | let path = path![std::ops::Not]; |
444 | let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; | 469 | let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; |
445 | self.db.trait_data(trait_).associated_type_by_name(&name::OUTPUT_TYPE) | 470 | self.db.trait_data(trait_).associated_type_by_name(&name![Output]) |
446 | } | 471 | } |
447 | 472 | ||
448 | fn resolve_future_future_output(&self) -> Option<TypeAliasId> { | 473 | fn resolve_future_future_output(&self) -> Option<TypeAliasId> { |
449 | let path = known::std_future_future(); | 474 | let path = path![std::future::Future]; |
450 | let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; | 475 | let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; |
451 | self.db.trait_data(trait_).associated_type_by_name(&name::OUTPUT_TYPE) | 476 | self.db.trait_data(trait_).associated_type_by_name(&name![Output]) |
452 | } | 477 | } |
453 | 478 | ||
454 | fn resolve_boxed_box(&self) -> Option<AdtId> { | 479 | fn resolve_boxed_box(&self) -> Option<AdtId> { |
455 | let path = known::std_boxed_box(); | 480 | let path = path![std::boxed::Box]; |
456 | let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; | 481 | let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; |
457 | Some(struct_.into()) | 482 | Some(struct_.into()) |
458 | } | 483 | } |
459 | 484 | ||
460 | fn resolve_range_full(&self) -> Option<AdtId> { | 485 | fn resolve_range_full(&self) -> Option<AdtId> { |
461 | let path = known::std_ops_range_full(); | 486 | let path = path![std::ops::RangeFull]; |
462 | let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; | 487 | let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; |
463 | Some(struct_.into()) | 488 | Some(struct_.into()) |
464 | } | 489 | } |
465 | 490 | ||
466 | fn resolve_range(&self) -> Option<AdtId> { | 491 | fn resolve_range(&self) -> Option<AdtId> { |
467 | let path = known::std_ops_range(); | 492 | let path = path![std::ops::Range]; |
468 | let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; | 493 | let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; |
469 | Some(struct_.into()) | 494 | Some(struct_.into()) |
470 | } | 495 | } |
471 | 496 | ||
472 | fn resolve_range_inclusive(&self) -> Option<AdtId> { | 497 | fn resolve_range_inclusive(&self) -> Option<AdtId> { |
473 | let path = known::std_ops_range_inclusive(); | 498 | let path = path![std::ops::RangeInclusive]; |
474 | let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; | 499 | let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; |
475 | Some(struct_.into()) | 500 | Some(struct_.into()) |
476 | } | 501 | } |
477 | 502 | ||
478 | fn resolve_range_from(&self) -> Option<AdtId> { | 503 | fn resolve_range_from(&self) -> Option<AdtId> { |
479 | let path = known::std_ops_range_from(); | 504 | let path = path![std::ops::RangeFrom]; |
480 | let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; | 505 | let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; |
481 | Some(struct_.into()) | 506 | Some(struct_.into()) |
482 | } | 507 | } |
483 | 508 | ||
484 | fn resolve_range_to(&self) -> Option<AdtId> { | 509 | fn resolve_range_to(&self) -> Option<AdtId> { |
485 | let path = known::std_ops_range_to(); | 510 | let path = path![std::ops::RangeTo]; |
486 | let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; | 511 | let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; |
487 | Some(struct_.into()) | 512 | Some(struct_.into()) |
488 | } | 513 | } |
489 | 514 | ||
490 | fn resolve_range_to_inclusive(&self) -> Option<AdtId> { | 515 | fn resolve_range_to_inclusive(&self) -> Option<AdtId> { |
491 | let path = known::std_ops_range_to_inclusive(); | 516 | let path = path![std::ops::RangeToInclusive]; |
492 | let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; | 517 | let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; |
493 | Some(struct_.into()) | 518 | Some(struct_.into()) |
494 | } | 519 | } |
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index f8c00a7b4..924ad3e81 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs | |||
@@ -10,7 +10,7 @@ use hir_def::{ | |||
10 | resolver::resolver_for_expr, | 10 | resolver::resolver_for_expr, |
11 | AdtId, ContainerId, Lookup, StructFieldId, | 11 | AdtId, ContainerId, Lookup, StructFieldId, |
12 | }; | 12 | }; |
13 | use hir_expand::name::{self, Name}; | 13 | use hir_expand::name::{name, Name}; |
14 | use ra_syntax::ast::RangeOp; | 14 | use ra_syntax::ast::RangeOp; |
15 | 15 | ||
16 | use crate::{ | 16 | use crate::{ |
@@ -613,6 +613,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
613 | continue; | 613 | continue; |
614 | } | 614 | } |
615 | 615 | ||
616 | let param_ty = self.insert_vars_for_impl_trait(param_ty); | ||
616 | let param_ty = self.normalize_associated_types_in(param_ty); | 617 | let param_ty = self.normalize_associated_types_in(param_ty); |
617 | self.infer_expr_coerce(arg, &Expectation::has_type(param_ty.clone())); | 618 | self.infer_expr_coerce(arg, &Expectation::has_type(param_ty.clone())); |
618 | } | 619 | } |
@@ -631,7 +632,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
631 | // Parent arguments are unknown, except for the receiver type | 632 | // Parent arguments are unknown, except for the receiver type |
632 | if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) { | 633 | if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) { |
633 | for (_id, param) in parent_generics { | 634 | for (_id, param) in parent_generics { |
634 | if param.name == name::SELF_TYPE { | 635 | if param.name == name![Self] { |
635 | substs.push(receiver_ty.clone()); | 636 | substs.push(receiver_ty.clone()); |
636 | } else { | 637 | } else { |
637 | substs.push(Ty::Unknown); | 638 | substs.push(Ty::Unknown); |
diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs index 37db005ea..3bae0ca6c 100644 --- a/crates/ra_hir_ty/src/infer/path.rs +++ b/crates/ra_hir_ty/src/infer/path.rs | |||
@@ -32,21 +32,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
32 | path: &Path, | 32 | path: &Path, |
33 | id: ExprOrPatId, | 33 | id: ExprOrPatId, |
34 | ) -> Option<Ty> { | 34 | ) -> Option<Ty> { |
35 | let (value, self_subst) = if let PathKind::Type(type_ref) = &path.kind { | 35 | let (value, self_subst) = if let PathKind::Type(type_ref) = path.kind() { |
36 | if path.segments.is_empty() { | 36 | if path.segments().is_empty() { |
37 | // This can't actually happen syntax-wise | 37 | // This can't actually happen syntax-wise |
38 | return None; | 38 | return None; |
39 | } | 39 | } |
40 | let ty = self.make_ty(type_ref); | 40 | let ty = self.make_ty(type_ref); |
41 | let remaining_segments_for_ty = &path.segments[..path.segments.len() - 1]; | 41 | let remaining_segments_for_ty = path.segments().take(path.segments().len() - 1); |
42 | 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); |
43 | self.resolve_ty_assoc_item( | 43 | self.resolve_ty_assoc_item( |
44 | ty, | 44 | ty, |
45 | &path.segments.last().expect("path had at least one segment").name, | 45 | &path.segments().last().expect("path had at least one segment").name, |
46 | id, | 46 | id, |
47 | )? | 47 | )? |
48 | } else { | 48 | } else { |
49 | 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())?; |
50 | 50 | ||
51 | match value_or_partial { | 51 | match value_or_partial { |
52 | ResolveValueResult::ValueNs(it) => (it, None), | 52 | ResolveValueResult::ValueNs(it) => (it, None), |
@@ -85,13 +85,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
85 | remaining_index: usize, | 85 | remaining_index: usize, |
86 | id: ExprOrPatId, | 86 | id: ExprOrPatId, |
87 | ) -> Option<(ValueNs, Option<Substs>)> { | 87 | ) -> Option<(ValueNs, Option<Substs>)> { |
88 | assert!(remaining_index < path.segments.len()); | 88 | assert!(remaining_index < path.segments().len()); |
89 | // there may be more intermediate segments between the resolved one and | 89 | // there may be more intermediate segments between the resolved one and |
90 | // 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 |
91 | // 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. |
92 | 92 | ||
93 | let resolved_segment = &path.segments[remaining_index - 1]; | 93 | let resolved_segment = path.segments().get(remaining_index - 1).unwrap(); |
94 | let remaining_segments = &path.segments[remaining_index..]; | 94 | let remaining_segments = path.segments().skip(remaining_index); |
95 | let is_before_last = remaining_segments.len() == 1; | 95 | let is_before_last = remaining_segments.len() == 1; |
96 | 96 | ||
97 | match (def, is_before_last) { | 97 | match (def, is_before_last) { |
@@ -112,7 +112,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
112 | // 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 |
113 | // 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 |
114 | // as Iterator>::Item::default`) | 114 | // as Iterator>::Item::default`) |
115 | 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); | ||
116 | let ty = Ty::from_partly_resolved_hir_path( | 117 | let ty = Ty::from_partly_resolved_hir_path( |
117 | self.db, | 118 | self.db, |
118 | &self.resolver, | 119 | &self.resolver, |
@@ -138,7 +139,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
138 | fn resolve_trait_assoc_item( | 139 | fn resolve_trait_assoc_item( |
139 | &mut self, | 140 | &mut self, |
140 | trait_ref: TraitRef, | 141 | trait_ref: TraitRef, |
141 | segment: &PathSegment, | 142 | segment: PathSegment<'_>, |
142 | id: ExprOrPatId, | 143 | id: ExprOrPatId, |
143 | ) -> Option<(ValueNs, Option<Substs>)> { | 144 | ) -> Option<(ValueNs, Option<Substs>)> { |
144 | let trait_ = trait_ref.trait_; | 145 | let trait_ = trait_ref.trait_; |
@@ -150,7 +151,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
150 | .map(|(_name, id)| (*id).into()) | 151 | .map(|(_name, id)| (*id).into()) |
151 | .find_map(|item| match item { | 152 | .find_map(|item| match item { |
152 | AssocItemId::FunctionId(func) => { | 153 | AssocItemId::FunctionId(func) => { |
153 | if segment.name == self.db.function_data(func).name { | 154 | if segment.name == &self.db.function_data(func).name { |
154 | Some(AssocItemId::FunctionId(func)) | 155 | Some(AssocItemId::FunctionId(func)) |
155 | } else { | 156 | } else { |
156 | None | 157 | None |
@@ -158,7 +159,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
158 | } | 159 | } |
159 | 160 | ||
160 | AssocItemId::ConstId(konst) => { | 161 | AssocItemId::ConstId(konst) => { |
161 | 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) |
162 | { | 163 | { |
163 | Some(AssocItemId::ConstId(konst)) | 164 | Some(AssocItemId::ConstId(konst)) |
164 | } else { | 165 | } else { |
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 5f795bc02..a4ddfc8ef 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs | |||
@@ -11,7 +11,7 @@ use std::sync::Arc; | |||
11 | use hir_def::{ | 11 | use 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, PathKind, PathSegment, PathSegments}, |
15 | resolver::{HasResolver, Resolver, TypeNs}, | 15 | resolver::{HasResolver, Resolver, TypeNs}, |
16 | type_ref::{TypeBound, TypeRef}, | 16 | type_ref::{TypeBound, TypeRef}, |
17 | AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, | 17 | AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, |
@@ -101,13 +101,13 @@ 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 let PathKind::Type(_) = path.kind() { |
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 | }; |
@@ -124,11 +124,11 @@ impl Ty { | |||
124 | db: &impl HirDatabase, | 124 | db: &impl HirDatabase, |
125 | resolver: &Resolver, | 125 | resolver: &Resolver, |
126 | ty: Ty, | 126 | ty: Ty, |
127 | remaining_segments: &[PathSegment], | 127 | remaining_segments: PathSegments<'_>, |
128 | ) -> Ty { | 128 | ) -> Ty { |
129 | if remaining_segments.len() == 1 { | 129 | if remaining_segments.len() == 1 { |
130 | // resolve unselected assoc types | 130 | // resolve unselected assoc types |
131 | let segment = &remaining_segments[0]; | 131 | let segment = remaining_segments.first().unwrap(); |
132 | Ty::select_associated_type(db, resolver, ty, segment) | 132 | Ty::select_associated_type(db, resolver, ty, segment) |
133 | } else if remaining_segments.len() > 1 { | 133 | } else if remaining_segments.len() > 1 { |
134 | // FIXME report error (ambiguous associated type) | 134 | // FIXME report error (ambiguous associated type) |
@@ -142,15 +142,15 @@ impl Ty { | |||
142 | db: &impl HirDatabase, | 142 | db: &impl HirDatabase, |
143 | resolver: &Resolver, | 143 | resolver: &Resolver, |
144 | resolution: TypeNs, | 144 | resolution: TypeNs, |
145 | resolved_segment: &PathSegment, | 145 | resolved_segment: PathSegment<'_>, |
146 | remaining_segments: &[PathSegment], | 146 | remaining_segments: PathSegments<'_>, |
147 | ) -> Ty { | 147 | ) -> Ty { |
148 | let ty = match resolution { | 148 | let ty = match resolution { |
149 | TypeNs::TraitId(trait_) => { | 149 | TypeNs::TraitId(trait_) => { |
150 | let trait_ref = | 150 | let trait_ref = |
151 | TraitRef::from_resolved_path(db, resolver, trait_, resolved_segment, None); | 151 | TraitRef::from_resolved_path(db, resolver, trait_, resolved_segment, None); |
152 | return if remaining_segments.len() == 1 { | 152 | return if remaining_segments.len() == 1 { |
153 | let segment = &remaining_segments[0]; | 153 | let segment = remaining_segments.first().unwrap(); |
154 | let associated_ty = associated_type_by_name_including_super_traits( | 154 | let associated_ty = associated_type_by_name_including_super_traits( |
155 | db, | 155 | db, |
156 | trait_ref.trait_, | 156 | trait_ref.trait_, |
@@ -202,21 +202,21 @@ impl Ty { | |||
202 | 202 | ||
203 | 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 { |
204 | // Resolve the path (in type namespace) | 204 | // Resolve the path (in type namespace) |
205 | if let PathKind::Type(type_ref) = &path.kind { | 205 | if let PathKind::Type(type_ref) = path.kind() { |
206 | let ty = Ty::from_hir(db, resolver, &type_ref); | 206 | let ty = Ty::from_hir(db, resolver, &type_ref); |
207 | let remaining_segments = &path.segments[..]; | 207 | return Ty::from_type_relative_path(db, resolver, ty, path.segments()); |
208 | return Ty::from_type_relative_path(db, resolver, ty, remaining_segments); | ||
209 | } | 208 | } |
210 | let (resolution, remaining_index) = match resolver.resolve_path_in_type_ns(db, path) { | 209 | let (resolution, remaining_index) = |
211 | Some(it) => it, | 210 | match resolver.resolve_path_in_type_ns(db, path.mod_path()) { |
212 | None => return Ty::Unknown, | 211 | Some(it) => it, |
213 | }; | 212 | None => return Ty::Unknown, |
213 | }; | ||
214 | let (resolved_segment, remaining_segments) = match remaining_index { | 214 | let (resolved_segment, remaining_segments) = match remaining_index { |
215 | None => ( | 215 | None => ( |
216 | path.segments.last().expect("resolved path has at least one element"), | 216 | path.segments().last().expect("resolved path has at least one element"), |
217 | &[] as &[PathSegment], | 217 | PathSegments::EMPTY, |
218 | ), | 218 | ), |
219 | Some(i) => (&path.segments[i - 1], &path.segments[i..]), | 219 | Some(i) => (path.segments().get(i - 1).unwrap(), path.segments().skip(i)), |
220 | }; | 220 | }; |
221 | Ty::from_partly_resolved_hir_path( | 221 | Ty::from_partly_resolved_hir_path( |
222 | db, | 222 | db, |
@@ -231,7 +231,7 @@ impl Ty { | |||
231 | db: &impl HirDatabase, | 231 | db: &impl HirDatabase, |
232 | resolver: &Resolver, | 232 | resolver: &Resolver, |
233 | self_ty: Ty, | 233 | self_ty: Ty, |
234 | segment: &PathSegment, | 234 | segment: PathSegment<'_>, |
235 | ) -> Ty { | 235 | ) -> Ty { |
236 | let param_idx = match self_ty { | 236 | let param_idx = match self_ty { |
237 | Ty::Param { idx, .. } => idx, | 237 | Ty::Param { idx, .. } => idx, |
@@ -261,7 +261,7 @@ impl Ty { | |||
261 | fn from_hir_path_inner( | 261 | fn from_hir_path_inner( |
262 | db: &impl HirDatabase, | 262 | db: &impl HirDatabase, |
263 | resolver: &Resolver, | 263 | resolver: &Resolver, |
264 | segment: &PathSegment, | 264 | segment: PathSegment<'_>, |
265 | typable: TyDefId, | 265 | typable: TyDefId, |
266 | ) -> Ty { | 266 | ) -> Ty { |
267 | let generic_def = match typable { | 267 | let generic_def = match typable { |
@@ -284,7 +284,7 @@ impl Ty { | |||
284 | // special-case enum variants | 284 | // special-case enum variants |
285 | resolved: ValueTyDefId, | 285 | resolved: ValueTyDefId, |
286 | ) -> Substs { | 286 | ) -> Substs { |
287 | 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"); |
288 | let (segment, generic_def) = match resolved { | 288 | let (segment, generic_def) = match resolved { |
289 | ValueTyDefId::FunctionId(it) => (last, Some(it.into())), | 289 | ValueTyDefId::FunctionId(it) => (last, Some(it.into())), |
290 | ValueTyDefId::StructId(it) => (last, Some(it.into())), | 290 | ValueTyDefId::StructId(it) => (last, Some(it.into())), |
@@ -296,13 +296,11 @@ impl Ty { | |||
296 | // referring to the variant. So `Option::<T>::None` and | 296 | // referring to the variant. So `Option::<T>::None` and |
297 | // `Option::None::<T>` are both allowed (though the former is | 297 | // `Option::None::<T>` are both allowed (though the former is |
298 | // preferred). See also `def_ids_for_path_segments` in rustc. | 298 | // preferred). See also `def_ids_for_path_segments` in rustc. |
299 | let len = path.segments.len(); | 299 | let len = path.segments().len(); |
300 | 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 }; |
301 | // Option::<T>::None | 301 | let segment = match penultimate { |
302 | &path.segments[len - 2] | 302 | Some(segment) if segment.args_and_bindings.is_some() => segment, |
303 | } else { | 303 | _ => last, |
304 | // Option::None::<T> | ||
305 | last | ||
306 | }; | 304 | }; |
307 | (segment, Some(var.parent.into())) | 305 | (segment, Some(var.parent.into())) |
308 | } | 306 | } |
@@ -314,7 +312,7 @@ impl Ty { | |||
314 | pub(super) fn substs_from_path_segment( | 312 | pub(super) fn substs_from_path_segment( |
315 | db: &impl HirDatabase, | 313 | db: &impl HirDatabase, |
316 | resolver: &Resolver, | 314 | resolver: &Resolver, |
317 | segment: &PathSegment, | 315 | segment: PathSegment<'_>, |
318 | def_generic: Option<GenericDefId>, | 316 | def_generic: Option<GenericDefId>, |
319 | add_self_param: bool, | 317 | add_self_param: bool, |
320 | ) -> Substs { | 318 | ) -> Substs { |
@@ -372,11 +370,11 @@ impl TraitRef { | |||
372 | path: &Path, | 370 | path: &Path, |
373 | explicit_self_ty: Option<Ty>, | 371 | explicit_self_ty: Option<Ty>, |
374 | ) -> Option<Self> { | 372 | ) -> Option<Self> { |
375 | 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())? { |
376 | TypeNs::TraitId(tr) => tr, | 374 | TypeNs::TraitId(tr) => tr, |
377 | _ => return None, | 375 | _ => return None, |
378 | }; | 376 | }; |
379 | 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"); |
380 | 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)) |
381 | } | 379 | } |
382 | 380 | ||
@@ -384,7 +382,7 @@ impl TraitRef { | |||
384 | db: &impl HirDatabase, | 382 | db: &impl HirDatabase, |
385 | resolver: &Resolver, | 383 | resolver: &Resolver, |
386 | resolved: TraitId, | 384 | resolved: TraitId, |
387 | segment: &PathSegment, | 385 | segment: PathSegment<'_>, |
388 | explicit_self_ty: Option<Ty>, | 386 | explicit_self_ty: Option<Ty>, |
389 | ) -> Self { | 387 | ) -> Self { |
390 | let mut substs = TraitRef::substs_from_path(db, resolver, segment, resolved); | 388 | let mut substs = TraitRef::substs_from_path(db, resolver, segment, resolved); |
@@ -410,7 +408,7 @@ impl TraitRef { | |||
410 | fn substs_from_path( | 408 | fn substs_from_path( |
411 | db: &impl HirDatabase, | 409 | db: &impl HirDatabase, |
412 | resolver: &Resolver, | 410 | resolver: &Resolver, |
413 | segment: &PathSegment, | 411 | segment: PathSegment<'_>, |
414 | resolved: TraitId, | 412 | resolved: TraitId, |
415 | ) -> Substs { | 413 | ) -> Substs { |
416 | let has_self_param = | 414 | let has_self_param = |
@@ -464,12 +462,12 @@ fn assoc_type_bindings_from_type_bound<'a>( | |||
464 | trait_ref: TraitRef, | 462 | trait_ref: TraitRef, |
465 | ) -> impl Iterator<Item = GenericPredicate> + 'a { | 463 | ) -> impl Iterator<Item = GenericPredicate> + 'a { |
466 | let last_segment = match bound { | 464 | let last_segment = match bound { |
467 | TypeBound::Path(path) => path.segments.last(), | 465 | TypeBound::Path(path) => path.segments().last(), |
468 | TypeBound::Error => None, | 466 | TypeBound::Error => None, |
469 | }; | 467 | }; |
470 | last_segment | 468 | last_segment |
471 | .into_iter() | 469 | .into_iter() |
472 | .flat_map(|segment| segment.args_and_bindings.iter()) | 470 | .flat_map(|segment| segment.args_and_bindings.into_iter()) |
473 | .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) | 471 | .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) |
474 | .map(move |(name, type_ref)| { | 472 | .map(move |(name, type_ref)| { |
475 | let associated_ty = | 473 | let associated_ty = |
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/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index 6139adb72..802937cb0 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs | |||
@@ -1,7 +1,10 @@ | |||
1 | use super::{infer, type_at, type_at_pos}; | ||
2 | use crate::test_db::TestDB; | ||
3 | use insta::assert_snapshot; | 1 | use insta::assert_snapshot; |
2 | |||
4 | use ra_db::fixture::WithFixture; | 3 | use ra_db::fixture::WithFixture; |
4 | use test_utils::covers; | ||
5 | |||
6 | use super::{infer, infer_with_mismatches, type_at, type_at_pos}; | ||
7 | use crate::test_db::TestDB; | ||
5 | 8 | ||
6 | #[test] | 9 | #[test] |
7 | fn infer_await() { | 10 | fn infer_await() { |
@@ -1486,3 +1489,61 @@ fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> { | |||
1486 | // this is a legitimate cycle | 1489 | // this is a legitimate cycle |
1487 | assert_eq!(t, "{unknown}"); | 1490 | assert_eq!(t, "{unknown}"); |
1488 | } | 1491 | } |
1492 | |||
1493 | #[test] | ||
1494 | fn unify_impl_trait() { | ||
1495 | covers!(insert_vars_for_impl_trait); | ||
1496 | assert_snapshot!( | ||
1497 | infer_with_mismatches(r#" | ||
1498 | trait Trait<T> {} | ||
1499 | |||
1500 | fn foo(x: impl Trait<u32>) { loop {} } | ||
1501 | fn bar<T>(x: impl Trait<T>) -> T { loop {} } | ||
1502 | |||
1503 | struct S<T>(T); | ||
1504 | impl<T> Trait<T> for S<T> {} | ||
1505 | |||
1506 | fn default<T>() -> T { loop {} } | ||
1507 | |||
1508 | fn test() -> impl Trait<i32> { | ||
1509 | let s1 = S(default()); | ||
1510 | foo(s1); | ||
1511 | let x: i32 = bar(S(default())); | ||
1512 | S(default()) | ||
1513 | } | ||
1514 | "#, true), | ||
1515 | @r###" | ||
1516 | [27; 28) 'x': impl Trait<u32> | ||
1517 | [47; 58) '{ loop {} }': () | ||
1518 | [49; 56) 'loop {}': ! | ||
1519 | [54; 56) '{}': () | ||
1520 | [69; 70) 'x': impl Trait<T> | ||
1521 | [92; 103) '{ loop {} }': T | ||
1522 | [94; 101) 'loop {}': ! | ||
1523 | [99; 101) '{}': () | ||
1524 | [172; 183) '{ loop {} }': T | ||
1525 | [174; 181) 'loop {}': ! | ||
1526 | [179; 181) '{}': () | ||
1527 | [214; 310) '{ ...t()) }': S<i32> | ||
1528 | [224; 226) 's1': S<u32> | ||
1529 | [229; 230) 'S': S<u32>(T) -> S<T> | ||
1530 | [229; 241) 'S(default())': S<u32> | ||
1531 | [231; 238) 'default': fn default<u32>() -> T | ||
1532 | [231; 240) 'default()': u32 | ||
1533 | [247; 250) 'foo': fn foo(impl Trait<u32>) -> () | ||
1534 | [247; 254) 'foo(s1)': () | ||
1535 | [251; 253) 's1': S<u32> | ||
1536 | [264; 265) 'x': i32 | ||
1537 | [273; 276) 'bar': fn bar<i32>(impl Trait<T>) -> T | ||
1538 | [273; 290) 'bar(S(...lt()))': i32 | ||
1539 | [277; 278) 'S': S<i32>(T) -> S<T> | ||
1540 | [277; 289) 'S(default())': S<i32> | ||
1541 | [279; 286) 'default': fn default<i32>() -> T | ||
1542 | [279; 288) 'default()': i32 | ||
1543 | [296; 297) 'S': S<i32>(T) -> S<T> | ||
1544 | [296; 308) 'S(default())': S<i32> | ||
1545 | [298; 305) 'default': fn default<i32>() -> T | ||
1546 | [298; 307) 'default()': i32 | ||
1547 | "### | ||
1548 | ); | ||
1549 | } | ||
diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs index 598fd81e3..cd587a338 100644 --- a/crates/ra_hir_ty/src/traits/builtin.rs +++ b/crates/ra_hir_ty/src/traits/builtin.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! This module provides the built-in trait implementations, e.g. to make | 1 | //! This module provides the built-in trait implementations, e.g. to make |
2 | //! closures implement `Fn`. | 2 | //! closures implement `Fn`. |
3 | use hir_def::{expr::Expr, lang_item::LangItemTarget, TraitId, TypeAliasId}; | 3 | use hir_def::{expr::Expr, lang_item::LangItemTarget, TraitId, TypeAliasId}; |
4 | use hir_expand::name; | 4 | use hir_expand::name::name; |
5 | use ra_db::CrateId; | 5 | use ra_db::CrateId; |
6 | 6 | ||
7 | use super::{AssocTyValue, Impl}; | 7 | use super::{AssocTyValue, Impl}; |
@@ -79,7 +79,7 @@ fn closure_fn_trait_impl_datum( | |||
79 | // and don't want to return a valid value only to find out later that FnOnce | 79 | // and don't want to return a valid value only to find out later that FnOnce |
80 | // is broken | 80 | // is broken |
81 | let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; | 81 | let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; |
82 | let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name::OUTPUT_TYPE)?; | 82 | let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?; |
83 | 83 | ||
84 | let num_args: u16 = match &db.body(data.def.into())[data.expr] { | 84 | let num_args: u16 = match &db.body(data.def.into())[data.expr] { |
85 | Expr::Lambda { args, .. } => args.len() as u16, | 85 | Expr::Lambda { args, .. } => args.len() as u16, |
@@ -137,7 +137,7 @@ fn closure_fn_trait_output_assoc_ty_value( | |||
137 | 137 | ||
138 | let output_ty_id = db | 138 | let output_ty_id = db |
139 | .trait_data(fn_once_trait) | 139 | .trait_data(fn_once_trait) |
140 | .associated_type_by_name(&name::OUTPUT_TYPE) | 140 | .associated_type_by_name(&name![Output]) |
141 | .expect("assoc ty value should not exist"); | 141 | .expect("assoc ty value should not exist"); |
142 | 142 | ||
143 | BuiltinImplAssocTyValueData { | 143 | BuiltinImplAssocTyValueData { |
diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs index aeb211a91..29799a8cb 100644 --- a/crates/ra_hir_ty/src/utils.rs +++ b/crates/ra_hir_ty/src/utils.rs | |||
@@ -6,14 +6,13 @@ use hir_def::{ | |||
6 | adt::VariantData, | 6 | adt::VariantData, |
7 | db::DefDatabase, | 7 | db::DefDatabase, |
8 | generics::{GenericParams, TypeParamData}, | 8 | generics::{GenericParams, TypeParamData}, |
9 | path::Path, | ||
9 | resolver::{HasResolver, TypeNs}, | 10 | resolver::{HasResolver, TypeNs}, |
10 | type_ref::TypeRef, | 11 | type_ref::TypeRef, |
11 | ContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId, VariantId, | 12 | ContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId, VariantId, |
12 | }; | 13 | }; |
13 | use hir_expand::name::{self, Name}; | 14 | use hir_expand::name::{name, Name}; |
14 | 15 | ||
15 | // FIXME: this is wrong, b/c it can't express `trait T: PartialEq<()>`. | ||
16 | // We should return a `TraitREf` here. | ||
17 | fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> { | 16 | fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> { |
18 | let resolver = trait_.resolver(db); | 17 | let resolver = trait_.resolver(db); |
19 | // returning the iterator directly doesn't easily work because of | 18 | // returning the iterator directly doesn't easily work because of |
@@ -24,10 +23,10 @@ fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> { | |||
24 | .where_predicates | 23 | .where_predicates |
25 | .iter() | 24 | .iter() |
26 | .filter_map(|pred| match &pred.type_ref { | 25 | .filter_map(|pred| match &pred.type_ref { |
27 | 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(), |
28 | _ => None, | 27 | _ => None, |
29 | }) | 28 | }) |
30 | .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()) { |
31 | Some(TypeNs::TraitId(t)) => Some(t), | 30 | Some(TypeNs::TraitId(t)) => Some(t), |
32 | _ => None, | 31 | _ => None, |
33 | }) | 32 | }) |