Skip to content

(Towards #3060) reference accesses for intrinsicCall#3125

Open
LonelyCat124 wants to merge 51 commits intomasterfrom
3060_reference_accesses
Open

(Towards #3060) reference accesses for intrinsicCall#3125
LonelyCat124 wants to merge 51 commits intomasterfrom
3060_reference_accesses

Conversation

@LonelyCat124
Copy link
Collaborator

No description provided.

@LonelyCat124 LonelyCat124 changed the title (3060 reference accesses (Closes #3060) reference accesses for intrinsicCall Sep 8, 2025
@LonelyCat124
Copy link
Collaborator Author

Follow-on to #3119

@codecov
Copy link

codecov bot commented Sep 8, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.95%. Comparing base (59f796e) to head (5f2bc4f).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3125      +/-   ##
==========================================
- Coverage   99.95%   99.95%   -0.01%     
==========================================
  Files         380      380              
  Lines       53949    53922      -27     
==========================================
- Hits        53927    53900      -27     
  Misses         22       22              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@LonelyCat124 LonelyCat124 added ready for review Blocked An issue/PR that is blocked by one or more issues/PRs. and removed in progress labels Sep 11, 2025
@LonelyCat124
Copy link
Collaborator Author

@sergisiso I have a first implementation of this now if you want to examine it if you have time. Its currently "blocked" by #3119 (which is in turn dependent on #3110 ) so there's very much no rush on this, especially if I do solve some other issues before we merge 3319.

Copy link
Collaborator

@sergisiso sergisiso left a comment

Choose a reason for hiding this comment

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

@LonelyCat124 See a few more comments, thanks for adding the new test. There is a previous comment that I haven't decided yet but I will come back to it.

Comment on lines 284 to 287
except InternalError:
# The argument here is also used in some other way
# so we do nothing as the other usage has precedence.
pass
Copy link
Collaborator

Choose a reason for hiding this comment

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

I am not a fan of this InternalError, is there any reason that the functions need to guarantee the starting value. Could they not be simply \.change_to_constant() and never raise?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I just copied the structure of the other functions here - I assume its safety to avoid it being called on the wrong things, e.g. if something is written elsewhere we can't change this to be constant as I think some of our other analysis stuff checks for if(any(type_access == CONSTANT)) and this would break a lot of that code.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I have been thinking about these middle methods and they still don't make sense to me.

They not only make things more complicated: adding multiple layers, unexpected behaviours (e.g. fail if there is > 1 READ accesses), internal errors... And fail for simple things that should be handled, e.g. the assignment "g(g(1)) = 1" currently fails.

I believe the implementation would be easier if we just delete them and do a more explicit:
access[the_specific_access_to_update].access_type = the_new_access_type

I created #3300 to test this. The base of that PR is this branch, so if you agree you can click merge to bring the changes here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Merged it in.

@LonelyCat124
Copy link
Collaborator Author

@sergisiso Ready for another look when you have time, think most of the funtionality should be nearly there.

Copy link
Collaborator

@sergisiso sergisiso left a comment

Choose a reason for hiding this comment

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

@LonelyCat124 See inline comments and proposed change

Comment on lines 284 to 287
except InternalError:
# The argument here is also used in some other way
# so we do nothing as the other usage has precedence.
pass
Copy link
Collaborator

Choose a reason for hiding this comment

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

I have been thinking about these middle methods and they still don't make sense to me.

They not only make things more complicated: adding multiple layers, unexpected behaviours (e.g. fail if there is > 1 READ accesses), internal errors... And fail for simple things that should be handled, e.g. the assignment "g(g(1)) = 1" currently fails.

I believe the implementation would be easier if we just delete them and do a more explicit:
access[the_specific_access_to_update].access_type = the_new_access_type

I created #3300 to test this. The base of that PR is this branch, so if you agree you can click merge to bring the changes here.

for ind in write_indices:
if ind < len(node.arguments) and node.argument_names[ind] is None:
arg = node.arguments[ind]
_add_write_argument(arg, reference_accesses)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I resolved the previous converstion because it was getting to long, but I still think it would be better to use the recursion (arg.reference_accesses()) that will properly handle all internal accesses, instead of thinking in each case what can or cannot happen in order to come up with the method implementation. Then all the add mehtods will be the same and can be implemented with a single method doing:

accesses = arg.reference_accesses()
if isinstance(arg, Reference):
   sig, _ = arg.get_signature_and_indices()
   accesses[sig][-1].access_type = access_type

with arg and access_type as a parameter. (note that I am using the setter from the proposed PR in the previous comment)

Or even inlining this expression.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I created a single function to do this and tests seemed ok with it.

reference_accesses = VariablesAccessMap()
# For indices, we only apply them if there is no argument name, othrwise
# it should be handled by the argument names.
for ind in read_indices:
Copy link
Collaborator

@sergisiso sergisiso Jan 26, 2026

Choose a reason for hiding this comment

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

This would make the AccessSequence have a strange order instead of left-to-right arguments. Tbh I don't think there is a "right" order, but it may be neater to start with a:
for ind, arg in enumerate(node.arguments)
and then do each individual:
if ind in read_indices ....
if node.argument_names[ind] in read_named_args ...
to end up with a more sensible order

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.

@LonelyCat124
Copy link
Collaborator Author

@sergisiso Ready for a review when you're back from leave.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants