Skip to content

Commit 3b55544

Browse files
committed
Import indirect trait impls when handling item use statements.
This updates `TraitMap::filter_by_type_item_import` to scan the trait map for indirect trait impls with generic types matching any of imported item types. This makes sure cases like an impl of a `StorageKey<T>` work, when importing T from a given scope. Fixes #7330
1 parent 9c92977 commit 3b55544

File tree

7 files changed

+113
-0
lines changed

7 files changed

+113
-0
lines changed

sway-core/src/semantic_analysis/namespace/trait_map.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,62 @@ impl TraitMap {
814814
self.filter_by_type_inner(engines, all_types, decider2),
815815
engines,
816816
);
817+
818+
// include indirect trait impls for cases like StorageKey<T>
819+
for key in self.trait_impls.keys() {
820+
for entry in self.trait_impls[key].iter() {
821+
let TraitEntry {
822+
key:
823+
TraitKey {
824+
name: trait_name,
825+
type_id: trait_type_id,
826+
trait_decl_span,
827+
impl_type_parameters,
828+
is_impl_interface_surface,
829+
},
830+
value:
831+
TraitValue {
832+
trait_items,
833+
impl_span,
834+
},
835+
} = entry.inner.as_ref();
836+
837+
let decider3 =
838+
|left: TypeId, right: TypeId| unify_checker_for_item_import.check(right, left);
839+
840+
let matches_generic_params = match *engines.te().get(*trait_type_id) {
841+
TypeInfo::Enum(decl_id) => engines
842+
.de()
843+
.get(&decl_id)
844+
.generic_parameters
845+
.iter()
846+
.any(|gp| gp.unifies(type_id, decider3)),
847+
TypeInfo::Struct(decl_id) => engines
848+
.de()
849+
.get(&decl_id)
850+
.generic_parameters
851+
.iter()
852+
.any(|gp| gp.unifies(type_id, decider3)),
853+
_ => false,
854+
};
855+
856+
if matches_generic_params
857+
|| impl_type_parameters.iter().any(|tp| decider(type_id, *tp))
858+
{
859+
trait_map.insert_inner(
860+
trait_name.clone(),
861+
impl_span.clone(),
862+
trait_decl_span.clone(),
863+
*trait_type_id,
864+
impl_type_parameters.clone(),
865+
trait_items.clone(),
866+
is_impl_interface_surface.clone(),
867+
engines,
868+
);
869+
}
870+
}
871+
}
872+
817873
trait_map
818874
}
819875

sway-core/src/type_system/ast_elements/type_parameter.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,21 @@ impl TypeParameter {
162162

163163
Ok(())
164164
}
165+
166+
pub(crate) fn unifies(
167+
&self,
168+
type_id: TypeId,
169+
decider: impl Fn(TypeId, TypeId) -> bool,
170+
) -> bool {
171+
match self {
172+
TypeParameter::Type(generic_type_parameter) => {
173+
decider(type_id, generic_type_parameter.type_id)
174+
}
175+
TypeParameter::Const(const_generic_parameter) => {
176+
decider(type_id, const_generic_parameter.ty)
177+
}
178+
}
179+
}
165180
}
166181

167182
impl Named for TypeParameter {
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[[package]]
2+
name = "std"
3+
source = "path+from-root-4F829CC0A9DE5C47"
4+
5+
[[package]]
6+
name = "trait_map_use_indirect_impl"
7+
source = "member"
8+
dependencies = ["std"]
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[project]
2+
name = "trait_map_use_indirect_impl"
3+
authors = ["Fuel Labs <contact@fuel.sh>"]
4+
entry = "main.sw"
5+
license = "Apache-2.0"
6+
7+
[dependencies]
8+
std = { path = "../../../../../../sway-lib-std" }
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
library;
2+
3+
pub struct StorageFoobar {}
4+
5+
impl StorageKey<StorageFoobar> {
6+
pub fn foobar(self) {
7+
log("foobar");
8+
}
9+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
contract;
2+
3+
mod foobar;
4+
5+
use foobar::StorageFoobar;
6+
7+
storage {
8+
foo: StorageFoobar = StorageFoobar {},
9+
}
10+
11+
impl Contract {
12+
fn foobar() {
13+
storage.foo.foobar();
14+
}
15+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
category = "compile"
2+
expected_warnings = 0

0 commit comments

Comments
 (0)