diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-05-25 15:47:46 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2021-05-25 15:47:46 +0100 |
commit | 3a1369955800752ed3a24f52ed2eb6be7ddf22a4 (patch) | |
tree | 047556acaa4ff4044d2900902810a3555c6eb2c1 | |
parent | 35db5e99f6f982f4257e88d13cbecca250b05efe (diff) | |
parent | 28ca37175572403edeb92324d251fbceb4c2487f (diff) |
Merge #8991
8991: Consider trait to be in scope for trait-impls r=Veykril a=Veykril
Fixes #8912
bors r+
Co-authored-by: Lukas Wirth <[email protected]>
-rw-r--r-- | crates/hir_def/src/resolver.rs | 38 | ||||
-rw-r--r-- | crates/hir_ty/src/infer.rs | 2 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/traits.rs | 30 |
3 files changed, 57 insertions, 13 deletions
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index 0391cc49b..fb8a6f260 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs | |||
@@ -337,22 +337,34 @@ impl Resolver { | |||
337 | pub fn traits_in_scope(&self, db: &dyn DefDatabase) -> FxHashSet<TraitId> { | 337 | pub fn traits_in_scope(&self, db: &dyn DefDatabase) -> FxHashSet<TraitId> { |
338 | let mut traits = FxHashSet::default(); | 338 | let mut traits = FxHashSet::default(); |
339 | for scope in &self.scopes { | 339 | for scope in &self.scopes { |
340 | if let Scope::ModuleScope(m) = scope { | 340 | match scope { |
341 | if let Some(prelude) = m.def_map.prelude() { | 341 | Scope::ModuleScope(m) => { |
342 | let prelude_def_map = prelude.def_map(db); | 342 | if let Some(prelude) = m.def_map.prelude() { |
343 | traits.extend(prelude_def_map[prelude.local_id].scope.traits()); | ||
344 | } | ||
345 | traits.extend(m.def_map[m.module_id].scope.traits()); | ||
346 | |||
347 | // Add all traits that are in scope because of the containing DefMaps | ||
348 | m.def_map.with_ancestor_maps(db, m.module_id, &mut |def_map, module| { | ||
349 | if let Some(prelude) = def_map.prelude() { | ||
350 | let prelude_def_map = prelude.def_map(db); | 343 | let prelude_def_map = prelude.def_map(db); |
351 | traits.extend(prelude_def_map[prelude.local_id].scope.traits()); | 344 | traits.extend(prelude_def_map[prelude.local_id].scope.traits()); |
352 | } | 345 | } |
353 | traits.extend(def_map[module].scope.traits()); | 346 | traits.extend(m.def_map[m.module_id].scope.traits()); |
354 | None::<()> | 347 | |
355 | }); | 348 | // Add all traits that are in scope because of the containing DefMaps |
349 | m.def_map.with_ancestor_maps(db, m.module_id, &mut |def_map, module| { | ||
350 | if let Some(prelude) = def_map.prelude() { | ||
351 | let prelude_def_map = prelude.def_map(db); | ||
352 | traits.extend(prelude_def_map[prelude.local_id].scope.traits()); | ||
353 | } | ||
354 | traits.extend(def_map[module].scope.traits()); | ||
355 | None::<()> | ||
356 | }); | ||
357 | } | ||
358 | &Scope::ImplDefScope(impl_) => { | ||
359 | if let Some(target_trait) = &db.impl_data(impl_).target_trait { | ||
360 | if let Some(TypeNs::TraitId(trait_)) = | ||
361 | self.resolve_path_in_type_ns_fully(db, target_trait.path.mod_path()) | ||
362 | { | ||
363 | traits.insert(trait_); | ||
364 | } | ||
365 | } | ||
366 | } | ||
367 | _ => (), | ||
356 | } | 368 | } |
357 | } | 369 | } |
358 | traits | 370 | traits |
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index edb65622f..164e85050 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs | |||
@@ -578,10 +578,12 @@ impl<'a> InferenceContext<'a> { | |||
578 | } | 578 | } |
579 | 579 | ||
580 | fn resolve_ops_try_ok(&self) -> Option<TypeAliasId> { | 580 | fn resolve_ops_try_ok(&self) -> Option<TypeAliasId> { |
581 | // FIXME resolve via lang_item once try v2 is stable | ||
581 | let path = path![core::ops::Try]; | 582 | let path = path![core::ops::Try]; |
582 | let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?; | 583 | let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?; |
583 | let trait_data = self.db.trait_data(trait_); | 584 | let trait_data = self.db.trait_data(trait_); |
584 | trait_data | 585 | trait_data |
586 | // FIXME remove once try v2 is stable | ||
585 | .associated_type_by_name(&name![Ok]) | 587 | .associated_type_by_name(&name![Ok]) |
586 | .or_else(|| trait_data.associated_type_by_name(&name![Output])) | 588 | .or_else(|| trait_data.associated_type_by_name(&name![Output])) |
587 | } | 589 | } |
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index 6cd8786ea..6ad96bfe3 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs | |||
@@ -3630,3 +3630,33 @@ fn test<F: FnOnce()>(f: F) { | |||
3630 | "#]], | 3630 | "#]], |
3631 | ); | 3631 | ); |
3632 | } | 3632 | } |
3633 | |||
3634 | #[test] | ||
3635 | fn trait_in_scope_of_trait_impl() { | ||
3636 | check_infer( | ||
3637 | r#" | ||
3638 | mod foo { | ||
3639 | pub trait Foo { | ||
3640 | fn foo(self); | ||
3641 | fn bar(self) -> usize { 0 } | ||
3642 | } | ||
3643 | } | ||
3644 | impl foo::Foo for u32 { | ||
3645 | fn foo(self) { | ||
3646 | let _x = self.bar(); | ||
3647 | } | ||
3648 | } | ||
3649 | "#, | ||
3650 | expect![[r#" | ||
3651 | 45..49 'self': Self | ||
3652 | 67..71 'self': Self | ||
3653 | 82..87 '{ 0 }': usize | ||
3654 | 84..85 '0': usize | ||
3655 | 131..135 'self': u32 | ||
3656 | 137..173 '{ ... }': () | ||
3657 | 151..153 '_x': usize | ||
3658 | 156..160 'self': u32 | ||
3659 | 156..166 'self.bar()': usize | ||
3660 | "#]], | ||
3661 | ); | ||
3662 | } | ||