Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a Collection type #40

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open

Add a Collection type #40

wants to merge 6 commits into from

Conversation

ruuda
Copy link
Owner

@ruuda ruuda commented Feb 24, 2024

Background

I want to add an unpack operator, so you can write [..xs] instead of [for x in xs: x], possibly to replace the union operator too. But to be able to propagate type expectations into collection literals, I need a way to express “List[T] or Set[T]”.

Solution

Defines a new type, Collection[T]. In the lattice, it is the meet of List[T] and Set[T]. I have a feeling that it will make typechecking the union operator more elegant as well, so maybe we can keep | after all. The new type fits in very naturally to the existing typechecking machinery, which is some evidence that the current iteration of #26 is a good approach.

To do

  • Ensure documentation is up to date.
  • Ensure test coverage.
  • Ensure the fuzzer discovers the new code paths.
  • Check existing error messages and docs for confusing use of the word “collection”.

@ruuda ruuda force-pushed the type-collection branch 2 times, most recently from fe4de0c to 6bb3dde Compare February 24, 2024 12:24
@ruuda ruuda force-pushed the types-static branch 2 times, most recently from 83caec5 to a813982 Compare February 24, 2024 20:54
Base automatically changed from types-static to master February 24, 2024 22:38
@ruuda ruuda force-pushed the type-collection branch from a9dc526 to c3a74f9 Compare March 7, 2024 20:45
@ruuda ruuda mentioned this pull request Mar 24, 2024
4 tasks
@ruuda
Copy link
Owner Author

ruuda commented Apr 22, 2024

#50 has been merged, but this is not entirely obsolete. In some cases the typechecker expects a collection, it needs to handle that. And also, when it extracts an element type from a collection, now it’s no longer sufficient to match on the type, we have to look inside the union for candidates too.

@ruuda ruuda force-pushed the type-collection branch 2 times, most recently from d717a8c to 4398e41 Compare March 15, 2025 17:25
ruuda added 4 commits March 15, 2025 21:13
I want to add an unpack operator, and to be able to type the type
expectation, I need a collection supertype for List and Set. Maybe
once I have this, I can actually type the union operator in a more
elegant way as well and I no longer need unpack. But unpack seems
nice anyway, and a Collection supertype seems nice as well.
It already worked before, but we would only report the mismatch
afterwards, and not blame inside, maybe even insert a runtime check.
Propagating the expecation inside results in better errors and more
efficient code.
At first I wasn't sure if I need to add Collection here, and how to
report an inner mismatch. But now it's clear, the TypeDiff should match
the expected supertype.
It would be nice to have that, but the current implementation is not
incorrect, so let's do the easy thing for now, we can always make it
better later.
@ruuda ruuda force-pushed the type-collection branch from 4398e41 to 340add7 Compare March 15, 2025 20:13
@ruuda
Copy link
Owner Author

ruuda commented Mar 15, 2025

Note to self, previously I wanted to add .. syntax for unpacking, and use it for dicts, lists, and sets. But that creates a complication in the typechecker: is xs a dict or set?

let xs = { ..ys };

That would depend on whether ys is a dict or a set, so what expectation does the typechecker provide when checking ys? We can do Any, or maybe Union[Dict[Any, Any], Collection[Any]], but the former may lead to worse errors and the latter may lead to complex/confusing errors. So instead, we could add two operators: .. for unpacking collections, and ... for unpacking key-value pairs. There is precedent for it, Python also distinguishes between * and ** for unpacking.

// This is a dict, that follows syntactically.
let xs = { ...ys };
// This is a set.
let xs = { ..ys };
// This is of course a list.
let xs = [..ys];
// And this is a syntax error, key-value unpack is only valid in a dict literal.
let xs = [...ys];

Though now that I’m writing this, maybe it is not that hard to just support .. in the typechecker. That would be ideal; I think people would be annoyed by the difference between .. and ... even if it is completely regular and overloading .. is in a sense more complex.

I am not really happy with this, because the type is not really
something that end-users should use (although they can), it's more for
the typechecker internally. How to explain this nicely?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant