Skip to content

Commit 98877f8

Browse files
xunilrjIGI-111
andauthored
check if all required generic arguments are valid (#6462)
## Description This PR fixes #6383, #6390 and #6385. ## Checklist - [x] I have linked to any relevant issues. - [x] I have commented my code, particularly in hard-to-understand areas. - [ ] I have updated the documentation where relevant (API docs, the reference, and the Sway book). - [ ] If my change requires substantial documentation changes, I have [requested support from the DevRel team](https://github.com/FuelLabs/devrel-requests/issues/new/choose) - [x] I have added tests that prove my fix is effective or that my feature works. - [x] I have added (or requested a maintainer to add) the necessary `Breaking*` or `New Feature` labels where relevant. - [ ] I have done my best to ensure that my PR adheres to [the Fuel Labs Code Review Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md). - [x] I have requested a review from the relevant team or maintainers. --------- Co-authored-by: IGI-111 <igi-111@protonmail.com>
1 parent 4698d37 commit 98877f8

File tree

6 files changed

+91
-6
lines changed

6 files changed

+91
-6
lines changed

sway-core/src/language/ty/expression/expression.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ impl CollectTypesMetadata for TyExpression {
188188
arguments,
189189
fn_ref,
190190
call_path,
191+
type_binding,
191192
..
192193
} => {
193194
for arg in arguments.iter() {
@@ -196,8 +197,30 @@ impl CollectTypesMetadata for TyExpression {
196197
let function_decl = decl_engine.get_function(fn_ref);
197198

198199
ctx.call_site_push();
199-
for type_parameter in &function_decl.type_parameters {
200-
ctx.call_site_insert(type_parameter.type_id, call_path.span())
200+
for (idx, type_parameter) in function_decl.type_parameters.iter().enumerate() {
201+
ctx.call_site_insert(type_parameter.type_id, call_path.span());
202+
203+
// Verify type arguments are concrete
204+
res.extend(
205+
type_parameter
206+
.type_id
207+
.collect_types_metadata(handler, ctx)?
208+
.into_iter()
209+
// try to use the caller span for better error messages
210+
.map(|x| match x {
211+
TypeMetadata::UnresolvedType(ident, original_span) => {
212+
let span = type_binding
213+
.as_ref()
214+
.and_then(|type_binding| {
215+
type_binding.type_arguments.as_slice().get(idx)
216+
})
217+
.map(|type_argument| Some(type_argument.span.clone()))
218+
.unwrap_or(original_span);
219+
TypeMetadata::UnresolvedType(ident, span)
220+
}
221+
x => x,
222+
}),
223+
);
201224
}
202225

203226
for content in function_decl.body.contents.iter() {

sway-core/src/type_system/id.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,10 @@ impl CollectTypesMetadata for TypeId {
6161
ctx: &mut CollectTypesMetadataContext,
6262
) -> Result<Vec<TypeMetadata>, ErrorEmitted> {
6363
fn filter_fn(type_info: &TypeInfo) -> bool {
64-
matches!(type_info, TypeInfo::UnknownGeneric { .. })
65-
|| matches!(type_info, TypeInfo::Placeholder(_))
64+
matches!(
65+
type_info,
66+
TypeInfo::UnknownGeneric { .. } | TypeInfo::Placeholder(_)
67+
)
6668
}
6769
let engines = ctx.engines;
6870
let possible = self.extract_any_including_self(engines, &filter_fn, vec![], 0);
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,43 @@
11
script;
22

3+
struct S {}
4+
5+
impl S {
6+
fn one_generic<T>(self) { }
7+
fn two_generics<A, B>(self) { }
8+
}
9+
10+
struct W<A> { }
11+
312
fn main() {
413
let g: bool = three_generics(true, "foo", 10);
14+
15+
// Should fail because compiler cannot infer generic argument T
16+
one_generic();
17+
18+
// Should fail because compiler cannot infer generic arguments A, B
19+
two_generics();
20+
21+
// Two generics arguments expected
22+
two_generics::<u64>();
23+
24+
// Should fail because compiler cannot infer generic argument T
25+
S{}.one_generic();
26+
27+
// Should fail because compiler cannot infer generic arguments A, B
28+
S{}.two_generics();
29+
30+
// Two generics arguments expected
31+
S{}.two_generics::<u64>();
32+
33+
// Missing generic argument of W
34+
one_generic::<W>();
535
}
636

737
fn three_generics(a: A, b: B, c: C) -> A {
838
let new_a: A = a;
939
new_a
1040
}
41+
42+
fn one_generic<T>() { }
43+
fn two_generics<A, B>() { }

test/src/e2e_vm_tests/test_programs/should_fail/missing_type_parameters/test.toml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,30 @@ category = "fail"
66
# check: $()Unknown type name "B"
77
# check: $()Could not find symbol "C" in this scope.
88
# check: $()Unknown type name "C"
9+
10+
# check: $()two_generics::<u64>();
11+
# nextln: $()Expected 2 type arguments for "two_generics", but instead found 1.
12+
13+
# check: $()S{}.two_generics::<u64>();
14+
# nextln: $()Expected 2 type arguments for "two_generics", but instead found 1.
15+
16+
# check: $()one_generic()
17+
# nextln: $()Cannot infer type for type parameter "T". Insufficient type information provided. Try annotating its type.
18+
19+
# check: $()two_generics();
20+
# nextln: $()Cannot infer type for type parameter "A". Insufficient type information provided. Try annotating its type.
21+
22+
# check: $()two_generics();
23+
# nextln: $()Cannot infer type for type parameter "B". Insufficient type information provided. Try annotating its type.
24+
25+
# check: $()S{}.one_generic()
26+
# nextln: $()Cannot infer type for type parameter "T". Insufficient type information provided. Try annotating its type.
27+
28+
# check: $()S{}.two_generics();
29+
# nextln: $()Cannot infer type for type parameter "A". Insufficient type information provided. Try annotating its type.
30+
31+
# check: $()S{}.two_generics();
32+
# nextln: $()Cannot infer type for type parameter "B". Insufficient type information provided. Try annotating its type.
33+
34+
# check: $()one_generic::<W>();
35+
# nextln: $()Cannot infer type for type parameter "A". Insufficient type information provided. Try annotating its type.

test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/src/main.sw

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,6 @@ fn test_storage() {
303303
// If these comparisons are done inline just above then it blows out the register allocator due to
304304
// all the ASM blocks.
305305
#[inline(never)]
306-
fn assert_streq<S1, S2>(lhs: S1, rhs: str) {
306+
fn assert_streq<S1>(lhs: S1, rhs: str) {
307307
assert(sha256_str_array(lhs) == sha256(rhs));
308308
}

test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_namespace/src/main.sw

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,6 @@ fn test_storage() {
291291
// If these comparisons are done inline just above then it blows out the register allocator due to
292292
// all the ASM blocks.
293293
#[inline(never)]
294-
fn assert_streq<S1, S2>(lhs: S1, rhs: str) {
294+
fn assert_streq<S1>(lhs: S1, rhs: str) {
295295
assert(sha256_str_array(lhs) == sha256(rhs));
296296
}

0 commit comments

Comments
 (0)