-
Notifications
You must be signed in to change notification settings - Fork 39
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
sigmatch: simpler procedural type matching #647
sigmatch: simpler procedural type matching #647
Conversation
Regarding the effect on overload quality, the only difference is for generic procedural types with an proc call(x: proc(x: int): int {.nimcall.}) = discard
proc generic[T](x: T): auto {.nimcall.} =
result = x
call(generic) # after instantiation, the types match exactly I'm unsure whether this is a good idea or not. |
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.
This is far more sensible than before. 🎉
I made some doc suggestions and possibly discovered a case that needs covering (nkBlockExpr
).
# possible in a concept context. There's nothing to instantiate | ||
return nil | ||
else: | ||
# nothing else is able to provide uninstantiated generic routines |
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.
(just thinking outloud; entirely ignorable)
This isn't a bug, just an observation, sigmatch has an assumption that all name lookups have been complete and we're dealing with symbols only (not counting untyped AST parameter values, but sigmatch just passes those around like opaque values). This is one of those invariants of the module that I'm figuring out how to capture in the long run (entirely outside this PR).
It's not ideal, but I'm not quite sure if +1 generic and exact is either. If it's cumbersome to fix right now I would note it in a comment as an issue and move on. |
a9b1215
to
f027a54
Compare
I have reverted the effects an instantiated The change with
To more properly fix the misuse of |
Summary ======= * simplify the logic for handling generic routines using `auto` as the return types * reject un-instantiated routines earlier when used in branch and array constructor expressions, resulting in clearer error messages (`has no concrete type` instead of `cannot instantiate`) * support lambda expressions coming from template expansions Details ======= Introduced by nim-lang/Nim#3234, when both the formal and actual type are unresolved meta types, the relation is considered to be `isBothMetaConvertible`. The intention seems to have been supporting passing `auto`-returning routines or lambda-expressions to generic procedure-type parameters, but the logic introduced by the aforementioned PR is not necessary for achieving that. `auto` return types now use dedicated handling in `procTypeRel`, both the formal and actual type being unresolved generics results in a mismatch again, and `typeRel` is no longer applied repeatedly for `isBothMetaConvertible` matches. There was also the issue of `generateTypeInstance` being misused, which could result in spurious `cannot instantiate` or internal compiler errors. Since meta types are possibly involved, the correct routine to use is `prepareMetatypeForSigmatch`. Testing that the produced type instance is not a meta type was also done incorrectly (`isMetaType` was used instead of `containsGenericType`). Finally, `nkStmtListExpr` nodes are now considered when instantiating a generic routine as part of parameter matching, which allows for complex expressions yielding un-instantiated generic routines (e.g.: `call((discard x; genericRoutine))`).
* fix typos * rename `genericProcCheck` to `exprNotGenericRoutine`
Block expressions that produce a generic routine are now also supported.
A procedural type that matches exactly after the procedure was instantiated now counts towards exact matches again, instead of towards generic ones.
f027a54
to
fd92bc8
Compare
That should fix the test failures. I had forgotten that the |
No overload resolution is taking place in the tests. In addition, slightly adjust the "return type of formal procedural type inference" case in a way so that it better catches inference failures.
`generateTypeInstance` is not intended to be used when it's not certain that all generic parameters have a concrete type bound -- it's misuse led to spurious instantiation failure errors. It first has to be verified that all used generic parameters resolve to concrete types, which is for now achieved via first calling `prepareMetatypeForSigmatch` and then checking that the produced type is not a generic type.
/merge |
Merge requested by: @saem Contents after the first section break of the PR description has been removed and preserved below:
|
This is a good step forward in making this bit of sem make more sense. |
Summary
auto
as thereturn type
constructor expressions, resulting in clearer error messages
(
has no concrete type
instead ofcannot instantiate
)cannot instantiate
errors when passing generic routinesas arguments to parameters that are also generic
Details
Introduced by nim-lang/Nim#3234, when both the
formal and actual type are unresolved meta types, the relation is
considered to be
isBothMetaConvertible
. The intention seems to havebeen supporting passing
auto
-returning routines or lambda-expressionsto generic procedure-type parameters, but the logic introduced by the
aforementioned PR is not necessary for achieving that.
auto
return types now use dedicated handling inprocTypeRel
, boththe formal and actual type being unresolved generics results in a
mismatch again, and
typeRel
is no longer applied repeatedly forisBothMetaConvertible
matches.There was also the issue of
generateTypeInstance
being misused, whichcould result in spurious
cannot instantiate
or internal compilererrors. Until type instantiation properly supports the case where it's
not certain whether all used generic parameters have been inferred
already, the
tryGenerateInstance
routine is introduced as a temporarysolution.
Finally, both
nkStmtListExpr
andnkBlockExpr
nodes are nowconsidered when instantiating a generic routine as part of parameter
matching, which allows for complex expressions yielding un-instantiated
generic routines (e.g.:
call((discard x; genericRoutine))
).