Namely:
1. Fully evaluate & type-check the label, irrespective of the trace level. So that labels using other variables do not generate "unused identifier" warnings when compiling with different trace mode (and so that the success of a build doesn't depend on the trace level).
This was already done for trace arguments, but not for labels, somehow.
2. Move the requirement for compact trace label being String from errors down to warnings; following point (1), we shouldn't fail compilation for different trace levels. It seems more reasonable to simply raise a warning.
Signed-off-by: KtorZ <matthias.benkort@gmail.com>
Wrongly suggesting args in lexicographical order instead of definition order... The tests were unfortunately only examplifying situations where the fields where also defined in lexicographical order... thus never really showing the issue. It came up in the real world, though. Whoopsie.
Signed-off-by: KtorZ <matthias.benkort@gmail.com>
This is a mildly scaring change, as it may horribly break things down
the line if we have ever relied on that information... However, the
value constructors inside each module are meant to reflect the own
module public API, and shouldn't be populated with Prelude stuff. Not
only does that mean this information is duplicated for all modules
(possibly significantly slowing things down), but it may also cause
weird scoping issues (e.g. one accessing a Prelude's constructor
through some random module).
Hence why I am isolating this change in this single commit, so it's
easier to troubleshoot if that ends up causing weird issues.
Signed-off-by: KtorZ <matthias.benkort@gmail.com>
While the feedback for human users is mostly the same, it does in fact
matter for the LSP since the quickfix will be different depending on
whether we look for a top-level identifier or if we look for a
constructor.
The typical case we see in the stdlib is the `VerificationKey` and
`Script` constructors for `Credential`, often being mixed with
their types counterparts in aiken/crypto!
Signed-off-by: KtorZ <matthias.benkort@gmail.com>
Also, show it actually for UnknownTypeConstructor, and not
UnknownVariable. There's currently an error that wrongly assign an
'UnknownVariable' in place where it should be an
'UnknownTypeConstructor'. Fix coming in the next commit.
Signed-off-by: KtorZ <matthias.benkort@gmail.com>
Fixes:
- Do not allow bench with no arguments; this causes a compiler panic
down the line otherwise.
- Do not force the return value to be a boolean or void. We do not
actually control what's returned by benchmark, so anything really
works here.
Refactor:
- Re-use code between test and bench type-checking; especially the
bits related to gathering information about the via arguments.
There's quite a lot and simply copy-pasting everything will likely
cause issues and discrepency at the first change.
Signed-off-by: KtorZ <5680256+KtorZ@users.noreply.github.com>
* Fix: Deeply nested assignments would offset the new columns count calculation. Now we track relevant columns and their path to ensure each row has wildcards if they don't contain the relevant column
* Add test plus clippy fix
* Clippy fix
* New version clippy fix
Constants are like tiny programs, so they are bound by the same rules
as validators and other programs. In fact, functions are slightly more
flexible in that they allow generic constant expressions like
`List<a>`.
Yet, there is no way to contain such generic structure that contain
inhabitants in a way that satisfies the type-checker. In the example
of `List<a>`, the only inhabitant of that type that we can construct
is the empty list. Anything else would require holding onto some
generic value.
In addition, we can't force literal values into generic annotation, as
something like:
```
const foo: List<a> = [1, 2, 3]
```
wouldn't type-check either since the right-side would unify to
`List<Int>`. And again, the only right-hand side that can type-check
is the empty list without any inhabitant.
The added restriction on generic function is necessary because while
we allow constants to return lambda, we cannot (easily) generate UPLC
that is generic in its argument. By the time we generate UPLC, the
underlying types have to be known.
This is not a "proper" fix as it simply get rid of the warning
altogether (whether you use or not the destructured values).
The reason for removing the warning entirely is because (1) it's
simpler, but more so (2) there's no impact on the final code produced
_anyway_. Redundant let bindings are already removed by the compiler;
and while it's an implicit behaviour that requires a proper warning
when it's coming from a user-defined assignment; here the redundant
assignment is introduced by the compiler to begin with as another
implicit behavior!
So we have an implicit behaviour triggering a warning on another
implicit behaviour. Truth is, there's no impact in having those
parameters destructured and unused. So since users are already not
aware that this results in an implicit let assignment being inserted
in place for them; there's no need for the warning at all.
This is only a start. It compiles, but with a few TODOs left open. In particular, it doesn't currently handle constants depending on other constants or functions; nor does it hoist constants.
Technically, we always need a fallback just because the way the UPLC
is going to work. The last case in the handler pattern matching is
always going to be else ...
We could optimize that away and when the validator is exhaustive, make
the last handler the fallback. Yet, it's really a micro optimization
that saves us one extra if/else. So the sake of getting things
working, we always assume that there's a fallback but, with the extra
condition that when the validator is exhaustive (i.e. there's a
handler covering all purposes), the fallback HAS TO BE the default
fallback (i.e. (_) => fail).
This allows us to gracefully format it out, and also raise an error in
case where there's an extraneous custom fallback.
When there's no type annotation in a validator handler signature, we
provide default annotation to help the type-checker. However, for
spend's datum and mint policy_id, those annotations mustn't be `Data`,
but rather Option<Data> and Bytearray.
Without that, when no annotation are provided, the compiler infer
invalid types and fails with incongruous errors.
This is a little trick which detects record access and replace them
with a simple var. The var itself is the validator handler name,
though since it contains dots, it cannot be referred to by users
explicitly. Yet fundamentally, it is semantically equivalent to just
calling the function by its name.
Note that this commit also removes the weird backdoor for allowing
importing validators in modules starting with `tests`. Allowing
validators handler to be used in importable module requires more work
and is arguably useful; so we will wait until someone complain and
reconsider the proper way to do it.
Without that, we may encounter weird error messages when writing
validators without an explicit `else`. Since we automatically fill it
with a `fail`; without annotation, it unifies to a generic parameter.
The existing check that would look for the body being an error term is
ill-advised as it doesn't work as soon as one adds tracing, or make
the validator a parameterized validator. Plus, it may simply trigger
the wrong behavior as one can now annotate a validator with _whatever_
and get pass the type-checker by plucking a `fail` keyword as body.