Skip to content

Commit b7d1539

Browse files
authored
fix extract_type_parameters regarding primitive types (#6965)
## Description This PR is part of #5110. It fixes a problem that improves the usability of slices. When a method is returned from the "method resolution algorithm", if any generic is involved, it is returned as its generic form. So for example, if a method `len` is called on `Vec<u8>`, we return something like `fn len(self: Vec<T>)`. Later we monomorphize `T` into `u8`. To do that we run a "pattern match" to realize that we need to replace `T` with `u8`. In this case, the bug was that we were not considering that some primitive types have "implicit type parameters". This was found whilst creating more tests for #6933, because I was not able to call the `len` method defined for slices as: ```sway impl<T> &[T] { pub fn len(self) -> u64 { ... } } ``` ## 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. - [x] 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.
1 parent 597ecfb commit b7d1539

File tree

6 files changed

+49
-8
lines changed

6 files changed

+49
-8
lines changed

sway-core/src/language/ty/declaration/function.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -159,16 +159,15 @@ impl DeclRefFunction {
159159
let matches = type_id_type_parameters
160160
.iter()
161161
.filter(|(_, orig_tp)| {
162-
engines.te().get(orig_tp.type_id).eq(
162+
engines.te().get(*orig_tp).eq(
163163
&*engines.te().get(impl_type_parameter.type_id),
164164
&PartialEqWithEnginesContext::new(engines),
165165
)
166166
})
167167
.collect::<Vec<_>>();
168168
if !matches.is_empty() {
169169
// Adds type substitution for first match only as we can apply only one.
170-
type_id_type_subst_map
171-
.insert(impl_type_parameter.type_id, matches[0].0.type_id);
170+
type_id_type_subst_map.insert(impl_type_parameter.type_id, matches[0].0);
172171
} else if engines
173172
.te()
174173
.get(impl_self_or_trait.implementing_for.initial_type_id)

sway-core/src/type_system/id.rs

+19-5
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,15 @@ impl TypeId {
190190
found
191191
}
192192

193+
/// Returns all pairs of type parameters and its
194+
/// concrete types.
195+
/// This includes primitive types that have "implicit"
196+
/// type parameters such as tuples, arrays and others...
193197
pub(crate) fn extract_type_parameters(
194198
self,
195199
engines: &Engines,
196200
depth: usize,
197-
type_parameters: &mut Vec<(TypeParameter, TypeParameter)>,
201+
type_parameters: &mut Vec<(TypeId, TypeId)>,
198202
orig_type_id: TypeId,
199203
) {
200204
if depth >= EXTRACT_ANY_MAX_DEPTH {
@@ -230,7 +234,7 @@ impl TypeId {
230234
.iter()
231235
.zip(orig_enum_decl.type_parameters.iter())
232236
{
233-
type_parameters.push((type_param.clone(), orig_type_param.clone()));
237+
type_parameters.push((type_param.type_id, orig_type_param.type_id));
234238
type_param.type_id.extract_type_parameters(
235239
engines,
236240
depth + 1,
@@ -251,7 +255,7 @@ impl TypeId {
251255
.iter()
252256
.zip(orig_struct_decl.type_parameters.iter())
253257
{
254-
type_parameters.push((type_param.clone(), orig_type_param.clone()));
258+
type_parameters.push((type_param.type_id, orig_type_param.type_id));
255259
type_param.type_id.extract_type_parameters(
256260
engines,
257261
depth + 1,
@@ -272,7 +276,7 @@ impl TypeId {
272276
.iter()
273277
.zip(orig_enum_decl.type_parameters.iter())
274278
{
275-
type_parameters.push((type_param.clone(), orig_type_param.clone()));
279+
type_parameters.push((type_param.type_id, orig_type_param.type_id));
276280
type_param.type_id.extract_type_parameters(
277281
engines,
278282
depth + 1,
@@ -293,7 +297,7 @@ impl TypeId {
293297
.iter()
294298
.zip(orig_struct_decl.type_parameters.iter())
295299
{
296-
type_parameters.push((type_param.clone(), orig_type_param.clone()));
300+
type_parameters.push((type_param.type_id, orig_type_param.type_id));
297301
type_param.type_id.extract_type_parameters(
298302
engines,
299303
depth + 1,
@@ -302,9 +306,11 @@ impl TypeId {
302306
);
303307
}
304308
}
309+
// Primitive types have "implicit" type parameters
305310
(TypeInfo::Tuple(elems), TypeInfo::Tuple(orig_elems)) => {
306311
assert_eq!(elems.len(), orig_elems.len());
307312
for (elem, orig_elem) in elems.iter().zip(orig_elems.iter()) {
313+
type_parameters.push((elem.type_id, orig_elem.type_id));
308314
elem.type_id.extract_type_parameters(
309315
engines,
310316
depth + 1,
@@ -356,7 +362,9 @@ impl TypeId {
356362
}
357363
}
358364
}
365+
// Primitive types have "implicit" type parameters
359366
(TypeInfo::Array(ty, _), TypeInfo::Array(orig_ty, _)) => {
367+
type_parameters.push((ty.type_id, orig_ty.type_id));
360368
ty.type_id.extract_type_parameters(
361369
engines,
362370
depth + 1,
@@ -376,22 +384,27 @@ impl TypeId {
376384
self.extract_type_parameters(engines, depth + 1, type_parameters, ty.type_id);
377385
}
378386
(TypeInfo::UnknownGeneric { .. }, TypeInfo::UnknownGeneric { .. }) => {}
387+
// Primitive types have "implicit" type parameters
379388
(TypeInfo::Ptr(ty), TypeInfo::Ptr(orig_ty)) => {
389+
type_parameters.push((ty.type_id, orig_ty.type_id));
380390
ty.type_id.extract_type_parameters(
381391
engines,
382392
depth + 1,
383393
type_parameters,
384394
orig_ty.type_id,
385395
);
386396
}
397+
// Primitive types have "implicit" type parameters
387398
(TypeInfo::Slice(ty), TypeInfo::Slice(orig_ty)) => {
399+
type_parameters.push((ty.type_id, orig_ty.type_id));
388400
ty.type_id.extract_type_parameters(
389401
engines,
390402
depth + 1,
391403
type_parameters,
392404
orig_ty.type_id,
393405
);
394406
}
407+
// Primitive types have "implicit" type parameters
395408
(
396409
TypeInfo::Ref {
397410
referenced_type, ..
@@ -401,6 +414,7 @@ impl TypeId {
401414
..
402415
},
403416
) => {
417+
type_parameters.push((referenced_type.type_id, orig_referenced_type.type_id));
404418
referenced_type.type_id.extract_type_parameters(
405419
engines,
406420
depth + 1,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[[package]]
2+
name = "core"
3+
source = "path+from-root-8D9646CA7E6F9448"
4+
5+
[[package]]
6+
name = "method_on_primitives"
7+
source = "member"
8+
dependencies = ["std"]
9+
10+
[[package]]
11+
name = "std"
12+
source = "path+from-root-8D9646CA7E6F9448"
13+
dependencies = ["core"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[project]
2+
authors = ["Fuel Labs <contact@fuel.sh>"]
3+
license = "Apache-2.0"
4+
name = "method_on_primitives"
5+
entry = "main.sw"
6+
7+
[dependencies]
8+
std = { path = "../../../../reduced_std_libs/sway-lib-std-assert" }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
script;
2+
3+
use std::assert::*;
4+
5+
fn main() {
6+
assert(__slice(&[1u8], 0, 1).len() == 1);
7+
}

0 commit comments

Comments
 (0)