-
Notifications
You must be signed in to change notification settings - Fork 90
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 record constructor to subtyping #2007
Conversation
@yannham What I did here is pretty much unify for record rows. It miss TailVar, Constant, etc... |
core/src/typecheck/unif.rs
Outdated
@@ -1599,7 +1599,7 @@ impl Unify for UnifRecordRows { | |||
} | |||
|
|||
#[derive(Clone, Copy, Debug)] | |||
enum RemoveRowError { | |||
pub enum RemoveRowError { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason to make this symbol public? Public means that it's accessible to other crates. I think most of those symbols are specific to nickel-lang-core
, or even to typecheck
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the mod.rs file, rust does not know what is RemoveRowError
. It says it is not accessible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In which file? typecheck/mod.rs
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, because it's a parent of unif
. Then you can use pub(super)
instead of pub
, which is more restricted and doesn't make this a public symbol of nickel-lang-core
. The latter has more consequences, because it means it impacts e.g. semantic versioning (if we change the name of this trait, it's a breaking change). While it stays internal, we can do whatever we want 🙂
The best, if those record rows are coming from destructuring a unif type to begin with, is to keep the original If this type is modified, or generated, or coming from some type inference transformation, you can just use |
The commit
|
The problem about records wasn't real, it was just a simple problem about reporting error correctly. If my fix does work, the work left to do is to :
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a first review, the approach looks good. We can think about how to de-depulicate the code between subsume and unify later on. Maybe the code comments still need to be put at the right place and updated a bit, they've been mostly copy pasted or so it seems.
To de-duplicate the code between |
I'm not sure to understand what you mean here. For example, when subsuming record types, we do the same general work but we still recursively calls P.S: it could be good to have tests for more complicated record types: types with tails, record types with subsumption acting on several components, etc. |
I was talking about cases where we do exactly the same work (with Constant and UnifVar etc...). In those cases, we can call |
…en there is a record/dictionary subsumption)
Co-authored-by: Yann Hamdaoui <yann.hamdaoui@gmail.com>
Co-authored-by: Yann Hamdaoui <yann.hamdaoui@gmail.com>
e55fce5
to
b09a6d6
Compare
Bencher
Click to view all benchmark results
Bencher - Continuous Benchmarking View Public Perf Page Docs | Repo | Chat | Help |
I don't understand why cargo and the continuous integration pipeline give me an error about the lsp. @yannham |
It's because the lsp snapshot tests have changed -- you've changed docs in the stdlib and so the hover text in the lsp is different. Running |
I don't see any change to the stdlib. Also, the diff of the snapshot is dubious - we now get an additional monomorphic type with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks good, but the LSP regression is suspicious.
core/src/typecheck/subtyping.rs
Outdated
//! Type subsumption | ||
/// Type subsumption is generally used when we change from inference mode to checking mode. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
//! Type subsumption | |
/// Type subsumption is generally used when we change from inference mode to checking mode. | |
//! Type subsumption | |
//! | |
/// Type subsumption is generally used when we change from inference mode to checking mode. |
core/src/typecheck/subtyping.rs
Outdated
@@ -0,0 +1,244 @@ | |||
//! Type subsumption | |||
/// Type subsumption is generally used when we change from inference mode to checking mode. | |||
/// Currently, there is one subtyping relations : |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here, and below, you should continue to use //!
instead of ///
, because it's part of the top-level module documentation.
...ts/snapshots/main__lsp__nls__tests__inputs__hover_field_typed_block_regression_1574.ncl.snap
Show resolved
Hide resolved
Co-authored-by: Yann Hamdaoui <yann.hamdaoui@gmail.com>
Co-authored-by: Yann Hamdaoui <yann.hamdaoui@gmail.com>
I'm taking over this PR for the foreseeable future, unless @Eckaos thinks he has the time to bring it down the finish line. |
This commit performs minor cosmetic improvements in the code handling subtyping, mostly around comments and function interfaces.
The support of subtyping for record types makes some types to be instantiated earlier than before. Given the way terms are visited, when writing something like `let f = std.array.map in ..`, `std.array.map` used to be inferred to be of a polymorphic type `forall a b. ...` and then only was instantiated (because record access is inferred, while the bound expression is checked). With the new implementation, it is instantiated as part of the subsumption rule, meaning that it'll appear differently on the LSP. All in all, both version of the data shown by the LSP (before this change and after) are meaningful, in some sense. The polymorphic type is still shown when it's part of the metadata anyway, in addition to the inferred monomorphic type. This also doesn't change which expressions are accepted or not. It's more of an artifact of when we visit terms, before or after instantiation and how those visits are intertwined with `check` and `infer`. It's not easy to revert to the previous state of affairs, and it's in fact not necessarily a good thing either: in the example above, the LSP would also show a polymorphic type for `f` - the one of `map` - while in fact `f` has a monomorphic type, so you couldn't use it in different contexts (say on an `Array Number` and later on a `Array String`). The current version is showing the real monomorphic nature of `f`.
After some thorough investigation, I think I understand what's happening and I convinced myself that it makes sense (although in the test case it adds a bit of noise, it's also more correct in some cases - see the commit message). It an artifact of when we visit the term compared to when the types are instantiated, more or less. |
No description provided.