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

Fix type update behaviour in expression clones #138

Merged
merged 9 commits into from
Sep 6, 2023

Conversation

mlange05
Copy link
Collaborator

@mlange05 mlange05 commented Sep 1, 2023

Note the problem this PR intends to fix is the underlying problem to the symptoms reported in #128. Many thanks to @rolfhm for providing the MFE that helped triage this.

This PR adds a test and fixes certain corner cases for type updates of symbols via symbol.clone(type-<...>). The key problem is that there were edge-cases where we would preserve existing type info stored in the associated scope of the symbol, if the new type was deemed inadequate. This PR now simplifies this logic and only ignores the incoming type if it is None, as we do not allow None type info in the symbol table (BaseType.DEFERRED signifies unknown types).

In addition, a test was added that pins down the intended behaviour for plain scalar symbols. In the future this could be extended to procedures etc., but this felt overkill for the current problem.

I've also needed to change the scope handling logic in the fparser-based standalone expression parsing utility, where we can never gain type info (no declarations in expressions), but would wipe existing type info by setting it to DEFERRED. We now instead use a dummy to parse expressions and suppress that info in the subsequent rescoping (see inline comments).

This avoids the standalone parse inserting DEFERRED types into the
parent scope, which would override existing type information. Instead
we force the new type info to be ignored when rescoping to the given
scope.
@github-actions
Copy link

github-actions bot commented Sep 1, 2023

Documentation for this branch can be viewed at https://sites.ecmwf.int/docs/loki/138/index.html

Copy link
Collaborator

@reuterbal reuterbal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very nice, many thanks! The fact that the logic in the symbol constructor could be that simple makes the current implementation almost embarrassing.

There are still a few failing tests and I've left a comment on the expression parsing change.

loki/frontend/fparser.py Outdated Show resolved Hide resolved
tests/test_expression.py Outdated Show resolved Hide resolved
We no longer ignore DEFERRED type setters...
This constitutes a small internal behaviour change, as we used to
prefer local type info and thus override existing info in newly
attached scopes.
@codecov
Copy link

codecov bot commented Sep 5, 2023

Codecov Report

Merging #138 (b940ecc) into main (3846c67) will increase coverage by 0.00%.
Report is 6 commits behind head on main.
The diff coverage is 100.00%.

@@           Coverage Diff           @@
##             main     #138   +/-   ##
=======================================
  Coverage   92.10%   92.11%           
=======================================
  Files          89       89           
  Lines       16546    16556   +10     
=======================================
+ Hits        15240    15250   +10     
  Misses       1306     1306           
Flag Coverage Δ
lint_rules 96.13% <ø> (+0.11%) ⬆️
loki 92.04% <100.00%> (-0.01%) ⬇️
transformations 91.68% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files Changed Coverage Δ
loki/expression/symbols.py 95.98% <100.00%> (-0.03%) ⬇️
loki/frontend/fparser.py 92.97% <100.00%> (ø)

... and 2 files with indirect coverage changes

@mlange05
Copy link
Collaborator Author

mlange05 commented Sep 5, 2023

@reuterbal As discussed offline, this branch now includes a small, but subtle behaviour change to get the expression tests back up and running. For this we now treat a Variable.clone(scope=scope) call, where the variable previously had no scope attached, as a re-scope, and prefer the type info in the provided scope over the previously stored DEFERRED type. This requires a small change in the TypeDef.variables property, but once fixed I think this is actually good.

So, please have another look and see if you agree. All other suggestions have been incorporated, let's see if CI can be convinced too.

Copy link
Collaborator

@reuterbal reuterbal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great now, many thanks for figuring this out! The comment in the clone method is a little out of date now (and factually wrong), so might be worth updating this.

@@ -815,16 +819,10 @@ def __new__(cls, **kwargs):
scope = kwargs.get('scope')
_type = kwargs.get('type')

if scope is not None and (_type is None or _type.dtype is BasicType.DEFERRED):
if scope is not None and _type is None:
# Try to determine stored type information if we have no or only deferred type
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment is out of date. Given the complexity, it might be worth expanding this here a little bit in general?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good spot. Should be fixed now. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants